From 216efeb39b66126251fbda3e79d5379b9bf227b1 Mon Sep 17 00:00:00 2001 From: craisinlord Date: Thu, 8 Oct 2026 13:54:21 -0500 Subject: [PATCH] portal gun fixes and variants --- .../config/AntarchyConfigCatalog.java | 5 +- .../antarchy/config/AntarchySettings.java | 26 +- .../antarchy/content/block/DuctTapeBlock.java | 385 ------------- .../entity/PortalGunPortalCellAccess.java | 5 +- .../entity/PortalGunPortalFaceRecord.java | 14 +- .../PortalGunPortalMasterBlockEntity.java | 72 +-- .../client/PortalGunClientTransit.java | 90 +++ .../client/PortalGunCrosshairRenderer.java | 94 +++ .../client/PortalGunGrabClientState.java | 20 - .../client/PortalGunRollClientState.java | 77 +-- .../client/PortalGunZoomClientState.java | 14 +- .../client/renderer/ElythiaSkyRenderer.java | 27 +- .../renderer/GlimmeringLivingLayer.java | 2 - .../renderer/PortalGunPortalRenderer.java | 37 +- .../client/renderer/PortalGunPortalRim.java | 178 ++++++ .../PortalGunPortalSceneRenderer.java | 14 +- .../renderer/PortalGunPortalViewRenderer.java | 112 ++-- .../PortalGunPortalVisibilityQueries.java | 1 - .../renderer/PortalGunProjectileRenderer.java | 151 +++-- .../renderer/PortalSceneRenderTrace.java | 91 --- .../client/renderer/PortalStencilTarget.java | 3 +- .../renderer/RoyalIndicatorRenderer.java | 2 - .../content/creative/CreativeTabContents.java | 19 +- .../content/entity/HushProjectileEntity.java | 1 - .../antarchy/content/entity/MantisEntity.java | 2 +- .../content/entity/ant/AntTeleportHelper.java | 43 +- .../entity/basilisk/BasiliskEntity.java | 4 +- .../entity/brutalfly/BrutalflyEntity.java | 4 - .../antarchy/content/item/PortalGunItem.java | 178 ++---- .../content/network/PortalGunGrabPayload.java | 17 - .../network/PortalGunGrabStatePayload.java | 20 - .../network/PortalGunTransitPayload.java | 43 ++ .../portalgun/PortalGunCollisionHelper.java | 26 - .../portalgun/PortalGunGrabManager.java | 280 --------- .../portalgun/PortalGunIndicatorSync.java | 5 - .../portalgun/PortalGunPortalEntity.java | 543 +++++++++--------- .../portalgun/PortalGunPortalRegistry.java | 81 +++ .../portalgun/PortalGunProjectileEntity.java | 38 +- .../content/portalgun/PortalGunSavedData.java | 373 ++---------- .../portalgun/PortalGunTransitHandler.java | 18 + .../portalgun/PortalGunTransitMath.java | 138 +++++ .../content/portalgun/PortalGunVariant.java | 66 +++ .../portalgun/PortalGunWorldPortalShape.java | 13 + .../elythia/KingsTreeGridFeature.java | 116 ++-- .../mixins/PortalGunEntityCollisionMixin.java | 36 +- .../mixins/PortalGunEntityInWallMixin.java | 2 +- .../mixins/PortalGunProjectileHitMixin.java | 22 + .../client/LocalPlayerPortalTransitMixin.java | 37 ++ .../client/MountedVehicleCameraMixin.java | 6 - .../PortalGunEntityTeleportPacketMixin.java | 2 +- .../ScreenEffectRendererPortalMixin.java | 3 +- .../gravity/BubbleColumnGravityMixin.java | 33 ++ .../mixins/gravity/EntityMoveMixin.java | 1 - .../mixins/gravity/ServerEntityAccessor.java | 8 + .../resources/antarchy-common.mixins.json | 4 + .../resources/assets/antarchy/lang/en_us.json | 16 +- .../models/item/portal_gun_atlas_gui.json | 7 + .../models/item/portal_gun_p_body_gui.json | 7 + .../portal_gun/portal_atlas_blue_vortex.png | Bin 0 -> 704 bytes .../portal_gun/portal_atlas_orange_vortex.png | Bin 0 -> 706 bytes .../portal_gun/portal_p_body_blue_vortex.png | Bin 0 -> 705 bytes .../portal_p_body_orange_vortex.png | Bin 0 -> 701 bytes .../gui/portal_gun_atlas_crosshair.png | Bin 0 -> 286 bytes .../textures/gui/portal_gun_crosshair.png | Bin 0 -> 341 bytes .../gui/portal_gun_p_body_crosshair.png | Bin 0 -> 534 bytes .../item/portal_gun/portal_gun_atlas_item.png | Bin 0 -> 415 bytes .../portal_gun/portal_gun_p_body_item.png | Bin 0 -> 416 bytes .../textures/models/item/portal_gun_atlas.png | Bin 0 -> 3046 bytes .../models/item/portal_gun_p_body.png | Bin 0 -> 3050 bytes .../antarchy/textures/vfx/portal_gun_shot.png | Bin 0 -> 648 bytes .../data/antarchy/recipe/portal_gun.json | 27 + .../antarchy/recipe/portal_gun_atlas.json | 19 + .../antarchy/recipe/portal_gun_p_body.json | 19 + .../worldgen/biome/elythia_meadow.json | 4 +- .../biome/fungal_ouranwood_forest.json | 13 +- .../worldgen/biome/ouranwood_forest.json | 2 +- .../worldgen/biome/truffalo_forest.json | 4 +- .../worldgen/structure_set/elythia_rare.json | 4 +- .../enchantment/blast_protection.json | 2 +- .../enchantment/fire_protection.json | 2 +- .../enchantment/projectile_protection.json | 2 +- .../minecraft/enchantment/protection.json | 2 +- .../antarchy/fabric/AntarchyFabricEvents.java | 14 +- .../client/AntarchyFabricClientBootstrap.java | 5 +- .../fabric/client/AntarchyKeyBindings.java | 13 +- .../client/DorrieJumpClientHandler.java | 2 - .../fabric/client/PortalGunClientHandler.java | 7 +- .../client/SeparateLargeItemModels.java | 2 + .../mixin/client/DuctTapeInputMixin.java | 30 - .../client/RenderTargetDepthStencilMixin.java | 28 + .../AntarchyFabricClientNetworking.java | 2 - .../network/AntarchyFabricNetworking.java | 13 +- .../fabric/registry/AntarchyFabricItems.java | 23 +- .../resources/antarchy-fabric.mixins.json | 2 +- .../models/item/portal_gun_atlas.json | 3 + .../models/item/portal_gun_p_body.json | 3 + logs/latest.log | 0 .../AntarchyConfigModuleNeoforge.java | 5 +- .../antarchy/neoforge/AntarchyMiscConfig.java | 15 +- .../neoforge/client/AntarchyKeyBindings.java | 12 - .../client/AntarchyNeoForgeClient.java | 7 + .../client/DuctTapeClientHandler.java | 38 -- .../client/PortalGunClientHandler.java | 5 - .../PortalGunPortalViewRenderHandler.java | 3 - .../neoforge/client/WaspSoundHandler.java | 1 - .../network/AntarchyGravityNetworking.java | 28 +- .../registry/AntarchyNeoForgeEvents.java | 9 +- .../registry/AntarchyNeoforgeItems.java | 23 +- ...Events.java => PortalGunServerEvents.java} | 12 +- .../models/item/portal_gun_atlas.json | 18 + .../models/item/portal_gun_p_body.json | 18 + 111 files changed, 1937 insertions(+), 2136 deletions(-) create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunClientTransit.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunCrosshairRenderer.java delete mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunGrabClientState.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRim.java delete mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalSceneRenderTrace.java delete mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabPayload.java delete mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabStatePayload.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunTransitPayload.java delete mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunGrabManager.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalRegistry.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitHandler.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitMath.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunVariant.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunProjectileHitMixin.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/LocalPlayerPortalTransitMixin.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/BubbleColumnGravityMixin.java create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas_gui.json create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body_gui.json create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_atlas_blue_vortex.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_atlas_orange_vortex.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_p_body_blue_vortex.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_p_body_orange_vortex.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_atlas_crosshair.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_crosshair.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_p_body_crosshair.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/item/portal_gun/portal_gun_atlas_item.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/item/portal_gun/portal_gun_p_body_item.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/models/item/portal_gun_atlas.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/models/item/portal_gun_p_body.png create mode 100644 common-1.21.1/src/main/resources/assets/antarchy/textures/vfx/portal_gun_shot.png create mode 100644 common-1.21.1/src/main/resources/data/antarchy/recipe/portal_gun.json create mode 100644 common-1.21.1/src/main/resources/data/antarchy/recipe/portal_gun_atlas.json create mode 100644 common-1.21.1/src/main/resources/data/antarchy/recipe/portal_gun_p_body.json delete mode 100644 fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/DuctTapeInputMixin.java create mode 100644 fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/RenderTargetDepthStencilMixin.java create mode 100644 fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json create mode 100644 fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json create mode 100644 logs/latest.log delete mode 100644 neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/DuctTapeClientHandler.java rename neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/{PortalGunGrabEvents.java => PortalGunServerEvents.java} (55%) create mode 100644 neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json create mode 100644 neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java index 45def0a3..5289b5d0 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java @@ -143,8 +143,9 @@ public final class AntarchyConfigCatalog { || name.equals("portalGunCanPortalsResizeWhenCreated") || name.equals("portalGunCanPortalProjectilesChunkload") || name.equals("portalGunMaxShootDistance") - || name.equals("portalGunEntityGrabWeightBase") - || name.equals("portalGunIndicatorSize") + || name.equals("portalGunMinFloorExitSpeed") + || name.equals("portalGunMaxLiveViews") + || name.equals("portalGunMaxExitSpeed") || name.equals("hushweedSporeLifetimeSeconds") || name.equals("elythiaFireflyParticlesEnabled") || name.equals("duplicatorTreeEnabled") diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java index b8207c6d..e65a7a0c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java @@ -555,9 +555,10 @@ public final class AntarchySettings { private static boolean portalGunCanPortalProjectilesChunkload = true; private static boolean portalGunSeeThroughPortals = true; private static boolean portalGunFancyPortals = true; - private static int portalGunIndicatorSize = 30; private static int portalGunMaxShootDistance = 10000; - private static int portalGunEntityGrabWeightBase = 100; + private static double portalGunMinFloorExitSpeed = 0.6D; + private static int portalGunMaxLiveViews = 8; + private static double portalGunMaxExitSpeed = 0.0D; private static boolean elythiaFireflyParticlesEnabled = true; private static int bloodCrystalArmorShieldRechargeTicks = 600; private static int bloodCrystalAppleShieldCount = 2; @@ -1335,16 +1336,20 @@ public final class AntarchySettings { portalGunFancyPortals = value; } - public static void setPortalGunIndicatorSize(int value) { - portalGunIndicatorSize = Math.max(0, Math.min(100, value)); - } - public static void setPortalGunMaxShootDistance(int value) { portalGunMaxShootDistance = Math.max(1, value); } - public static void setPortalGunEntityGrabWeightBase(int value) { - portalGunEntityGrabWeightBase = Math.max(0, value); + public static void setPortalGunMaxLiveViews(int value) { + portalGunMaxLiveViews = Math.max(0, Math.min(32, value)); + } + + public static void setPortalGunMinFloorExitSpeed(double value) { + portalGunMinFloorExitSpeed = Math.max(0.0D, Math.min(4.0D, value)); + } + + public static void setPortalGunMaxExitSpeed(double value) { + portalGunMaxExitSpeed = Math.max(0.0D, Math.min(100.0D, value)); } public static boolean permanentPortalsEnabled() { return permanentPortalsEnabled; } @@ -1358,9 +1363,10 @@ public final class AntarchySettings { public static boolean portalGunCanPortalProjectilesChunkload() { return portalGunCanPortalProjectilesChunkload; } public static boolean portalGunSeeThroughPortals() { return portalGunSeeThroughPortals; } public static boolean portalGunFancyPortals() { return portalGunFancyPortals; } - public static int portalGunIndicatorSize() { return portalGunIndicatorSize; } public static int portalGunMaxShootDistance() { return portalGunMaxShootDistance; } - public static int portalGunEntityGrabWeightBase() { return portalGunEntityGrabWeightBase; } + public static double portalGunMinFloorExitSpeed() { return portalGunMinFloorExitSpeed; } + public static int portalGunMaxLiveViews() { return portalGunMaxLiveViews; } + public static double portalGunMaxExitSpeed() { return portalGunMaxExitSpeed; } public static void setBrownAntRequiresReagent(boolean value) { brownAntRequiresReagent = value; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/DuctTapeBlock.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/DuctTapeBlock.java index be7004f4..b3fe5e60 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/DuctTapeBlock.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/DuctTapeBlock.java @@ -6,23 +6,14 @@ import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchyTags; import com.mojang.serialization.MapCodec; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; import net.minecraft.world.ItemInteractionResult; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.DiggerItem; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ShearsItem; -import net.minecraft.world.item.SwordItem; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; @@ -38,9 +29,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; @@ -54,24 +43,6 @@ public class DuctTapeBlock extends Block { public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; private static final int TAPE_HEIGHT = 2; - private static final long STICK_SOUND_COOLDOWN_TICKS = 10L; - private static final long TAPE_DECAY_INTERVAL_TICKS = 30L; - private static final double FLOOR_TRIGGER_HEIGHT = 0.30D; - private static final double WALL_TRIGGER_DEPTH = 0.25D; - private static final double TRIGGER_PAD = 0.12D; - private static final double WALL_Y_PAD = 0.12D; - private static final double WALL_SIDE_PAD = 0.08D; - private static final double WALL_INNER_INSET = 0.03D; - private static final double TRIGGER_INFLATE_DEFAULT = 0.15D; - private static final int SEARCH_INTERVAL_TICKS = 4; - private static final double SEARCH_MOTION_THRESHOLD_SQR = 1.0E-8D; - private static final double SEARCH_PAD_XZ = Math.max(WALL_TRIGGER_DEPTH, TRIGGER_PAD); - private static final double SEARCH_PAD_Y = FLOOR_TRIGGER_HEIGHT; - - private static final Map STICK_SOUND_TIMES = new HashMap<>(); - private static final Map STICK_CONTACT_KEYS = new HashMap<>(); - private static final Map TAPE_DECAY_TIMES = new HashMap<>(); - private static final Map STUCK_ENTITIES = new HashMap<>(); public DuctTapeBlock(BlockBehaviour.Properties properties) { super(properties); @@ -138,14 +109,6 @@ public class DuctTapeBlock extends Block { return state.canSurvive(context.getLevel(), context.getClickedPos()) ? state : null; } - @Override - protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { - if (!state.is(newState.getBlock())) { - releaseEntitiesForTape(level, pos); - } - super.onRemove(state, level, pos, newState, movedByPiston); - } - @Override protected ItemInteractionResult useItemOn( ItemStack stack, @@ -160,14 +123,6 @@ public class DuctTapeBlock extends Block { return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; } - if (isReleaseTool(stack) && (isStuckToTape(player) || isTouchingTape(level, player))) { - if (!level.isClientSide) { - consumeTapeUse(level, pos, state); - level.playSound(null, pos, SoundEvents.WOOL_BREAK, SoundSource.BLOCKS, 0.8F, 0.9F + level.random.nextFloat() * 0.2F); - } - return ItemInteractionResult.sidedSuccess(level.isClientSide); - } - if (!stack.isDamageableItem() || !stack.isDamaged() || stack.is(AntarchyTags.Items.DUCT_TAPE_BLACKLIST)) { return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; } @@ -194,24 +149,6 @@ public class DuctTapeBlock extends Block { return ItemInteractionResult.sidedSuccess(level.isClientSide); } - @Override - protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { - if (level.isClientSide || entity.isSpectator() || !touchesTape(level, entity, pos, state)) { - return; - } - - rememberStuckContact(level, pos, entity); - if (!(entity instanceof ItemEntity)) { - maybeConsumeTapeDecay(level, pos, state); - } - long gameTime = level.getGameTime(); - String tapeKey = tapeKey(level, pos); - if (shouldPlayStickSound(entity.getUUID(), tapeKey, gameTime)) { - level.playSound(null, pos, AntarchySoundEvents.DUCT_TAPE_USE.get(), SoundSource.BLOCKS, 0.85F, 0.9F + level.random.nextFloat() * 0.15F); - } - applyStick(state, pos, entity); - } - @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(USES, FACE, FACING); @@ -244,12 +181,6 @@ public class DuctTapeBlock extends Block { }; } - private static boolean isReleaseTool(ItemStack stack) { - return stack.getItem() instanceof DiggerItem - || stack.getItem() instanceof SwordItem - || stack.getItem() instanceof ShearsItem; - } - private static void consumeTapeUse(Level level, BlockPos pos, BlockState state) { int remainingUses = state.getValue(USES) - 1; if (remainingUses > 0) { @@ -257,322 +188,6 @@ public class DuctTapeBlock extends Block { return; } - releaseEntitiesForTape(level, pos); - TAPE_DECAY_TIMES.remove(tapeDecayKey(level, pos)); level.removeBlock(pos, false); } - - private static void removeTape(Level level, BlockPos pos, BlockState state) { - releaseEntitiesForTape(level, pos); - TAPE_DECAY_TIMES.remove(tapeDecayKey(level, pos)); - level.removeBlock(pos, false); - } - - private static void maybeConsumeTapeDecay(Level level, BlockPos pos, BlockState state) { - long gameTime = level.getGameTime(); - String key = tapeDecayKey(level, pos); - Long lastConsumed = TAPE_DECAY_TIMES.get(key); - if (lastConsumed == null) { - TAPE_DECAY_TIMES.put(key, gameTime); - return; - } - - if (gameTime - lastConsumed < TAPE_DECAY_INTERVAL_TICKS) { - return; - } - - TAPE_DECAY_TIMES.put(key, gameTime); - consumeTapeUse(level, pos, state); - } - - public static void tickStuckEntity(Entity entity) { - if (entity == null || entity.level().isClientSide() || isStickyBlacklist(entity)) { - return; - } - - if (!entity.isAlive() || entity.isRemoved()) { - releaseEntity(entity); - return; - } - - StuckContact contact = STUCK_ENTITIES.get(entity.getUUID()); - if (contact != null && isContactValid(entity.level(), contact)) { - BlockPos pos = BlockPos.of(contact.blockPos()); - BlockState state = entity.level().getBlockState(pos); - applyStick(state, pos, entity); - if (!(entity instanceof ItemEntity)) { - maybeConsumeTapeDecay(entity.level(), pos, state); - } - return; - } - - if (contact != null) { - releaseEntity(entity); - } - - if (!shouldSearchForTape(entity)) { - return; - } - - TapeHit hit = findTouchedTape(entity.level(), entity); - if (hit == null) { - if (entity.isNoGravity()) { - entity.setNoGravity(false); - } - return; - } - - rememberStuckContact(entity.level(), hit.pos(), entity); - applyStick(hit.state(), hit.pos(), entity); - if (!(entity instanceof ItemEntity)) { - maybeConsumeTapeDecay(entity.level(), hit.pos(), hit.state()); - } - } - - public static boolean isStuckToTape(Entity entity) { - if (entity == null || entity.level().isClientSide() || isStickyBlacklist(entity)) { - return false; - } - - StuckContact contact = STUCK_ENTITIES.get(entity.getUUID()); - return contact != null && isContactValid(entity.level(), contact); - } - - public static boolean isTouchingTape(Entity entity) { - return entity != null && isTouchingTape(entity.level(), entity); - } - - public static boolean isTouchingTape(Level level, Entity entity) { - if (isStickyBlacklist(entity)) { - return false; - } - - return findTouchedTape(level, entity) != null; - } - - public static boolean shouldTickStuckEntity(Entity entity) { - if (entity == null || entity.level().isClientSide() || isStickyBlacklist(entity)) { - return false; - } - - if (!entity.isAlive() || entity.isRemoved()) { - return true; - } - - StuckContact contact = STUCK_ENTITIES.get(entity.getUUID()); - if (contact != null) { - return true; - } - - return shouldSearchForTape(entity); - } - - private static boolean isStickyBlacklist(Entity entity) { - return entity != null && entity.getType().is(AntarchyTags.Entities.DUCT_TAPE_STICK_BLACKLIST); - } - - private static void applyStick(BlockState state, BlockPos pos, Entity entity) { - entity.setDeltaMovement(Vec3.ZERO); - entity.resetFallDistance(); - entity.hasImpulse = true; - entity.setNoGravity(true); - - Vec3 anchor = getTapeAnchor(state, pos, entity); - entity.setPos(anchor.x, anchor.y, anchor.z); - - if (state.getValue(FACE) == AttachFace.FLOOR) { - entity.setOnGround(true); - } - } - - private static void rememberStuckContact(Level level, BlockPos pos, Entity entity) { - UUID entityId = entity.getUUID(); - String key = tapeKey(level, pos); - StuckContact existing = STUCK_ENTITIES.get(entityId); - if (existing != null && existing.tapeKey().equals(key)) { - return; - } - - double offsetX = entity.getX() - pos.getX(); - double offsetY = entity.getY() - pos.getY(); - double offsetZ = entity.getZ() - pos.getZ(); - STUCK_ENTITIES.put(entityId, new StuckContact( - key, - level.dimension().location().toString(), - pos.asLong(), - clamp(offsetX, 0.05D, 0.95D), - clamp(offsetY, 0.0D, 0.98D), - clamp(offsetZ, 0.05D, 0.95D) - )); - } - - private static Vec3 getTapeAnchor(BlockState state, BlockPos pos, Entity entity) { - StuckContact contact = STUCK_ENTITIES.get(entity.getUUID()); - double offsetX = contact != null ? contact.offsetX() : 0.5D; - double offsetY = contact != null ? contact.offsetY() : 0.0D; - double offsetZ = contact != null ? contact.offsetZ() : 0.5D; - double wallOffset = entity instanceof Player ? 0.06D : -0.28D; - double centerX = pos.getX() + 0.5D; - double centerZ = pos.getZ() + 0.5D; - - return switch (state.getValue(FACE)) { - case FLOOR -> new Vec3( - pos.getX() + offsetX, - pos.getY() + 0.01D, - pos.getZ() + offsetZ - ); - case WALL -> switch (state.getValue(FACING)) { - case NORTH -> new Vec3(centerX, pos.getY() + offsetY, pos.getZ() - wallOffset); - case SOUTH -> new Vec3(centerX, pos.getY() + offsetY, pos.getZ() + 1.0D + wallOffset); - case EAST -> new Vec3(pos.getX() + 1.0D + wallOffset, pos.getY() + offsetY, centerZ); - case WEST -> new Vec3(pos.getX() - wallOffset, pos.getY() + offsetY, centerZ); - default -> new Vec3(centerX, pos.getY() + offsetY, centerZ); - }; - default -> new Vec3(pos.getX() + offsetX, pos.getY() + 0.01D, pos.getZ() + offsetZ); - }; - } - - private static boolean isContactValid(Level level, StuckContact contact) { - if (!level.dimension().location().toString().equals(contact.dimensionId())) { - return false; - } - - BlockPos pos = BlockPos.of(contact.blockPos()); - BlockState state = level.getBlockState(pos); - return state.getBlock() instanceof DuctTapeBlock - && tapeKey(level, pos).equals(contact.tapeKey()); - } - - private static boolean shouldSearchForTape(Entity entity) { - Vec3 velocity = entity.getDeltaMovement(); - if (velocity.lengthSqr() < SEARCH_MOTION_THRESHOLD_SQR) { - return false; - } - - return (entity.tickCount + entity.getId()) % SEARCH_INTERVAL_TICKS == 0; - } - - private static TapeHit findTouchedTape(Level level, Entity entity) { - AABB box = entity.getBoundingBox().inflate(SEARCH_PAD_XZ, SEARCH_PAD_Y, SEARCH_PAD_XZ); - BlockPos min = BlockPos.containing(box.minX, box.minY, box.minZ); - BlockPos max = BlockPos.containing(box.maxX, box.maxY, box.maxZ); - if (!level.hasChunksAt(min, max)) { - return null; - } - BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos(); - for (int x = min.getX(); x <= max.getX(); x++) { - for (int y = min.getY(); y <= max.getY(); y++) { - for (int z = min.getZ(); z <= max.getZ(); z++) { - cursor.set(x, y, z); - BlockState state = level.getBlockState(cursor); - if (state.isAir()) { - continue; - } - if (state.getBlock() instanceof DuctTapeBlock && touchesTape(level, entity, cursor, state)) { - return new TapeHit(cursor.immutable(), state); - } - } - } - } - return null; - } - - private static boolean touchesTape(Level level, Entity entity, BlockPos pos, BlockState state) { - return entity.getBoundingBox().intersects(getStickyTriggerBounds(state, pos)); - } - - private static AABB getStickyTriggerBounds(BlockState state, BlockPos pos) { - AABB bounds = getShapeFor(state).bounds().move(pos); - return switch (state.getValue(FACE)) { - case FLOOR -> new AABB( - bounds.minX - TRIGGER_PAD, - pos.getY() - 0.02D, - bounds.minZ - TRIGGER_PAD, - bounds.maxX + TRIGGER_PAD, - pos.getY() + FLOOR_TRIGGER_HEIGHT, - bounds.maxZ + TRIGGER_PAD - ); - case WALL -> { - yield switch (state.getValue(FACING)) { - case NORTH -> new AABB(bounds.minX - WALL_SIDE_PAD, bounds.minY - WALL_Y_PAD, bounds.minZ - WALL_TRIGGER_DEPTH, bounds.maxX + WALL_SIDE_PAD, bounds.maxY + WALL_Y_PAD, bounds.maxZ + WALL_INNER_INSET); - case SOUTH -> new AABB(bounds.minX - WALL_SIDE_PAD, bounds.minY - WALL_Y_PAD, bounds.minZ - WALL_INNER_INSET, bounds.maxX + WALL_SIDE_PAD, bounds.maxY + WALL_Y_PAD, bounds.maxZ + WALL_TRIGGER_DEPTH); - case EAST -> new AABB(bounds.minX - WALL_TRIGGER_DEPTH, bounds.minY - WALL_Y_PAD, bounds.minZ - WALL_SIDE_PAD, bounds.maxX + WALL_INNER_INSET, bounds.maxY + WALL_Y_PAD, bounds.maxZ + WALL_SIDE_PAD); - case WEST -> new AABB(bounds.minX - WALL_INNER_INSET, bounds.minY - WALL_Y_PAD, bounds.minZ - WALL_SIDE_PAD, bounds.maxX + WALL_TRIGGER_DEPTH, bounds.maxY + WALL_Y_PAD, bounds.maxZ + WALL_SIDE_PAD); - default -> bounds.inflate(TRIGGER_INFLATE_DEFAULT); - }; - } - default -> bounds.inflate(TRIGGER_INFLATE_DEFAULT); - }; - } - - private static void releaseEntitiesForTape(Level level, BlockPos pos) { - String key = tapeKey(level, pos); - AABB searchBox = AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(pos)).inflate(2.0D); - STUCK_ENTITIES.entrySet().removeIf(entry -> { - StuckContact contact = entry.getValue(); - if (!key.equals(contact.tapeKey())) { - return false; - } - - level.getEntitiesOfClass(Entity.class, searchBox, candidate -> candidate.getUUID().equals(entry.getKey())) - .forEach(candidate -> candidate.setNoGravity(false)); - - STICK_SOUND_TIMES.remove(entry.getKey()); - STICK_CONTACT_KEYS.remove(entry.getKey()); - return true; - }); - } - - private static void releaseEntity(Entity entity) { - if (entity == null) { - return; - } - - STUCK_ENTITIES.remove(entity.getUUID()); - STICK_SOUND_TIMES.remove(entity.getUUID()); - STICK_CONTACT_KEYS.remove(entity.getUUID()); - entity.setNoGravity(false); - } - - private static String tapeDecayKey(Level level, BlockPos pos) { - return level.dimension().location() + ":" + pos.asLong(); - } - - private static String tapeKey(Level level, BlockPos pos) { - return level.dimension().location() + ":" + pos.asLong(); - } - - private static boolean shouldPlayStickSound(UUID entityId, String tapeKey, long gameTime) { - String lastKey = STICK_CONTACT_KEYS.get(entityId); - Long lastContact = STICK_SOUND_TIMES.get(entityId); - if (lastKey == null || !tapeKey.equals(lastKey)) { - STICK_CONTACT_KEYS.put(entityId, tapeKey); - STICK_SOUND_TIMES.put(entityId, gameTime); - return true; - } - - if (lastContact == null || gameTime - lastContact > STICK_SOUND_COOLDOWN_TICKS) { - STICK_SOUND_TIMES.put(entityId, gameTime); - return true; - } - - return false; - } - - private static double clamp(double value, double min, double max) { - return Math.max(min, Math.min(max, value)); - } - - private record StuckContact( - String tapeKey, - String dimensionId, - long blockPos, - double offsetX, - double offsetY, - double offsetZ - ) { - } - - private record TapeHit(BlockPos pos, BlockState state) { - } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalCellAccess.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalCellAccess.java index 14c30c4c..3c1cd9b0 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalCellAccess.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalCellAccess.java @@ -26,8 +26,7 @@ public interface PortalGunPortalCellAccess { default boolean portalGun$putFaceRecord(PortalGunPortalFaceRecord record) { PortalGunPortalFaceRecord existing = this.portalGun$getFaceRecord(record.face()); if (existing != null - && (!existing.ownerId().equals(record.ownerId()) - || !java.util.Objects.equals(existing.channelName(), record.channelName()) + && (!java.util.Objects.equals(existing.gunId(), record.gunId()) || existing.side() != record.side())) { return false; } @@ -63,7 +62,7 @@ public interface PortalGunPortalCellAccess { if (record.ownerId() == null || record.portalId() == null) { continue; } - if (!PortalGunSavedData.isRegistered(level, record.ownerId(), record.gunId(), record.channelName(), record.side(), record.portalId())) { + if (!PortalGunSavedData.isRegistered(level, record.gunId(), record.side(), record.portalId())) { this.portalGun$removeFaceRecord(record.face(), record.portalId()); continue; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalFaceRecord.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalFaceRecord.java index 806568b1..fd336042 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalFaceRecord.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalFaceRecord.java @@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.block.entity; import com.craisinlord.antarchy.content.portalgun.PortalGunPlacement; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; +import com.craisinlord.antarchy.content.portalgun.PortalGunVariant; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -14,9 +15,8 @@ import net.minecraft.nbt.Tag; public record PortalGunPortalFaceRecord( UUID ownerId, - String ownerIdentity, UUID gunId, - String channelName, + PortalGunVariant variant, UUID portalId, UUID linkedPortalId, PortalGunPortalEntity.PortalSide side, @@ -43,21 +43,20 @@ public record PortalGunPortalFaceRecord( } public PortalGunPortalFaceRecord withPair(UUID linkedPortalId, int pairTime) { - return new PortalGunPortalFaceRecord(this.ownerId, this.ownerIdentity, this.gunId, this.channelName, this.portalId, linkedPortalId, this.side, this.face, this.upAxis, this.masterPos, this.basePos, this.portalSpots, this.compensatedSpots, pairTime, this.portalWidth, this.portalHeight, this.master); + return new PortalGunPortalFaceRecord(this.ownerId, this.gunId, this.variant, this.portalId, linkedPortalId, this.side, this.face, this.upAxis, this.masterPos, this.basePos, this.portalSpots, this.compensatedSpots, pairTime, this.portalWidth, this.portalHeight, this.master); } public PortalGunPortalFaceRecord withMaster(boolean master) { - return new PortalGunPortalFaceRecord(this.ownerId, this.ownerIdentity, this.gunId, this.channelName, this.portalId, this.linkedPortalId, this.side, this.face, this.upAxis, this.masterPos, this.basePos, this.portalSpots, this.compensatedSpots, this.pairTime, this.portalWidth, this.portalHeight, master); + return new PortalGunPortalFaceRecord(this.ownerId, this.gunId, this.variant, this.portalId, this.linkedPortalId, this.side, this.face, this.upAxis, this.masterPos, this.basePos, this.portalSpots, this.compensatedSpots, this.pairTime, this.portalWidth, this.portalHeight, master); } public CompoundTag save() { CompoundTag tag = new CompoundTag(); tag.putUUID("OwnerId", this.ownerId); - tag.putString("OwnerIdentity", this.ownerIdentity == null ? "" : this.ownerIdentity); if (this.gunId != null) { tag.putUUID("GunId", this.gunId); } - tag.putString("ChannelName", this.channelName == null ? "" : this.channelName); + tag.putInt("Variant", this.variant.id()); tag.putUUID("PortalId", this.portalId); if (this.linkedPortalId != null) { tag.putUUID("LinkedPortalId", this.linkedPortalId); @@ -105,9 +104,8 @@ public record PortalGunPortalFaceRecord( int height = net.minecraft.util.Mth.clamp(tag.getInt("PortalHeight"), 2, 16); return new PortalGunPortalFaceRecord( tag.getUUID("OwnerId"), - tag.getString("OwnerIdentity"), tag.hasUUID("GunId") ? tag.getUUID("GunId") : null, - tag.getString("ChannelName"), + PortalGunVariant.byId(tag.getInt("Variant")), tag.getUUID("PortalId"), tag.hasUUID("LinkedPortalId") ? tag.getUUID("LinkedPortalId") : null, side, diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalMasterBlockEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalMasterBlockEntity.java index 1b670bda..04fb2dd9 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalMasterBlockEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/entity/PortalGunPortalMasterBlockEntity.java @@ -4,6 +4,7 @@ import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunPlacement; import com.craisinlord.antarchy.content.portalgun.PortalGunSavedData; +import com.craisinlord.antarchy.content.portalgun.PortalGunVariant; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashSet; @@ -35,9 +36,8 @@ import net.minecraft.world.phys.Vec3; public class PortalGunPortalMasterBlockEntity extends BlockEntity implements PortalGunPortalCellAccess { private final Map faceRecords = new EnumMap<>(Direction.class); private UUID ownerId; - private String ownerIdentity; private UUID gunId; - private String channelName; + private PortalGunVariant variant = PortalGunVariant.DEFAULT; private UUID portalId; private PortalGunPortalEntity.PortalSide side = PortalGunPortalEntity.PortalSide.BLUE; private Direction facing = Direction.NORTH; @@ -57,8 +57,7 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por public void configure( UUID ownerId, UUID gunId, - String ownerIdentity, - String channelName, + PortalGunVariant variant, UUID portalId, PortalGunPortalEntity.PortalSide side, Direction facing, @@ -71,9 +70,8 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por int portalHeight ) { this.ownerId = ownerId; - this.ownerIdentity = ownerIdentity; this.gunId = gunId; - this.channelName = channelName; + this.variant = variant == null ? PortalGunVariant.DEFAULT : variant; this.portalId = portalId; this.side = side; this.facing = facing; @@ -84,7 +82,7 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por this.portalHeight = portalHeight; this.compensatedSpots = new HashSet<>(compensatedSpots); this.pairTime = pairTime; - this.portalGun$putFaceRecord(new PortalGunPortalFaceRecord(ownerId, ownerIdentity, gunId, channelName, portalId, this.linkedPortalId, side, facing, upAxis, this.worldPosition, this.basePos, List.of(this.portalSpots), this.compensatedSpots, pairTime, portalWidth, portalHeight, true)); + this.portalGun$putFaceRecord(new PortalGunPortalFaceRecord(ownerId, gunId, this.variant, portalId, this.linkedPortalId, side, facing, upAxis, this.worldPosition, this.basePos, List.of(this.portalSpots), this.compensatedSpots, pairTime, portalWidth, portalHeight, true)); this.setChanged(); } @@ -105,30 +103,8 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por return this.gunId; } - public String getChannelName() { - return this.channelName; - } - - public void adoptGunId(UUID gunId) { - if (this.gunId == null && gunId != null) { - this.gunId = gunId; - this.setChanged(); - } - } - - public void adoptChannelIdentity(UUID gunId, String channelName) { - boolean changed = false; - if (this.gunId == null && gunId != null) { - this.gunId = gunId; - changed = true; - } - if (channelName != null && !channelName.isEmpty() && !channelName.equals(this.channelName)) { - this.channelName = channelName; - changed = true; - } - if (changed) { - this.setChanged(); - } + public PortalGunVariant getVariant() { + return this.variant; } public PortalGunPortalEntity.PortalSide getSide() { @@ -228,12 +204,6 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por level.removeBlock(pos, false); return; } - if (blockEntity.gunId == null && portal.getGunId() != null) { - blockEntity.adoptGunId(portal.getGunId()); - } else if (portal.getGunId() == null && blockEntity.gunId != null) { - portal.adoptGunId(blockEntity.gunId); - } - blockEntity.adoptChannelIdentity(portal.getGunId(), portal.getChannelName()); blockEntity.ensureLinkedPortal(level, portal); UUID linkedPortalId = portal.getLinkedPortalId(); if ((linkedPortalId == null && blockEntity.linkedPortalId != null) @@ -282,7 +252,7 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por if (this.portalId == null || this.ownerId == null) { return null; } - if (!PortalGunSavedData.isRegistered(level, this.ownerId, this.gunId, this.channelName, this.side, this.portalId)) { + if (!PortalGunSavedData.isRegistered(level, this.gunId, this.side, this.portalId)) { return null; } if (level.getEntity(this.portalId) instanceof PortalGunPortalEntity portal && !portal.isRemoved()) { @@ -300,18 +270,18 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por @SuppressWarnings("unchecked") PortalGunPortalEntity restored = new PortalGunPortalEntity((EntityType) rawType, level); restored.setUUID(this.portalId); - restored.configure(this.ownerId, this.gunId, this.ownerIdentity == null ? String.valueOf(this.ownerId) : this.ownerIdentity, this.channelName == null ? String.valueOf(this.gunId) : this.channelName, this.side, placement); + restored.configure(this.ownerId, this.gunId, this.variant, this.side, placement); restored.restorePair(this.linkedPortalId, this.pairTime); Vec3 center = placement.center(); restored.moveTo(center.x, center.y, center.z, placement.yaw(), 0.0F); level.addFreshEntity(restored); - PortalGunSavedData.setPortal(level, this.ownerId, this.gunId, this.channelName, this.side, restored.getUUID()); + PortalGunSavedData.setPortal(level, this.gunId, this.side, restored.getUUID()); return restored; } public static PortalGunPortalEntity restorePortalEntity(ServerLevel level, PortalGunPortalFaceRecord record) { if (record.ownerId() == null || record.portalId() == null - || !PortalGunSavedData.isRegistered(level, record.ownerId(), record.gunId(), record.channelName(), record.side(), record.portalId())) { + || !PortalGunSavedData.isRegistered(level, record.gunId(), record.side(), record.portalId())) { return null; } if (level.getEntity(record.portalId()) instanceof PortalGunPortalEntity portal && !portal.isRemoved()) { @@ -325,13 +295,13 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por @SuppressWarnings("unchecked") PortalGunPortalEntity restored = new PortalGunPortalEntity((EntityType) rawType, level); restored.setUUID(record.portalId()); - restored.configure(record.ownerId(), record.gunId(), record.ownerIdentity(), record.channelName(), record.side(), placement); + restored.configure(record.ownerId(), record.gunId(), record.variant(), record.side(), placement); restored.restorePair(record.linkedPortalId(), record.pairTime()); Vec3 center = placement.center(); restored.moveTo(center.x, center.y, center.z, placement.yaw(), 0.0F); level.addFreshEntity(restored); - PortalGunSavedData.setPortal(level, record.ownerId(), record.gunId(), record.channelName(), record.side(), restored.getUUID()); - PortalGunPortalEntity linked = PortalGunSavedData.findLoadedPortal(level, record.ownerId(), record.gunId(), record.channelName(), record.side() == PortalGunPortalEntity.PortalSide.BLUE ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE); + PortalGunSavedData.setPortal(level, record.gunId(), record.side(), restored.getUUID()); + PortalGunPortalEntity linked = PortalGunSavedData.findLoadedPortal(level, record.gunId(), record.side() == PortalGunPortalEntity.PortalSide.BLUE ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE); if (linked != null && linked != restored && !linked.isRemoved()) { restored.linkTo(linked); linked.linkTo(restored); @@ -345,9 +315,7 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por } PortalGunPortalEntity counterpart = PortalGunSavedData.findLoadedPortal( level, - this.ownerId, this.gunId, - this.channelName, this.side == PortalGunPortalEntity.PortalSide.BLUE ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE ); if (counterpart == null || counterpart == portal || counterpart.isRemoved()) { @@ -365,15 +333,10 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por if (this.ownerId != null) { tag.putUUID("OwnerId", this.ownerId); } - if (this.ownerIdentity != null) { - tag.putString("OwnerIdentity", this.ownerIdentity); - } if (this.gunId != null) { tag.putUUID("GunId", this.gunId); } - if (this.channelName != null) { - tag.putString("ChannelName", this.channelName); - } + tag.putInt("Variant", this.variant.id()); if (this.portalId != null) { tag.putUUID("PortalId", this.portalId); } @@ -414,9 +377,8 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); this.ownerId = tag.hasUUID("OwnerId") ? tag.getUUID("OwnerId") : null; - this.ownerIdentity = tag.contains("OwnerIdentity") ? tag.getString("OwnerIdentity") : String.valueOf(this.ownerId); this.gunId = tag.hasUUID("GunId") ? tag.getUUID("GunId") : null; - this.channelName = tag.contains("ChannelName") ? tag.getString("ChannelName") : this.gunId == null ? "" : "Random Channel #" + this.gunId.hashCode(); + this.variant = PortalGunVariant.byId(tag.getInt("Variant")); this.portalId = tag.hasUUID("PortalId") ? tag.getUUID("PortalId") : null; this.linkedPortalId = tag.hasUUID("LinkedPortalId") ? tag.getUUID("LinkedPortalId") : null; this.side = tag.getInt("Side") == PortalGunPortalEntity.PortalSide.ORANGE.ordinal() ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE; @@ -443,7 +405,7 @@ public class PortalGunPortalMasterBlockEntity extends BlockEntity implements Por this.compensatedSpots = compensatedSpots; this.portalGun$loadFaceRecords(tag); if (this.faceRecords.isEmpty() && this.ownerId != null && this.portalId != null && this.portalSpots.length > 0) { - this.portalGun$putFaceRecord(new PortalGunPortalFaceRecord(this.ownerId, this.ownerIdentity, this.gunId, this.channelName, this.portalId, this.linkedPortalId, this.side, this.facing, this.upAxis, this.worldPosition, this.basePos, List.of(this.portalSpots), this.compensatedSpots, this.pairTime, this.portalWidth, this.portalHeight, true)); + this.portalGun$putFaceRecord(new PortalGunPortalFaceRecord(this.ownerId, this.gunId, this.variant, this.portalId, this.linkedPortalId, this.side, this.facing, this.upAxis, this.worldPosition, this.basePos, List.of(this.portalSpots), this.compensatedSpots, this.pairTime, this.portalWidth, this.portalHeight, true)); } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunClientTransit.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunClientTransit.java new file mode 100644 index 00000000..eb73c736 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunClientTransit.java @@ -0,0 +1,90 @@ +package com.craisinlord.antarchy.content.client; + +import com.craisinlord.antarchy.content.network.PortalGunTransitPayload; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; +import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; +import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil; +import com.craisinlord.antarchy.content.portalgun.PortalGunTransitMath; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public final class PortalGunClientTransit { + private static long cooldownUntil; + + private PortalGunClientTransit() { + } + + public static void afterLocalMove(LocalPlayer player, AABB startBox, Vec3 velocity) { + if (player.level() == null || !player.isAlive() || player.isPassenger() || player.isSpectator()) { + return; + } + long gameTime = player.level().getGameTime(); + if (gameTime < cooldownUntil && cooldownUntil - gameTime <= PortalGunPortalEntity.TELEPORT_COOLDOWN_TICKS) { + return; + } + AABB currentBox = player.getBoundingBox(); + if (velocity.lengthSqr() <= 1.0E-12D && startBox.getCenter().distanceToSqr(currentBox.getCenter()) <= 1.0E-10D) { + return; + } + ClientPacketListener connection = Minecraft.getInstance().getConnection(); + if (connection == null) { + return; + } + Vec3 crossingVelocity = AntarchyGravityApi.isGravityInverted(player) + ? PortalGunTransitMath.entityVelocityToWorld(player, velocity) + : velocity; + for (PortalGunPortalEntity portal : PortalGunPortalEntity.findPortalsNearBounds(player.level(), startBox.minmax(currentBox).expandTowards(crossingVelocity).inflate(1.0D))) { + PortalGunPortalEntity linked = portal.getLinkedPortal(); + if (linked == null || !linked.isAlive()) { + continue; + } + if (portal.resolveCrossing(player, startBox, currentBox, crossingVelocity) == null) { + continue; + } + Vec3 look = player.getLookAngle(); + connection.send(new ServerboundCustomPayloadPacket(new PortalGunTransitPayload( + portal.getId(), PortalGunTransitMath.entityPosition(startBox, player), player.position(), velocity))); + PortalGunPortalEntity.PortalTransit transit = portal.computeTransit(player, linked, currentBox, velocity, look); + Vec3 rollLook = AntarchyGravityApi.isGravityInverted(player) + ? PortalGunTransitMath.entityVelocityToWorld(player, look) + : look; + PortalGunRollClientState.onTransit(portal, linked, rollLook); + apply(player, transit); + cooldownUntil = gameTime + PortalGunPortalEntity.TELEPORT_COOLDOWN_TICKS; + return; + } + } + + private static void apply(LocalPlayer player, PortalGunPortalEntity.PortalTransit transit) { + Vec3 position = transit.position(); + float yaw = PortalGunTransformUtil.yawFromLook(transit.look()); + float pitch = PortalGunTransformUtil.pitchFromLook(transit.look()); + player.setPos(position.x, position.y, position.z); + player.xo = position.x; + player.yo = position.y; + player.zo = position.z; + player.xOld = position.x; + player.yOld = position.y; + player.zOld = position.z; + player.setYRot(yaw); + player.setXRot(pitch); + player.yRotO = yaw; + player.xRotO = pitch; + player.setYHeadRot(yaw); + player.yHeadRotO = yaw; + player.setYBodyRot(yaw); + player.yBodyRotO = yaw; + player.setDeltaMovement(transit.velocity()); + Vec3 fallVelocity = PortalGunTransitMath.entityVelocityToWorld(player, transit.velocity()); + player.fallDistance = PortalGunTransitMath.exitFallDistance(player.fallDistance, fallVelocity, player); + player.setOnGround(false); + player.horizontalCollision = false; + player.verticalCollision = false; + player.verticalCollisionBelow = false; + player.setPortalCooldown(PortalGunPortalEntity.TELEPORT_COOLDOWN_TICKS); + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunCrosshairRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunCrosshairRenderer.java new file mode 100644 index 00000000..5e2662e7 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunCrosshairRenderer.java @@ -0,0 +1,94 @@ +package com.craisinlord.antarchy.content.client; + +import com.craisinlord.antarchy.content.item.PortalGunItem; +import com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload; +import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.EnumSet; +import java.util.Set; +import java.util.UUID; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +public final class PortalGunCrosshairRenderer { + private static final int WIDTH = 34; + private static final int HEIGHT = 33; + private static final int HALF_WIDTH = 17; + private static final float MISSING_BRIGHTNESS = 0.3F; + private static final float MISSING_ALPHA = 0.75F; + private static ClientLevel cachedLevel; + private static long cachedGameTime = Long.MIN_VALUE; + private static UUID cachedGunId; + private static Set cachedPortals = Set.of(); + + private PortalGunCrosshairRenderer() { + } + + public static void render(GuiGraphics guiGraphics) { + Minecraft minecraft = Minecraft.getInstance(); + if (minecraft.player == null || minecraft.level == null || minecraft.screen != null || minecraft.options.hideGui + || !minecraft.options.getCameraType().isFirstPerson()) { + return; + } + ItemStack held = minecraft.player.getMainHandItem(); + if (!(held.getItem() instanceof PortalGunItem)) { + held = minecraft.player.getOffhandItem(); + if (!(held.getItem() instanceof PortalGunItem)) { + return; + } + } + ResourceLocation crosshair = ((PortalGunItem) held.getItem()).getVariant().crosshairTexture(); + UUID gunId = PortalGunItem.getGunId(held); + PortalGunIndicatorClientState.requestIfNeeded(minecraft, gunId); + Set portals = portalsFor(minecraft, gunId); + PortalGunIndicatorPayload serverState = PortalGunIndicatorClientState.get(gunId); + boolean blueAvailable = serverState == null + ? portals.contains(PortalGunPortalEntity.PortalSide.BLUE) + : serverState.blueAvailable(); + boolean orangeAvailable = serverState == null + ? portals.contains(PortalGunPortalEntity.PortalSide.ORANGE) + : serverState.orangeAvailable(); + + int left = (minecraft.getWindow().getGuiScaledWidth() - WIDTH) / 2; + int top = (minecraft.getWindow().getGuiScaledHeight() - HEIGHT) / 2; + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + drawHalf(guiGraphics, crosshair, left + 6, top, 0.0F, blueAvailable); + drawHalf(guiGraphics, crosshair, left + 11, top, HALF_WIDTH, orangeAvailable); + guiGraphics.setColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.disableBlend(); + } + + private static void drawHalf(GuiGraphics guiGraphics, ResourceLocation crosshair, int x, int y, float u, boolean available) { + if (available) { + guiGraphics.setColor(1.0F, 1.0F, 1.0F, 1.0F); + } else { + guiGraphics.setColor(MISSING_BRIGHTNESS, MISSING_BRIGHTNESS, MISSING_BRIGHTNESS, MISSING_ALPHA); + } + guiGraphics.blit(crosshair, x, y, u, 0.0F, HALF_WIDTH, HEIGHT, WIDTH, HEIGHT); + } + + private static Set portalsFor(Minecraft minecraft, UUID gunId) { + if (gunId == null) { + return Set.of(); + } + ClientLevel level = minecraft.level; + long gameTime = level.getGameTime(); + if (cachedLevel != level || cachedGameTime != gameTime || !gunId.equals(cachedGunId)) { + Set portals = EnumSet.noneOf(PortalGunPortalEntity.PortalSide.class); + for (PortalGunPortalEntity portal : com.craisinlord.antarchy.content.portalgun.PortalGunPortalRegistry.all(level)) { + if (portal.isAlive() && gunId.equals(portal.getGunId())) { + portals.add(portal.getPortalSide()); + } + } + cachedLevel = level; + cachedGameTime = gameTime; + cachedGunId = gunId; + cachedPortals = Set.copyOf(portals); + } + return cachedPortals; + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunGrabClientState.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunGrabClientState.java deleted file mode 100644 index f6779c39..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunGrabClientState.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.craisinlord.antarchy.content.client; - -public final class PortalGunGrabClientState { - private static boolean active; - - private PortalGunGrabClientState() { - } - - public static void update(boolean grabActive) { - active = grabActive; - } - - public static boolean isActive() { - return active; - } - - public static void clear() { - active = false; - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunRollClientState.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunRollClientState.java index 7b4c4cdf..fc6a85f7 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunRollClientState.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunRollClientState.java @@ -2,20 +2,14 @@ package com.craisinlord.antarchy.content.client; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; public final class PortalGunRollClientState { private static final double PORTAL_QUERY_RADIUS = 12.0D; - private static final int TELEPORT_COOLDOWN_TICKS = 3; private static final float ROLL_DECAY = 0.85F; private static final float ROLL_EPSILON = 0.05F; - private static final Map TELEPORT_COOLDOWNS = new HashMap<>(); private static float previousRollDegrees; private static float rollDegrees; @@ -34,10 +28,7 @@ public final class PortalGunRollClientState { if (minecraft.level == null || entity == null) { return false; } - for (PortalGunPortalEntity portal : minecraft.level.getEntitiesOfClass( - PortalGunPortalEntity.class, - entity.getBoundingBox().inflate(PORTAL_QUERY_RADIUS), - Entity::isAlive)) { + for (PortalGunPortalEntity portal : com.craisinlord.antarchy.content.portalgun.PortalGunPortalRegistry.near(minecraft.level, entity.getBoundingBox().inflate(PORTAL_QUERY_RADIUS))) { if (portal.intersectsEntityBounds(entity)) { return true; } @@ -53,7 +44,6 @@ public final class PortalGunRollClientState { public static void clear() { previousRollDegrees = 0.0F; rollDegrees = 0.0F; - TELEPORT_COOLDOWNS.clear(); } public static void tick(Minecraft minecraft) { @@ -61,74 +51,17 @@ public final class PortalGunRollClientState { clear(); return; } - Entity cameraEntity = minecraft.getCameraEntity(); - if (cameraEntity == null) { - return; - } previousRollDegrees = rollDegrees; rollDegrees *= ROLL_DECAY; if (Math.abs(rollDegrees) < ROLL_EPSILON) { rollDegrees = 0.0F; } - long gameTime = minecraft.level.getGameTime(); - TELEPORT_COOLDOWNS.entrySet().removeIf(entry -> entry.getValue() <= gameTime); - for (PortalGunPortalEntity portal : minecraft.level.getEntitiesOfClass( - PortalGunPortalEntity.class, - cameraEntity.getBoundingBox().inflate(PORTAL_QUERY_RADIUS), - Entity::isAlive)) { - PortalGunPortalEntity linkedPortal = portal.getLinkedPortal(); - if (linkedPortal == null || !linkedPortal.isAlive()) { - continue; - } - if (!portal.shouldRenderFront(cameraEntity.position())) { - continue; - } - if (!canTeleport(cameraEntity, gameTime)) { - continue; - } - AABB currentBox = cameraEntity.getBoundingBox(); - AABB previousBox = currentBox.move(cameraEntity.xo - cameraEntity.getX(), cameraEntity.yo - cameraEntity.getY(), cameraEntity.zo - cameraEntity.getZ()); - PortalGunPortalEntity.PortalCrossing crossing = portal.resolveCrossing(cameraEntity, previousBox, currentBox); - if (crossing == null) { - continue; - } - applyPredictedTeleport(cameraEntity, portal, linkedPortal, crossing, gameTime); - break; - } } - private static boolean canTeleport(Entity entity, long gameTime) { - if (!entity.isAlive() || entity instanceof PortalGunPortalEntity || entity.isPassenger() || entity.isVehicle()) { - return false; - } - long cooldownUntil = TELEPORT_COOLDOWNS.getOrDefault(entity.getUUID(), 0L); - return cooldownUntil <= gameTime; - } - - private static void applyPredictedTeleport(Entity entity, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, PortalGunPortalEntity.PortalCrossing crossing, long gameTime) { - Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, entity.getLookAngle()).normalize(); - Vec3 transformedUp = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, PortalGunTransformUtil.upVectorFromLookAndRoll(entity.getLookAngle(), rollDegrees)).normalize(); - Vec3 resolvedMovement = entity.position().subtract(entity.xo, entity.yo, entity.zo); - PortalGunPortalEntity.PortalTransitTransform transit = sourcePortal.previewTransit(entity, destinationPortal, crossing, resolvedMovement); - Vec3 transformedMotion = transit.movement(); - transformedMotion = clampPortalMotion(transformedMotion); + public static void onTransit(PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 look) { + Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, look).normalize(); + Vec3 transformedUp = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, PortalGunTransformUtil.upVectorFromLookAndRoll(look, rollDegrees)).normalize(); rollDegrees = PortalGunTransformUtil.rollFromOrientation(transformedLook, transformedUp); - Vec3 exitPos = transit.exitPosition(); - entity.teleportTo(exitPos.x, exitPos.y, exitPos.z); - entity.setDeltaMovement(transformedMotion); - float verticalMotion = (float) transformedMotion.y; - entity.fallDistance = 0.1F * (verticalMotion / -0.1F * verticalMotion / -0.1F); - entity.setYRot(PortalGunTransformUtil.yawFromLook(transformedLook)); - entity.setXRot(PortalGunTransformUtil.pitchFromLook(transformedLook)); - entity.setPortalCooldown(TELEPORT_COOLDOWN_TICKS); - TELEPORT_COOLDOWNS.put(entity.getUUID(), gameTime + TELEPORT_COOLDOWN_TICKS); - } - - private static Vec3 clampPortalMotion(Vec3 motion) { - return new Vec3(clampPortalMotionComponent(motion.x), clampPortalMotionComponent(motion.y), clampPortalMotionComponent(motion.z)); - } - - private static double clampPortalMotionComponent(double motion) { - return Math.abs(motion) > 0.99D ? motion / (Math.abs(motion) + 0.001D) : motion; + previousRollDegrees = rollDegrees; } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunZoomClientState.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunZoomClientState.java index faf14641..87b4f53d 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunZoomClientState.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/PortalGunZoomClientState.java @@ -6,6 +6,7 @@ import net.minecraft.client.Options; import net.minecraft.world.item.ItemStack; public final class PortalGunZoomClientState { + private static final int MAX_PROGRESS = 5; private static int progress; private static boolean zooming; private static Double originalSensitivity; @@ -34,7 +35,7 @@ public final class PortalGunZoomClientState { zooming = false; } - progress = Math.max(0, Math.min(5, progress + (zooming ? 1 : -1))); + progress = Math.max(0, Math.min(MAX_PROGRESS, progress + (zooming ? 1 : -1))); if (originalSensitivity != null) { if (progress == 0) { restoreSensitivity(minecraft.options); @@ -47,7 +48,13 @@ public final class PortalGunZoomClientState { restoreSensitivity(options); return fov; } - double easedProgress = zooming ? progress - 1.0D + partialTick : progress + 1.0D - partialTick; + double tickProgress = Math.max(0.0D, Math.min(1.0D, partialTick)); + double easedProgress = progress == MAX_PROGRESS + ? MAX_PROGRESS + : zooming + ? progress - 1.0D + tickProgress + : progress + 1.0D - tickProgress; + easedProgress = Math.max(0.0D, Math.min(MAX_PROGRESS, easedProgress)); double zoomFactor = zoomFactor(easedProgress); if (originalSensitivity != null) { options.sensitivity().set(originalSensitivity * zoomFactor); @@ -56,7 +63,8 @@ public final class PortalGunZoomClientState { } private static double zoomFactor(double progress) { - return 0.1D + 0.9D * (1.0D - Math.sin(Math.toRadians(90.0D * Math.max(0.0D, Math.min(1.0D, progress / 5.0D))))); + double normalizedProgress = Math.max(0.0D, Math.min(1.0D, progress / MAX_PROGRESS)); + return 0.1D + 0.9D * (1.0D - Math.sin(Math.toRadians(90.0D * normalizedProgress))); } private static double zoomFactor(int progress) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/ElythiaSkyRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/ElythiaSkyRenderer.java index 51673580..1dec4295 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/ElythiaSkyRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/ElythiaSkyRenderer.java @@ -72,7 +72,7 @@ public final class ElythiaSkyRenderer { float blue = (float) skyColor.z; float rainLevel = level.getRainLevel(partialTick); float starBrightness = level.getStarBrightness(partialTick) * (1.0F - rainLevel); - float timeOfDay = level.getTimeOfDay(partialTick); + double timeDegrees = (level.getDayTime() + partialTick) * (360.0D / 24000.0D); // Blend in a dark purple when it's night (starBrightness > 0) float nightPurpleR = 0.055F; @@ -90,7 +90,7 @@ public final class ElythiaSkyRenderer { RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); renderSunrise(poseStack, projectionMatrix, level, partialTick, rainLevel); - renderCelestialBodies(poseStack.last().pose(), projectionMatrix, timeOfDay, rainLevel); + renderCelestialBodies(poseStack.last().pose(), projectionMatrix, timeDegrees, rainLevel); if (starBrightness > 0.1F) { if (coloredStarBuffer == null) { @@ -210,28 +210,31 @@ public final class ElythiaSkyRenderer { RenderSystem.disableBlend(); } - private static void renderCelestialBodies(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, float timeOfDay, float rainLevel) { - float t = timeOfDay * 360.0F; + private static void renderCelestialBodies(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, double timeDegrees, float rainLevel) { // Purple sun - float sun1Orbit = t; + float sun1Orbit = orbitAngle(timeDegrees, 1.0D, 0.0D); renderBodyGlow(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 0xD06BFF, rainLevel, 70.0F); - renderTexturedBody(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 38.0F, 0xD06BFF, 1.0F, SUN_TEXTURE, false, 0, t * 0.8F); + renderTexturedBody(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 38.0F, 0xD06BFF, 1.0F, SUN_TEXTURE, false, 0, orbitAngle(timeDegrees, 0.8D, 0.0D)); // Orange sub - float sun2Orbit = t * 0.73F + 54.0F; + float sun2Orbit = orbitAngle(timeDegrees, 0.73D, 54.0D); renderBodyGlow(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 0xFF9A33, rainLevel, 70.0F); - renderTexturedBody(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 16.0F, 0xFF9A33, 1.0F, SUN_TEXTURE, false, 0, -t * 0.5F); + renderTexturedBody(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 16.0F, 0xFF9A33, 1.0F, SUN_TEXTURE, false, 0, orbitAngle(timeDegrees, -0.5D, 0.0D)); // Dark green moon - float moon2Orbit = t * 1.27F + 228.0F; + float moon2Orbit = orbitAngle(timeDegrees, 1.27D, 228.0D); renderBodyGlow(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 0x4FD84D, rainLevel, 78.0F); - renderTexturedBody(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 14.0F, 0x4FD84D, 1.0F, MOON_TEXTURE, true, 1, t * 0.3F); + renderTexturedBody(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 14.0F, 0x4FD84D, 1.0F, MOON_TEXTURE, true, 1, orbitAngle(timeDegrees, 0.3D, 0.0D)); // Light green moon - float moon3Orbit = t * 0.38F + 122.0F; + float moon3Orbit = orbitAngle(timeDegrees, 0.38D, 122.0D); renderBodyGlow(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 0xA3FF8F, rainLevel, 78.0F); - renderTexturedBody(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 12.0F, 0xA3FF8F, 1.0F, MOON_TEXTURE, true, 2, -t * 0.6F); + renderTexturedBody(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 12.0F, 0xA3FF8F, 1.0F, MOON_TEXTURE, true, 2, orbitAngle(timeDegrees, -0.6D, 0.0D)); + } + + private static float orbitAngle(double timeDegrees, double speed, double offset) { + return (float) ((timeDegrees * speed + offset) % 360.0D); } private static void renderBodyGlow( diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/GlimmeringLivingLayer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/GlimmeringLivingLayer.java index 97aa44d7..b58c934c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/GlimmeringLivingLayer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/GlimmeringLivingLayer.java @@ -15,8 +15,6 @@ import net.minecraft.world.effect.MobEffect; import net.minecraft.world.entity.LivingEntity; public final class GlimmeringLivingLayer> extends RenderLayer { - // High-alpha, luminance-preserving tint drawn straight over the skin (no scale-up) so it - // reads as the body itself recolored spirit-blue rather than a separate ghost shell. private static final int GLIMMERING_TINT = 0x4266CCFF; public GlimmeringLivingLayer(RenderLayerParent renderer) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRenderer.java index 07603ae1..bd654eda 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRenderer.java @@ -41,25 +41,25 @@ public class PortalGunPortalRenderer extends GeoEntityRenderer> 16 & 0xFF : 255; + int green = channelTint ? color >> 8 & 0xFF : 255; + int blue = channelTint ? color & 0xFF : 255; + int alpha = channelTint ? PortalGunPortalRim.ENTITY_ALPHA : 210; consumer.addVertex(pose, (float) position.x, (float) position.y, (float) position.z) .setColor(red, green, blue, alpha) .setUv(u, v) diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRim.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRim.java new file mode 100644 index 00000000..92f03e25 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalRim.java @@ -0,0 +1,178 @@ +package com.craisinlord.antarchy.content.client.renderer; + +import com.craisinlord.antarchy.Antarchy; +import com.craisinlord.antarchy.content.item.PortalGunItem; +import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.MeshData; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.blaze3d.vertex.VertexSorting; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4f; +import org.joml.Matrix4fStack; +import org.lwjgl.opengl.GL11; + +public final class PortalGunPortalRim { + public static final float EXTRA_WIDTH = 0.0F; + public static final float EXTRA_HEIGHT = 0.0F; + public static final int ENTITY_ALPHA = 150; + private static final double OVERLAY_OFFSET = 0.05D; + private static final int HIDDEN_RIM_ALPHA = 170; + private static final ResourceLocation BLUE_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_portal_blue.png"); + private static final ResourceLocation ORANGE_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_portal_orange.png"); + + private PortalGunPortalRim() { + } + + public static ResourceLocation texture(PortalGunPortalEntity portal) { + return portal.getPortalSide() == PortalGunPortalEntity.PortalSide.BLUE ? BLUE_TEXTURE : ORANGE_TEXTURE; + } + + static void drawOverView(PortalGunPortalEntity portal, Vec3 cameraPos, Matrix4f viewMatrix, Matrix4f projectionMatrix, float partialTick) { + withCameraMatrices(viewMatrix, projectionMatrix, () -> { + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.defaultBlendFunc(); + drawRims(List.of(portal), cameraPos, partialTick, ENTITY_ALPHA); + }); + } + + static void drawHiddenOutlines(Minecraft minecraft, Vec3 cameraPos, Matrix4f viewMatrix, Matrix4f projectionMatrix, float partialTick) { + if (minecraft.level == null || minecraft.player == null) { + return; + } + List ownedPortals = collectOwnedPortals(minecraft); + if (ownedPortals.isEmpty()) { + return; + } + withCameraMatrices(viewMatrix, projectionMatrix, () -> { + RenderSystem.enableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.depthFunc(GL11.GL_GREATER); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); + drawRims(ownedPortals, cameraPos, partialTick, HIDDEN_RIM_ALPHA); + }); + } + + private static void withCameraMatrices(Matrix4f viewMatrix, Matrix4f projectionMatrix, Runnable draw) { + Matrix4fStack modelViewStack = RenderSystem.getModelViewStack(); + Matrix4f previousProjection = new Matrix4f(RenderSystem.getProjectionMatrix()); + VertexSorting previousSorting = RenderSystem.getVertexSorting(); + modelViewStack.pushMatrix(); + try { + modelViewStack.set(viewMatrix); + RenderSystem.applyModelViewMatrix(); + RenderSystem.setProjectionMatrix(new Matrix4f(projectionMatrix), VertexSorting.DISTANCE_TO_ORIGIN); + RenderSystem.setShader(GameRenderer::getPositionTexColorShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.disableCull(); + RenderSystem.enableBlend(); + draw.run(); + } finally { + RenderSystem.depthFunc(GL11.GL_LEQUAL); + RenderSystem.enableDepthTest(); + RenderSystem.depthMask(true); + RenderSystem.defaultBlendFunc(); + RenderSystem.disableBlend(); + RenderSystem.enableCull(); + RenderSystem.setProjectionMatrix(previousProjection, previousSorting); + modelViewStack.popMatrix(); + RenderSystem.applyModelViewMatrix(); + } + } + + private static List collectOwnedPortals(Minecraft minecraft) { + Set owners = new HashSet<>(); + Player player = minecraft.player; + owners.add(player.getUUID()); + addGunOwner(owners, player.getMainHandItem(), player.getUUID()); + addGunOwner(owners, player.getOffhandItem(), player.getUUID()); + List portals = new ArrayList<>(); + for (PortalGunPortalEntity portal : com.craisinlord.antarchy.content.portalgun.PortalGunPortalRegistry.all(minecraft.level)) { + if (portal.isAlive() && owners.contains(portal.getOwnerId())) { + portals.add(portal); + } + } + return portals; + } + + private static void addGunOwner(Set owners, ItemStack stack, UUID fallback) { + if (stack.getItem() instanceof PortalGunItem) { + UUID owner = PortalGunItem.getPortalOwnerId(stack, fallback); + if (owner != null) { + owners.add(owner); + } + } + } + + private static void drawRims(List portals, Vec3 cameraPos, float partialTick, int alpha) { + drawRimsWithTexture(portals, cameraPos, partialTick, alpha, BLUE_TEXTURE, PortalGunPortalEntity.PortalSide.BLUE); + drawRimsWithTexture(portals, cameraPos, partialTick, alpha, ORANGE_TEXTURE, PortalGunPortalEntity.PortalSide.ORANGE); + } + + private static void drawRimsWithTexture(List portals, Vec3 cameraPos, float partialTick, int alpha, + ResourceLocation texture, PortalGunPortalEntity.PortalSide side) { + BufferBuilder buffer = null; + for (PortalGunPortalEntity portal : portals) { + if (portal.getPortalSide() != side) { + continue; + } + if (buffer == null) { + buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + } + addRim(buffer, portal, cameraPos, partialTick, alpha); + } + if (buffer == null) { + return; + } + MeshData mesh = buffer.build(); + if (mesh == null) { + return; + } + RenderSystem.setShaderTexture(0, texture); + BufferUploader.drawWithShader(mesh); + } + + private static void addRim(BufferBuilder buffer, PortalGunPortalEntity portal, Vec3 cameraPos, float partialTick, int alpha) { + float scale = portal.getPortalVisualScale(partialTick); + if (scale <= 0.0F) { + return; + } + Vec3 right = portal.getWidthVec().normalize(); + Vec3 up = portal.getUpVec().normalize(); + Vec3 center = portal.position().add(portal.getNormalVec().normalize().scale(OVERLAY_OFFSET)).subtract(cameraPos); + double halfWidth = (portal.getPortalWidth() * 0.5D + EXTRA_WIDTH) * scale; + double halfHeight = (portal.getPortalHeight() * 0.5D + EXTRA_HEIGHT) * scale; + int color = portal.getPortalColor(); + int red = color >> 16 & 0xFF; + int green = color >> 8 & 0xFF; + int blue = color & 0xFF; + addVertex(buffer, center, right, up, -halfWidth, -halfHeight, 0.0F, 1.0F, red, green, blue, alpha); + addVertex(buffer, center, right, up, -halfWidth, halfHeight, 0.0F, 0.0F, red, green, blue, alpha); + addVertex(buffer, center, right, up, halfWidth, halfHeight, 1.0F, 0.0F, red, green, blue, alpha); + addVertex(buffer, center, right, up, halfWidth, -halfHeight, 1.0F, 1.0F, red, green, blue, alpha); + } + + private static void addVertex(BufferBuilder buffer, Vec3 center, Vec3 right, Vec3 up, double horizontal, double vertical, + float u, float v, int red, int green, int blue, int alpha) { + Vec3 position = center.add(right.scale(horizontal)).add(up.scale(vertical)); + buffer.addVertex((float) position.x, (float) position.y, (float) position.z) + .setUv(u, v) + .setColor(red, green, blue, alpha); + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java index da8fbbb8..c7210f43 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java @@ -53,7 +53,7 @@ public final class PortalGunPortalSceneRenderer { public static void render(Minecraft minecraft, Camera camera, float partialTick, Matrix4f viewMatrix, Matrix4f projection, Matrix4f skyProjection, Frustum frustum, - PortalTerrain terrain, Consumer crossingEntities, String tracePair) { + PortalTerrain terrain, Consumer crossingEntities) { LevelRenderer renderer = minecraft.levelRenderer; LevelRendererPortalViewAreaAccessor state = (LevelRendererPortalViewAreaAccessor) renderer; LevelRendererPortalSceneInvoker scene = (LevelRendererPortalSceneInvoker) renderer; @@ -82,7 +82,7 @@ public final class PortalGunPortalSceneRenderer { boolean foggy = minecraft.level.effects().isFoggyAt(cameraBlockPos.getX(), cameraBlockPos.getY()) || minecraft.gui.getBossOverlay().shouldCreateWorldFog(); - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "background-and-sky", "sections=" + terrain.sectionCount())) { + { RenderSystem.setShaderGameTime(minecraft.level.getGameTime(), partialTick); minecraft.getBlockEntityRenderDispatcher().prepare(minecraft.level, camera, minecraft.hitResult); minecraft.getEntityRenderDispatcher().prepare(minecraft.level, camera, minecraft.crosshairPickEntity); @@ -99,7 +99,7 @@ public final class PortalGunPortalSceneRenderer { RenderSystem.setProjectionMatrix(projection, VertexSorting.DISTANCE_TO_ORIGIN); FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_TERRAIN, Math.max(renderDistance, 32.0F), foggy, partialTick); - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "opaque-terrain", "sections=" + terrain.sectionCount())) { + { RenderSystem.enableDepthTest(); RenderSystem.depthMask(true); terrain.drawLayer(minecraft, RenderType.solid(), cameraPosition, viewMatrix, projection); @@ -118,7 +118,7 @@ public final class PortalGunPortalSceneRenderer { PoseStack poseStack = new PoseStack(); MultiBufferSource.BufferSource buffers = bufferSource(); try { - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "entities", "rendering")) { + { for (Entity entity : minecraft.level.entitiesForRendering()) { if (!minecraft.getEntityRenderDispatcher().shouldRender(entity, frustum, cameraX, cameraY, cameraZ) && !entity.hasIndirectPassenger(minecraft.player)) { @@ -138,20 +138,20 @@ public final class PortalGunPortalSceneRenderer { } buffers.endBatch(); - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "block-entities", "rendering")) { + { terrain.forEachBlockEntity(minecraft, frustum, blockEntity -> renderBlockEntity(minecraft, blockEntity, cameraX, cameraY, cameraZ, partialTick, poseStack, buffers)); } buffers.endBatch(); - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "translucent-and-particles", "rendering")) { + { terrain.drawLayer(minecraft, RenderType.translucent(), cameraPosition, viewMatrix, projection); buffers.endBatch(); terrain.drawLayer(minecraft, RenderType.tripwire(), cameraPosition, viewMatrix, projection); minecraft.particleEngine.render(minecraft.gameRenderer.lightTexture(), camera, partialTick); } - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(tracePair, "weather-and-border", "rendering")) { + { RenderSystem.depthMask(false); scene.antarchy$renderPortalWeather(minecraft.gameRenderer.lightTexture(), partialTick, cameraX, cameraY, cameraZ); scene.antarchy$renderPortalWorldBorder(camera); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java index f8b5fae8..cdf42ae2 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java @@ -45,19 +45,17 @@ import org.joml.Vector4f; import org.lwjgl.opengl.GL11; public final class PortalGunPortalViewRenderer { - private static final int MAX_ROOT_VIEWS = 2; private static final int MAX_VIEW_LEVELS = 2; - private static final int MAX_VIEWS_PER_FRAME = 4; private static final double PORTAL_SEARCH_RADIUS = 128.0D; private static final int PORTAL_TARGET_FILTER = 9729; private static final double SURFACE_OFFSET = 0.04D; private static final double EXIT_CLIP_OFFSET = 0.01D; + private static final int APERTURE_SEGMENTS = 32; + private static final double APERTURE_RIM_FRACTION = 0.92D; private static TextureTarget offscreenTarget; private static ShaderInstance portalViewShader; private static boolean renderingPortalView; - private static boolean loggedRendererActivation; private static boolean loggedMissingPortalViewShader; - private static String lastPortalCandidateState = ""; private static long lastRenderFailureTick = Long.MIN_VALUE; private PortalGunPortalViewRenderer() { @@ -65,7 +63,6 @@ public final class PortalGunPortalViewRenderer { public static void setPortalViewShader(ShaderInstance shader) { portalViewShader = shader; - Antarchy.LOGGER.info("Portal gun view shader registered"); } public static void clearPortalViewShader() { @@ -77,7 +74,6 @@ public final class PortalGunPortalViewRenderer { } public static void releaseTargets() { - PortalSceneRenderTrace.reset(); PortalGunPortalVisibilityQueries.clear(); PortalGunPortalSectionViews.clear(); if (offscreenTarget != null) { @@ -87,18 +83,35 @@ public final class PortalGunPortalViewRenderer { } public static void render(Camera camera, Matrix4f poseMatrix, Matrix4f projectionMatrix, DeltaTracker tickCounter) { - if (!isEnabled() || renderingPortalView) { + if (renderingPortalView) { return; } + if (isEnabled()) { + renderViews(camera, poseMatrix, projectionMatrix, tickCounter); + } + renderHiddenOutlines(camera, poseMatrix, projectionMatrix, tickCounter); + } + + private static void renderHiddenOutlines(Camera camera, Matrix4f poseMatrix, Matrix4f projectionMatrix, DeltaTracker tickCounter) { + Minecraft minecraft = Minecraft.getInstance(); + if (minecraft.level == null || camera == null || poseMatrix == null || projectionMatrix == null || tickCounter == null) { + return; + } + try { + minecraft.getMainRenderTarget().bindWrite(true); + PortalGunPortalRim.drawHiddenOutlines(minecraft, camera.getPosition(), new Matrix4f(poseMatrix), new Matrix4f(projectionMatrix), + tickCounter.getGameTimeDeltaPartialTick(true)); + } catch (RuntimeException exception) { + logRenderFailure(minecraft, exception); + } + } + + private static void renderViews(Camera camera, Matrix4f poseMatrix, Matrix4f projectionMatrix, DeltaTracker tickCounter) { PortalRenderWatchdog.frame(); Minecraft minecraft = Minecraft.getInstance(); if (minecraft.level == null || minecraft.gameRenderer == null || camera == null || poseMatrix == null || projectionMatrix == null || tickCounter == null) { return; } - if (!loggedRendererActivation) { - loggedRendererActivation = true; - Antarchy.LOGGER.info("Portal gun view renderer hook active (terrain: {})", SodiumCompat.isLoaded() ? "sodium" : "vanilla"); - } Entity cameraEntity = minecraft.getCameraEntity(); if (cameraEntity == null) { return; @@ -127,10 +140,10 @@ public final class PortalGunPortalViewRenderer { } } candidates.sort((left, right) -> Integer.compare(right.clip().area(), left.clip().area())); - if (candidates.size() > MAX_ROOT_VIEWS) { - candidates = candidates.subList(0, MAX_ROOT_VIEWS); + int maxRootViews = AntarchySettings.portalGunMaxLiveViews(); + if (candidates.size() > maxRootViews) { + candidates = candidates.subList(0, maxRootViews); } - logCandidateState(portals, candidates); if (candidates.isEmpty()) { return; } @@ -147,7 +160,7 @@ public final class PortalGunPortalViewRenderer { Vector3f rootLook = cameraToWorld.transformDirection(new Vector3f(0.0F, 0.0F, -1.0F)).normalize(); Vector3f rootUp = cameraToWorld.transformDirection(new Vector3f(0.0F, 1.0F, 0.0F)).normalize(); RenderContext rootContext = new RenderContext(cameraPos, new Vec3(rootLook), new Vec3(rootUp), rootViewMatrix); - ViewBudget budget = new ViewBudget(MAX_VIEWS_PER_FRAME); + ViewBudget budget = new ViewBudget(maxRootViews * 2); PortalRenderWatchdog.portalViewDrawn(); renderingPortalView = true; RenderSystem.backupProjectionMatrix(); @@ -202,7 +215,6 @@ public final class PortalGunPortalViewRenderer { if (!PortalTerrain.canView(minecraft, exit.center())) { return; } - String pairKey = source.getUUID() + "->" + destination.getUUID(); boolean root = parentLevel == 0; boolean visible = !root || PortalGunPortalVisibilityQueries.shouldRender(source.getUUID(), destination.getUUID()); RenderTarget target = minecraft.getMainRenderTarget(); @@ -224,14 +236,21 @@ public final class PortalGunPortalViewRenderer { Matrix4f clippedProjection = applyPortalClipPlane(rootProjection, transformed, destination); RenderSystem.enableScissor(clip.x(), clip.y(), clip.width(), clip.height()); renderScene(minecraft, cameraEntity, partialTick, transformed, rootProjection, clippedProjection, - source, destination, clip, target.width, target.height, parentLevel + 1, pairKey); + source, destination, clip, target.width, target.height, parentLevel + 1); if (parentLevel + 1 < MAX_VIEW_LEVELS) { renderNestedViews(minecraft, cameraEntity, partialTick, transformed, rootProjection, clippedProjection, destination, parentLevel + 1, clip, budget, target.width, target.height); } } finally { - PortalStencilTarget.popAperture(parentLevel, - () -> restorePortalApertureDepth(context.cameraPos(), context.viewMatrix(), parentProjection, source, partialTick)); + try { + if (visible) { + PortalStencilTarget.drawInside(parentLevel + 1); + PortalGunPortalRim.drawOverView(source, context.cameraPos(), context.viewMatrix(), parentProjection, partialTick); + } + } finally { + PortalStencilTarget.popAperture(parentLevel, + () -> restorePortalApertureDepth(context.cameraPos(), context.viewMatrix(), parentProjection, source, partialTick)); + } if (parentClip == null) { RenderSystem.disableScissor(); } else { @@ -275,7 +294,6 @@ public final class PortalGunPortalViewRenderer { TextureTarget target = ensureOffscreenTarget(mainTarget.width, mainTarget.height); RenderContext transformed = transformContext(context, source, destination); Matrix4f clippedProjection = applyPortalClipPlane(rootProjection, transformed, destination); - String pairKey = source.getUUID() + "->" + destination.getUUID(); MinecraftMainRenderTargetAccessor targetAccessor = (MinecraftMainRenderTargetAccessor) minecraft; targetAccessor.antarchy$setMainRenderTarget(target); try { @@ -285,7 +303,7 @@ public final class PortalGunPortalViewRenderer { target.bindWrite(true); RenderSystem.enableScissor(clip.x(), clip.y(), clip.width(), clip.height()); renderScene(minecraft, cameraEntity, partialTick, transformed, rootProjection, clippedProjection, - source, destination, clip, target.width, target.height, 1, pairKey); + source, destination, clip, target.width, target.height, 1); } finally { RenderSystem.disableScissor(); targetAccessor.antarchy$setMainRenderTarget(mainTarget); @@ -298,7 +316,7 @@ public final class PortalGunPortalViewRenderer { private static void renderScene(Minecraft minecraft, Entity cameraEntity, float partialTick, RenderContext transformed, Matrix4f rootProjection, Matrix4f clippedProjection, PortalGunPortalEntity source, PortalGunPortalEntity destination, - ScreenClip clip, int width, int height, int level, String pairKey) { + ScreenClip clip, int width, int height, int level) { PortalGunWorldPortalShape exit = destination.getWorldPortalShape(); PortalCamera portalCamera = new PortalCamera(); portalCamera.setup(minecraft.level, cameraEntity, partialTick, transformed.cameraPos(), transformed.look(), transformed.up()); @@ -308,42 +326,26 @@ public final class PortalGunPortalViewRenderer { source.getWorldPortalShape(), exit, transformed.cameraPos(), transformed.look(), transformed.up(), transformed.viewMatrix(), clippedProjection, level, false, destination.getUUID())); try { - PortalTerrain terrain; - try (PortalSceneRenderTrace.Phase ignored = PortalSceneRenderTrace.begin(pairKey, "section-visibility", "level=" + level)) { - terrain = PortalTerrain.prepare(minecraft, destination.getUUID(), exit.center(), exit.normal(), frustum); - } + PortalTerrain terrain = PortalTerrain.prepare(minecraft, destination.getUUID(), exit.center(), exit.normal(), frustum); PortalGunPortalSceneRenderer.render(minecraft, portalCamera, partialTick, transformed.viewMatrix(), clippedProjection, rootProjection, frustum, terrain, - poseStack -> renderCrossingEntities(minecraft, transformed.cameraPos(), partialTick, source, destination, poseStack), - pairKey); + poseStack -> renderCrossingEntities(minecraft, transformed.cameraPos(), partialTick, source, destination, poseStack)); } finally { PortalGunPortalRenderState.popPortalView(false); } } private static List collectPortals(Minecraft minecraft, Vec3 cameraPos) { - List portals = minecraft.level.getEntitiesOfClass(PortalGunPortalEntity.class, - new AABB(cameraPos, cameraPos).inflate(PORTAL_SEARCH_RADIUS), Entity::isAlive); - portals.removeIf(portal -> portal.distanceToSqr(cameraPos) > PORTAL_SEARCH_RADIUS * PORTAL_SEARCH_RADIUS); + List portals = new ArrayList<>(); + for (PortalGunPortalEntity portal : com.craisinlord.antarchy.content.portalgun.PortalGunPortalRegistry.all(minecraft.level)) { + if (portal.isAlive() && portal.distanceToSqr(cameraPos) <= PORTAL_SEARCH_RADIUS * PORTAL_SEARCH_RADIUS) { + portals.add(portal); + } + } portals.sort((left, right) -> Double.compare(left.distanceToSqr(cameraPos), right.distanceToSqr(cameraPos))); return portals; } - private static void logCandidateState(List portals, List candidates) { - String state = portals.size() + "|" + candidates.stream() - .map(candidate -> candidate.portal().getUUID() + "->" + candidate.linked().getUUID()) - .sorted() - .toList(); - if (state.equals(lastPortalCandidateState)) { - return; - } - lastPortalCandidateState = state; - if (!candidates.isEmpty()) { - PortalSceneRenderTrace.arm(state); - } - Antarchy.LOGGER.info("Portal gun view candidates changed portals={} selected={}", portals.size(), candidates.size()); - } - private static void logRenderFailure(Minecraft minecraft, RuntimeException exception) { long gameTime = minecraft.level == null ? Long.MIN_VALUE : minecraft.level.getGameTime(); if (lastRenderFailureTick == Long.MIN_VALUE || gameTime == Long.MIN_VALUE || gameTime - lastRenderFailureTick >= 100L) { @@ -382,8 +384,7 @@ public final class PortalGunPortalViewRenderer { private static ScreenClip computeScreenClip(Vec3 cameraPos, Matrix4f viewMatrix, Matrix4f projectionMatrix, PortalGunPortalEntity portal, float partialTick, int width, int height) { - List clipVertices = projectPortalPolygon(new Matrix4f(projectionMatrix).mul(viewMatrix), cameraPos, - portal.getWorldPortalShape().scaleAperture(portal.getPortalVisualScale(partialTick))); + List clipVertices = projectPortalPolygon(new Matrix4f(projectionMatrix).mul(viewMatrix), cameraPos, portal, partialTick); if (clipVertices.size() < 3) { return null; } @@ -456,8 +457,8 @@ public final class PortalGunPortalViewRenderer { return nearPlane ? vertex.z + vertex.w : vertex.w - 0.001F; } - private static List projectPortalPolygon(Matrix4f combined, Vec3 cameraPos, PortalGunWorldPortalShape shape) { - Vec3[] corners = shape.getCorners(SURFACE_OFFSET); + private static List projectPortalPolygon(Matrix4f combined, Vec3 cameraPos, PortalGunPortalEntity portal, float partialTick) { + Vec3[] corners = apertureOutline(portal, partialTick); List polygon = new ArrayList<>(corners.length); for (Vec3 corner : corners) { Vec3 relative = corner.subtract(cameraPos); @@ -467,10 +468,17 @@ public final class PortalGunPortalViewRenderer { return clipPolygon(polygon, true); } + static Vec3[] apertureOutline(PortalGunPortalEntity portal, float partialTick) { + float scale = portal.getPortalVisualScale(partialTick); + PortalGunWorldPortalShape shape = portal.getWorldPortalShape().scaleAperture(scale); + double radiusHorizontal = Math.min(shape.halfWidth(), (shape.halfWidth() + PortalGunPortalRim.EXTRA_WIDTH * scale) * APERTURE_RIM_FRACTION); + double radiusVertical = Math.min(shape.halfHeight(), (shape.halfHeight() + PortalGunPortalRim.EXTRA_HEIGHT * scale) * APERTURE_RIM_FRACTION); + return shape.getOutline(SURFACE_OFFSET, APERTURE_SEGMENTS, radiusHorizontal, radiusVertical); + } + private static MeshData buildAperture(Vec3 cameraPos, Matrix4f viewMatrix, Matrix4f projectionMatrix, PortalGunPortalEntity portal, float partialTick, boolean withScreenUv) { - PortalGunWorldPortalShape shape = portal.getWorldPortalShape().scaleAperture(portal.getPortalVisualScale(partialTick)); - List polygon = projectPortalPolygon(new Matrix4f(projectionMatrix).mul(viewMatrix), cameraPos, shape); + List polygon = projectPortalPolygon(new Matrix4f(projectionMatrix).mul(viewMatrix), cameraPos, portal, partialTick); if (polygon.size() < 3) { return null; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalVisibilityQueries.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalVisibilityQueries.java index 8c2be980..25db1fa9 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalVisibilityQueries.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalVisibilityQueries.java @@ -22,7 +22,6 @@ public final class PortalGunPortalVisibilityQueries { state.visible = GL15.glGetQueryObjecti(state.query, GL15.GL_QUERY_RESULT) != 0; state.hasResult = true; state.inFlight = false; - PortalSceneRenderTrace.event(source + "->" + destination, "visibility-query-result", "visible=" + state.visible); } return !state.hasResult || state.visible; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunProjectileRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunProjectileRenderer.java index 0dd92ebf..cf44ce87 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunProjectileRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunProjectileRenderer.java @@ -4,6 +4,7 @@ import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.content.portalgun.PortalGunProjectileEntity; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRenderer; @@ -11,11 +12,25 @@ import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; public class PortalGunProjectileRenderer extends EntityRenderer { - private static final ResourceLocation BLUE_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_portal_blue.png"); - private static final ResourceLocation ORANGE_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_portal_orange.png"); + private static final ResourceLocation SHOT_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_shot.png"); + private static final float CORE_SIZE = 0.16F; + private static final float GLOW_SIZE = 0.34F; + private static final float STREAK_WIDTH = 0.045F; + private static final double STREAK_LENGTH = 2.2D; + private static final float MUZZLE_TICKS = 4.0F; + private static final double MUZZLE_FORWARD = 0.55D; + private static final double MUZZLE_SIDE = 0.32D; + private static final double MUZZLE_DOWN = 0.28D; + private static final double HIDDEN_DISTANCE = 0.9D; + private static final double FADE_DISTANCE = 1.8D; public PortalGunProjectileRenderer(EntityRendererProvider.Context context) { super(context); @@ -23,37 +38,103 @@ public class PortalGunProjectileRenderer extends EntityRenderer> 16 & 0xFF) / 255.0F; + float green = (color >> 8 & 0xFF) / 255.0F; + float blue = (color & 0xFF) / 255.0F; - poseStack.scale(baseScale * trailStretch, baseScale * travelPulse, baseScale * travelPulse); + poseStack.pushPose(); + Vec3 offset = renderPos.subtract(entityPos); + poseStack.translate(offset.x, offset.y, offset.z); + this.renderStreak(entity, renderPos, cameraPos, poseStack, bufferSource, red, green, blue, fade, partialTick); + poseStack.mulPose(this.entityRenderDispatcher.cameraOrientation()); PoseStack.Pose pose = poseStack.last(); Matrix4f matrix = pose.pose(); - VertexConsumer core = bufferSource.getBuffer(RenderType.entityTranslucent(texture)); - addQuad(core, pose, matrix, red, green, blue, 0.92F, packedLight, -0.9F, -0.5F, 0.9F, 0.5F); - VertexConsumer glow = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)); - addQuad(glow, pose, matrix, 1.0F, 1.0F, 1.0F, 0.8F * pulse, 0xF000F0, -1.15F, -0.7F, 1.15F, 0.7F); - - poseStack.mulPose(com.mojang.math.Axis.ZP.rotationDegrees(90.0F)); - pose = poseStack.last(); - matrix = pose.pose(); - core = bufferSource.getBuffer(RenderType.entityTranslucent(texture)); - addQuad(core, pose, matrix, red, green, blue, 0.74F, packedLight, -0.45F, -0.95F, 0.45F, 0.95F); - glow = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)); - addQuad(glow, pose, matrix, 1.0F, 1.0F, 1.0F, 0.52F * pulse, 0xF000F0, -0.62F, -1.15F, 0.62F, 1.15F); + VertexConsumer glow = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(SHOT_TEXTURE)); + addQuad(glow, pose, matrix, red, green, blue, 0.55F * fade, GLOW_SIZE); + addQuad(glow, pose, matrix, 1.0F, 1.0F, 1.0F, 0.9F * fade, CORE_SIZE); poseStack.popPose(); } + private void renderStreak(PortalGunProjectileEntity entity, Vec3 renderPos, Vec3 cameraPos, PoseStack poseStack, MultiBufferSource bufferSource, + float red, float green, float blue, float fade, float partialTick) { + Vec3 velocity = entity.getSyncedVelocity(); + if (velocity.lengthSqr() < 1.0E-6D) { + velocity = entity.getDeltaMovement(); + } + if (velocity.lengthSqr() < 1.0E-6D) { + return; + } + Vec3 direction = velocity.normalize(); + Vec3 toCamera = cameraPos.subtract(renderPos); + Vec3 side = direction.cross(toCamera); + if (side.lengthSqr() < 1.0E-6D) { + return; + } + side = side.normalize().scale(STREAK_WIDTH); + double travelled = entity.getSyncedSpawnPosition().distanceTo(renderPos); + double length = Math.min(STREAK_LENGTH, Math.max(0.0D, travelled - HIDDEN_DISTANCE)); + if (length <= 0.05D) { + return; + } + Vec3 tail = direction.scale(-length); + Matrix4f matrix = poseStack.last().pose(); + VertexConsumer streak = bufferSource.getBuffer(RenderType.lightning()); + float headAlpha = 0.7F * fade; + Vec3 tailLeft = tail.add(side.scale(0.3D)); + Vec3 tailRight = tail.subtract(side.scale(0.3D)); + Vec3 headLeft = side; + Vec3 headRight = side.scale(-1.0D); + addStreakVertex(streak, matrix, headLeft, red, green, blue, headAlpha); + addStreakVertex(streak, matrix, tailLeft, red, green, blue, 0.0F); + addStreakVertex(streak, matrix, tailRight, red, green, blue, 0.0F); + addStreakVertex(streak, matrix, headRight, red, green, blue, headAlpha); + addStreakVertex(streak, matrix, headRight, red, green, blue, headAlpha); + addStreakVertex(streak, matrix, tailRight, red, green, blue, 0.0F); + addStreakVertex(streak, matrix, tailLeft, red, green, blue, 0.0F); + addStreakVertex(streak, matrix, headLeft, red, green, blue, headAlpha); + } + + private static void addStreakVertex(VertexConsumer consumer, Matrix4f matrix, Vec3 position, float red, float green, float blue, float alpha) { + consumer.addVertex(matrix, (float) position.x, (float) position.y, (float) position.z).setColor(red, green, blue, alpha); + } + + private Vec3 muzzleBlendedPosition(PortalGunProjectileEntity entity, Vec3 entityPos, float partialTick) { + float age = entity.tickCount + partialTick; + if (age >= MUZZLE_TICKS) { + return entityPos; + } + Entity shooter = Minecraft.getInstance().level == null ? null : Minecraft.getInstance().level.getEntity(entity.getShooterId()); + if (!(shooter instanceof LivingEntity livingShooter)) { + return entityPos; + } + Vec3 eye = livingShooter.getEyePosition(partialTick); + Vec3 look = livingShooter.getViewVector(partialTick); + Vec3 right = look.cross(new Vec3(0.0D, 1.0D, 0.0D)); + right = right.lengthSqr() < 1.0E-6D ? new Vec3(1.0D, 0.0D, 0.0D) : right.normalize(); + Vec3 down = right.cross(look).normalize().scale(-1.0D); + boolean rightHanded = livingShooter.getMainArm() == HumanoidArm.RIGHT; + boolean offhand = !(livingShooter.getMainHandItem().getItem() instanceof com.craisinlord.antarchy.content.item.PortalGunItem) + && livingShooter.getOffhandItem().getItem() instanceof com.craisinlord.antarchy.content.item.PortalGunItem; + double sideSign = rightHanded != offhand ? 1.0D : -1.0D; + Vec3 muzzle = eye.add(look.scale(MUZZLE_FORWARD)).add(right.scale(MUZZLE_SIDE * sideSign)).add(down.scale(MUZZLE_DOWN)); + double blend = Mth.clamp(age / MUZZLE_TICKS, 0.0F, 1.0F); + return muzzle.lerp(entityPos, blend * blend); + } + + @Override + public boolean shouldRender(PortalGunProjectileEntity entity, net.minecraft.client.renderer.culling.Frustum frustum, double cameraX, double cameraY, double cameraZ) { + return true; + } + @Override protected int getBlockLightLevel(PortalGunProjectileEntity entity, BlockPos pos) { return 15; @@ -61,22 +142,22 @@ public class PortalGunProjectileRenderer extends EntityRenderer LOGGED_PHASES = new HashSet<>(); - private static long generation; - private static String armedKey = ""; - - private PortalSceneRenderTrace() { - } - - public static synchronized void arm(String key) { - if (!armedKey.equals(key)) { - armedKey = key; - generation++; - LOGGED_PHASES.clear(); - } - } - - public static synchronized void reset() { - armedKey = ""; - LOGGED_PHASES.clear(); - generation++; - } - - public static Phase begin(String pair, String phase, String detail) { - boolean verbose = Boolean.getBoolean(DEBUG_PROPERTY); - long currentGeneration; - boolean logStart; - synchronized (PortalSceneRenderTrace.class) { - currentGeneration = generation; - logStart = LOGGED_PHASES.add(currentGeneration + ":" + pair + ":" + phase); - } - if (logStart) { - Antarchy.LOGGER.info("Portal scene trace begin generation={} pair={} phase={} detail={}", currentGeneration, pair, phase, detail); - } - return new Phase(currentGeneration, pair, phase, logStart, verbose, System.nanoTime()); - } - - public static void event(String pair, String event, String detail) { - if (!Boolean.getBoolean(DEBUG_PROPERTY)) { - return; - } - long currentGeneration; - boolean shouldLog; - synchronized (PortalSceneRenderTrace.class) { - currentGeneration = generation; - shouldLog = LOGGED_PHASES.add(currentGeneration + ":" + pair + ":event:" + event); - } - if (shouldLog) { - Antarchy.LOGGER.info("Portal scene trace event generation={} pair={} event={} detail={}", currentGeneration, pair, event, detail); - } - } - - public static final class Phase implements AutoCloseable { - private final long generation; - private final String pair; - private final String phase; - private final boolean logStart; - private final boolean verbose; - private final long startNanos; - private boolean closed; - - private Phase(long generation, String pair, String phase, boolean logStart, boolean verbose, long startNanos) { - this.generation = generation; - this.pair = pair; - this.phase = phase; - this.logStart = logStart; - this.verbose = verbose; - this.startNanos = startNanos; - } - - @Override - public void close() { - if (this.closed) { - return; - } - this.closed = true; - long durationNanos = System.nanoTime() - this.startNanos; - if (this.logStart && (this.verbose || durationNanos >= SLOW_PHASE_NANOS)) { - Antarchy.LOGGER.info("Portal scene trace complete generation={} pair={} phase={} durationMs={}", - this.generation, this.pair, this.phase, durationNanos / 1_000_000.0D); - } - } - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalStencilTarget.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalStencilTarget.java index 3a46d6da..a644722c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalStencilTarget.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalStencilTarget.java @@ -41,7 +41,7 @@ public final class PortalStencilTarget { ensureMainStencilAttachment(target); } catch (IllegalStateException exception) { UNSUPPORTED_MAIN_TARGETS.put(target, target.frameBufferId); - Antarchy.LOGGER.warn("Portal gun direct stencil is unavailable; using offscreen portal rendering", exception); + Antarchy.LOGGER.debug("Portal gun direct stencil is unavailable ({}); using offscreen portal rendering", exception.getMessage()); } } } @@ -150,7 +150,6 @@ public final class PortalStencilTarget { throw new IllegalStateException("Main render target is incomplete with stencil attachment: 0x" + Integer.toHexString(status)); } MAIN_STENCIL_ATTACHMENTS.put(target, new Attachment(target.frameBufferId, renderbuffer, target.width, target.height)); - PortalSceneRenderTrace.event("main-target", "stencil-attached", "framebuffer=" + target.frameBufferId + " size=" + target.width + "x" + target.height); } catch (RuntimeException | Error exception) { GL30.glDeleteRenderbuffers(renderbuffer); throw exception; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalIndicatorRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalIndicatorRenderer.java index c730774a..44936b80 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalIndicatorRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalIndicatorRenderer.java @@ -101,8 +101,6 @@ public final class RoyalIndicatorRenderer { } private static void judgmentFlare(VertexConsumer out, PoseStack.Pose pose, float radius, float rotation) { - // The old mark was almost edge-on from normal gameplay camera angles. Add a vertical, - // unmistakable judgment sigil while keeping the rotating ring as its core. for (int i = 0; i < 4; i++) { double angle = rotation + Math.PI * 0.5D * i; float x = (float) Math.cos(angle) * radius; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java index 80ff3128..daa82d41 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java @@ -4,7 +4,6 @@ import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.entity.glimmer.GlimmerVariant; import com.craisinlord.antarchy.content.item.GiantFryingPanToolHelper; import com.craisinlord.antarchy.content.item.GlimmerBottleItem; -import com.craisinlord.antarchy.content.item.PortalGunItem; import com.craisinlord.antarchy.content.item.royal.RoyalGearHelper; import com.craisinlord.antarchy.content.item.ultimate.UltimateGearHelper; import java.util.HashMap; @@ -427,6 +426,8 @@ public final class CreativeTabContents { entry("growth_ray", "combat"), entry("gravity_gun", "combat"), entry("portal_gun", "combat"), + entry("portal_gun_atlas", "combat"), + entry("portal_gun_p_body", "combat"), entry("eye_of_the_storm", "combat"), entry("water_cannon", "combat"), entry("attitude_adjuster", "combat"), @@ -641,14 +642,6 @@ public final class CreativeTabContents { } continue; } - if ("portal_gun".equals(entry.path())) { - Item portalGun = item(entry.path()); - output.accept(portalGun); - output.accept(PortalGunItem.createGlobalVariant(portalGun, "Chell")); - output.accept(PortalGunItem.createGlobalVariant(portalGun, "Atlas")); - output.accept(PortalGunItem.createGlobalVariant(portalGun, "P-body")); - continue; - } output.accept(item(entry.path())); } for (String potionPath : ANTARCHY_POTION_FAMILIES) { @@ -678,14 +671,6 @@ public final class CreativeTabContents { output.insertAfter(vanillaItem(entry.insertAfterPath()), item(entry.path())); continue; } - if ("portal_gun".equals(entry.path())) { - Item portalGun = item(entry.path()); - output.accept(portalGun); - output.accept(PortalGunItem.createGlobalVariant(portalGun, "Chell")); - output.accept(PortalGunItem.createGlobalVariant(portalGun, "Atlas")); - output.accept(PortalGunItem.createGlobalVariant(portalGun, "P-body")); - continue; - } if ("combat".equals(tabPath)) { if (isUltimateArmor(entry.path())) { output.accept(UltimateGearHelper.createUltimateArmorStack(item(entry.path()), holders)); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/HushProjectileEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/HushProjectileEntity.java index 0ab9206f..8ac547b1 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/HushProjectileEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/HushProjectileEntity.java @@ -115,7 +115,6 @@ public class HushProjectileEntity extends ThrowableItemProjectile { return; } - // Smoothly steer toward the target each tick Vec3 desired = toTarget.normalize().scale(TRAVEL_SPEED); this.setDeltaMovement(this.getDeltaMovement().lerp(desired, 0.1D)); } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java index 3c72e4f0..3acf470c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java @@ -167,7 +167,7 @@ public class MantisEntity extends Monster implements GeoEntity { MantisEntity.class, new AABB(pos).inflate(64.0D), Entity::isAlive - ).size() < 3; + ).size() < 4; } @Override diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/AntTeleportHelper.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/AntTeleportHelper.java index 84eb3fc3..9b852e6e 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/AntTeleportHelper.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/AntTeleportHelper.java @@ -284,9 +284,10 @@ public final class AntTeleportHelper { // The bounded search can fail near rough or sparsely-generated terrain. // Retry once with a wider radius before giving up. loadArrivalSearchArea(destination, preferredPos, EXPANDED_ARRIVAL_SEARCH_RADIUS); - return findSafeArrivalPositionInYRange( + Vec3 expandedSafePos = findSafeArrivalPositionInYRange( player, destination, preferredPos, yRange[0], yRange[1], EXPANDED_ARRIVAL_SEARCH_RADIUS, EXPANDED_ARRIVAL_VERTICAL_SEARCH); + return expandedSafePos != null ? expandedSafePos : createEmergencyArrivalPlatform(destination, preferredPos, yRange[0], yRange[1]); } Set candidates = new LinkedHashSet<>(); @@ -323,6 +324,46 @@ public final class AntTeleportHelper { } } + return createEmergencyArrivalPlatform(destination, preferredPos, destination.getMinBuildHeight() + 1, destination.getMaxBuildHeight() - 3); + } + + @Nullable + private static Vec3 createEmergencyArrivalPlatform(ServerLevel destination, BlockPos preferredPos, int minY, int maxY) { + int y = Math.clamp(preferredPos.getY(), minY, maxY); + int centerX = preferredPos.getX(); + int centerZ = preferredPos.getZ(); + for (int radius = 0; radius <= EXPANDED_ARRIVAL_SEARCH_RADIUS; radius++) { + for (int xOff = -radius; xOff <= radius; xOff++) { + for (int zOff = -radius; zOff <= radius; zOff++) { + if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) continue; + int x = centerX + xOff; + int z = centerZ + zOff; + BlockPos floor = new BlockPos(x, y - 1, z); + boolean withinBorder = true; + for (int dx = -2; dx <= 2 && withinBorder; dx++) { + for (int dz = -2; dz <= 2; dz++) { + BlockPos check = floor.offset(dx, 0, dz); + if (!destination.getWorldBorder().isWithinBounds(check) || !destination.hasChunkAt(check.above(3))) { + withinBorder = false; + break; + } + } + } + if (!withinBorder) continue; + for (int dx = -2; dx <= 2; dx++) { + for (int dz = -2; dz <= 2; dz++) { + BlockPos pad = floor.offset(dx, 0, dz); + destination.setBlock(pad, Blocks.COBBLESTONE.defaultBlockState(), Block.UPDATE_ALL); + for (int dy = 1; dy <= 3; dy++) { + destination.setBlock(pad.above(dy), Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL); + } + } + } + Vec3 safePos = new Vec3(x + 0.5D, y, z + 0.5D); + if (isValidArrivalPosition(destination, safePos)) return safePos; + } + } + } return null; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/basilisk/BasiliskEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/basilisk/BasiliskEntity.java index 056d2244..d296b7c2 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/basilisk/BasiliskEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/basilisk/BasiliskEntity.java @@ -141,9 +141,9 @@ public class BasiliskEntity extends Monster implements GeoEntity { } return level.getDifficulty() != Difficulty.PEACEFUL - && pos.getY() >= 60 && pos.getY() <= 90 + && pos.getY() >= 60 && pos.getY() <= 100 && level.getMaxLocalRawBrightness(pos) <= AntarchySettings.basiliskSpawnMaxLightLevel() - && level.getEntitiesOfClass(BasiliskEntity.class, new AABB(pos).inflate(40.0D), Entity::isAlive).isEmpty() + && level.getEntitiesOfClass(BasiliskEntity.class, new AABB(pos).inflate(36.0D), Entity::isAlive).isEmpty() && Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random); } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/brutalfly/BrutalflyEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/brutalfly/BrutalflyEntity.java index 85b771e8..efaba0d5 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/brutalfly/BrutalflyEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/brutalfly/BrutalflyEntity.java @@ -277,12 +277,10 @@ public class BrutalflyEntity extends Monster implements GeoEntity { this.cocoonHitCooldownTicks--; } - // Pin position to hang from anchor if (this.anchorPos != null) { this.setPos(this.anchorPos.getX() + 0.5, this.anchorPos.getY() - 1.5, this.anchorPos.getZ() + 0.5); this.setDeltaMovement(Vec3.ZERO); - // Hatch immediately if anchor log was broken if (!this.isHatching && !this.level().getBlockState(this.anchorPos).is(BlockTags.LOGS)) { this.startHatching(); return; @@ -303,7 +301,6 @@ public class BrutalflyEntity extends Monster implements GeoEntity { return; } - // Count down hit animation if (this.cocoonAnimTicks > 0) { this.cocoonAnimTicks--; if (this.cocoonAnimTicks <= 0) { @@ -312,7 +309,6 @@ public class BrutalflyEntity extends Monster implements GeoEntity { return; } - // Occasionally play idle animation if (this.getAnimationState() == ANIM_COCOON_IDLE) { // Will be reset to COCOON after idle ticks counted down } else if (this.tickCount % 200 == 17 && this.random.nextFloat() < 0.4F) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java index 3ff744e2..78901055 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java @@ -7,12 +7,14 @@ import com.craisinlord.antarchy.content.block.entity.PortalGunPortalFaceRecord; import com.craisinlord.antarchy.content.block.entity.PortalGunPortalCellAccess; import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel; import com.craisinlord.antarchy.content.client.renderer.AnimatedHeldItemRenderer; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; import com.craisinlord.antarchy.content.network.PortalGunPrimaryPayload; import com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunPlacement; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunProjectileEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunSavedData; +import com.craisinlord.antarchy.content.portalgun.PortalGunVariant; import com.craisinlord.antarchy.content.portalgun.PortalGunResetManager; import com.craisinlord.antarchy.config.AntarchySettings; import java.util.HashSet; @@ -20,7 +22,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.nio.charset.StandardCharsets; import java.util.function.Consumer; import java.util.function.Supplier; import net.minecraft.core.BlockPos; @@ -73,23 +74,19 @@ public class PortalGunItem extends Item implements GeoItem { private static final String LAST_SIDE_TAG = "antarchy.portal_gun_last_side"; private static final String MOON_SIDE_TAG = "antarchy.portal_gun_moon_side"; public static final String GUN_ID_TAG = "antarchy.portal_gun_id"; - public static final String CHANNEL_NAME_TAG = "antarchy.portal_gun_channel"; public static final String OWNER_ID_TAG = "antarchy.portal_gun_owner"; - public static final String OWNER_NAME_TAG = "antarchy.portal_gun_owner_name"; - public static final UUID GLOBAL_OWNER_ID = UUID.nameUUIDFromBytes("Global".getBytes(StandardCharsets.UTF_8)); public static final String PORTAL_WIDTH_TAG = "width"; public static final String PORTAL_HEIGHT_TAG = "height"; - public static final String GRAB_STRENGTH_TAG = "grabStrength"; private static final int MAX_PORTAL_WIDTH = 16; private static final int MAX_PORTAL_HEIGHT = 16; private static final ResourceLocation MODEL_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/portal_gun.geo.json"); - private static final ResourceLocation TEXTURE_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/models/item/portal_gun.png"); private static final ResourceLocation ANIMATION_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/portal_gun.animation.json"); private final Supplier> portalType; private final Supplier> blackHoleType; private final Supplier> projectileType; private final Supplier portalMasterBlock; private final Supplier portalBaseBlock; + private final PortalGunVariant variant; private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); public PortalGunItem( @@ -98,9 +95,11 @@ public class PortalGunItem extends Item implements GeoItem { Supplier> blackHoleType, Supplier> projectileType, Supplier portalMasterBlock, - Supplier portalBaseBlock + Supplier portalBaseBlock, + PortalGunVariant variant ) { super(properties); + this.variant = variant; this.portalType = portalType; this.blackHoleType = blackHoleType; this.projectileType = projectileType; @@ -109,6 +108,10 @@ public class PortalGunItem extends Item implements GeoItem { GeoItem.registerSyncedAnimatable(this); } + public PortalGunVariant getVariant() { + return this.variant; + } + @Override public InteractionResultHolder use(Level level, Player player, InteractionHand usedHand) { ItemStack stack = player.getItemInHand(usedHand); @@ -134,23 +137,21 @@ public class PortalGunItem extends Item implements GeoItem { } public void resetPortals(ServerPlayer player, ItemStack stack) { - UUID gunId = this.ensureGunId(stack, player.getUUID(), player.getGameProfile().getName()); - UUID ownerId = getPortalOwnerId(stack, player.getUUID()); - PortalGunSavedData.clearAllPortals(player.serverLevel(), ownerId, gunId, getChannelName(stack)); + UUID gunId = this.ensureGunId(stack, player.getUUID()); + PortalGunSavedData.clearAllPortals(player.serverLevel(), gunId); this.setLastSide(stack, null); this.setMoonSide(stack, null); player.serverLevel().playSound(null, player.getX(), player.getY(), player.getZ(), PortalGunPortalEntity.sound("portal_fizzle"), SoundSource.PLAYERS, 0.6F, 1.0F); } public void resetPortalSide(ServerPlayer player, ItemStack stack, PortalGunPortalEntity.PortalSide side) { - UUID gunId = this.ensureGunId(stack, player.getUUID(), player.getGameProfile().getName()); - UUID ownerId = getPortalOwnerId(stack, player.getUUID()); - PortalGunSavedData.clearPortalSide(player.serverLevel(), ownerId, gunId, getChannelName(stack), side); + UUID gunId = this.ensureGunId(stack, player.getUUID()); + PortalGunSavedData.clearPortalSide(player.serverLevel(), gunId, side); player.serverLevel().playSound(null, player.getX(), player.getY(), player.getZ(), PortalGunPortalEntity.sound("portal_fizzle"), SoundSource.PLAYERS, 0.6F, 1.0F); } public void fireMobPortal(ServerLevel level, LivingEntity shooter, ItemStack stack, PortalGunPortalEntity.PortalSide side) { - this.ensureGunId(stack, shooter.getUUID(), shooter.getName().getString()); + this.ensureGunId(stack, shooter.getUUID()); String firePath = side == PortalGunPortalEntity.PortalSide.BLUE ? "portal_gun_fire_blue" : "portal_gun_fire_orange"; level.playSound(null, shooter.getX(), shooter.getY(), shooter.getZ(), PortalGunPortalEntity.sound(firePath), shooter.getSoundSource(), 0.65F, side == PortalGunPortalEntity.PortalSide.BLUE ? 1.15F : 0.88F); this.spawnProjectile(level, shooter, stack, side); @@ -163,7 +164,7 @@ public class PortalGunItem extends Item implements GeoItem { } } this.triggerFireAnimation(level, player, stack); - this.ensureGunId(stack, player.getUUID(), player.getGameProfile().getName()); + this.ensureGunId(stack, player.getUUID()); stack.hurtAndBreak(1, player, offhand ? EquipmentSlot.OFFHAND : EquipmentSlot.MAINHAND); player.awardStat(Stats.ITEM_USED.get(this)); player.getCooldowns().addCooldown(this, 6); @@ -175,10 +176,8 @@ public class PortalGunItem extends Item implements GeoItem { public void handlePortalImpact(ServerLevel level, LivingEntity shooter, ItemStack stack, UUID gunId, PortalGunPortalEntity.PortalSide side, BlockHitResult hitResult, Vec3 impactPos, int portalWidth, int portalHeight) { UUID portalOwnerId = getPortalOwnerId(stack, shooter.getUUID()); - String portalOwnerIdentity = getPortalOwnerIdentity(stack, shooter.getUUID()); - String channelName = getChannelName(stack); - PortalGunPortalEntity existing = this.findPlacedPortal(level, portalOwnerId, gunId, channelName, side); - PortalGunPlacement placement = this.findPlacement(level, shooter, portalOwnerId, channelName, side, hitResult, existing, portalWidth, portalHeight); + PortalGunPortalEntity existing = this.findPlacedPortal(level, gunId, side); + PortalGunPlacement placement = this.findPlacement(level, shooter, gunId, side, hitResult, existing, portalWidth, portalHeight); if (placement == null) { Antarchy.LOGGER.debug("Portal gun placement failed owner={} side={} hitBlock={} hitFace={} hitLocation={}", shooter.getUUID(), side, hitResult.getBlockPos(), hitResult.getDirection(), hitResult.getLocation()); level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface"), SoundSource.PLAYERS, 0.55F, 1.0F); @@ -204,16 +203,16 @@ public class PortalGunItem extends Item implements GeoItem { return; } PortalGunPortalEntity portal = new PortalGunPortalEntity(this.portalType.get(), level); - portal.configure(portalOwnerId, gunId, portalOwnerIdentity, channelName, side, placement); + portal.configure(portalOwnerId, gunId, this.variant, side, placement); portal.moveTo(placement.center().x, placement.center().y, placement.center().z, placement.yaw(), 0.0F); - if (!this.placePortalBlocks(level, portalOwnerId, gunId, portalOwnerIdentity, channelName, side, portal, placement)) { + if (!this.placePortalBlocks(level, portalOwnerId, gunId, side, portal, placement)) { Antarchy.LOGGER.debug("Portal gun block placement failed owner={} side={} portal={} center={} facing={} up={} master={} base={}", shooter.getUUID(), side, portal.getUUID(), placement.center(), placement.facing(), placement.upAxis(), placement.masterPos(), placement.basePos()); level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface"), SoundSource.PLAYERS, 0.55F, 1.0F); return; } level.addFreshEntity(portal); - PortalGunSavedData.setPortal(level, portalOwnerId, gunId, channelName, side, portal.getUUID()); - PortalGunPortalEntity other = this.findCounterpart(level, portalOwnerId, gunId, channelName, side); + PortalGunSavedData.setPortal(level, gunId, side, portal.getUUID()); + PortalGunPortalEntity other = this.findCounterpart(level, gunId, side); if (other != null) { portal.linkTo(other); other.linkTo(portal); @@ -261,8 +260,7 @@ public class PortalGunItem extends Item implements GeoItem { if (!level.dimensionType().hasSkyLight() || !level.isNight() || player.getXRot() > -40.0F) { return false; } - UUID ownerId = getPortalOwnerId(stack, player.getUUID()); - PortalGunPortalEntity existing = this.findPlacedPortal(level, ownerId, this.ensureGunId(stack, player.getUUID(), player.getGameProfile().getName()), getChannelName(stack), side); + PortalGunPortalEntity existing = this.findPlacedPortal(level, this.ensureGunId(stack, player.getUUID()), side); if (existing != null) { existing.discard(); } @@ -273,7 +271,7 @@ public class PortalGunItem extends Item implements GeoItem { player.awardStat(Stats.ITEM_USED.get(this)); player.getCooldowns().addCooldown(this, 6); level.playSound(null, player.getX(), player.getY(), player.getZ(), PortalGunPortalEntity.sound(side == PortalGunPortalEntity.PortalSide.BLUE ? "portal_gun_fire_blue" : "portal_gun_fire_orange"), SoundSource.PLAYERS, 0.65F, side == PortalGunPortalEntity.PortalSide.BLUE ? 1.15F : 0.88F); - this.spawnShotTrail(level, player, player.getEyePosition().add(player.getLookAngle().scale(64.0D)), side); + this.spawnShotTrail(level, player, player.getEyePosition().add(this.worldLook(player).scale(64.0D)), side); return true; } @@ -301,10 +299,10 @@ public class PortalGunItem extends Item implements GeoItem { } private void spawnProjectile(ServerLevel level, LivingEntity shooter, ItemStack stack, PortalGunPortalEntity.PortalSide side) { - UUID gunId = this.ensureGunId(stack, shooter.getUUID(), shooter.getName().getString()); + UUID gunId = this.ensureGunId(stack, shooter.getUUID()); PortalGunProjectileEntity projectile = new PortalGunProjectileEntity(this.projectileType.get(), shooter, level); projectile.configure(side, gunId, stack); - Vec3 look = shooter.getLookAngle(); + Vec3 look = this.worldLook(shooter); Vec3 start = shooter.getEyePosition(); double launchSpeed = PortalGunProjectileEntity.MIN_LAUNCH_SPEED + level.getRandom().nextDouble() * PortalGunProjectileEntity.LAUNCH_SPEED_VARIANCE; projectile.setProjectileSpeed(launchSpeed); @@ -324,14 +322,9 @@ public class PortalGunItem extends Item implements GeoItem { return Mth.clamp(data == null || !data.copyTag().contains(PORTAL_HEIGHT_TAG) ? 2 : data.copyTag().getInt(PORTAL_HEIGHT_TAG), 2, MAX_PORTAL_HEIGHT); } - public static int getGrabStrength(ItemStack stack) { - net.minecraft.world.item.component.CustomData data = stack.get(DataComponents.CUSTOM_DATA); - return Mth.clamp(data == null || !data.copyTag().contains(GRAB_STRENGTH_TAG) ? 4 : data.copyTag().getInt(GRAB_STRENGTH_TAG), 1, 4); - } - - private PortalGunPortalEntity findCounterpart(ServerLevel level, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side) { + private PortalGunPortalEntity findCounterpart(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side) { PortalGunPortalEntity.PortalSide otherSide = side == PortalGunPortalEntity.PortalSide.BLUE ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE; - Optional otherId = PortalGunSavedData.getPortalId(level.getServer(), owner, gunId, channelName, otherSide, level.dimension().location()); + Optional otherId = PortalGunSavedData.getPortalId(level.getServer(), gunId, otherSide, level.dimension().location()); if (otherId.isEmpty()) { return null; } @@ -339,8 +332,8 @@ public class PortalGunItem extends Item implements GeoItem { return entity instanceof PortalGunPortalEntity portal ? portal : null; } - private PortalGunPortalEntity findPlacedPortal(ServerLevel level, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side) { - Optional portalId = PortalGunSavedData.getPortalId(level.getServer(), owner, gunId, channelName, side, level.dimension().location()); + private PortalGunPortalEntity findPlacedPortal(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side) { + Optional portalId = PortalGunSavedData.getPortalId(level.getServer(), gunId, side, level.dimension().location()); if (portalId.isEmpty()) { return null; } @@ -354,11 +347,19 @@ public class PortalGunItem extends Item implements GeoItem { private BlockHitResult raycast(Level level, Player player) { Vec3 start = player.getEyePosition(); - Vec3 end = start.add(player.getLookAngle().scale(64.0D)); + Vec3 end = start.add(this.worldLook(player).scale(64.0D)); return level.clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player)); } - private PortalGunPlacement findPlacement(Level level, LivingEntity shooter, UUID ownerId, String channelName, PortalGunPortalEntity.PortalSide side, BlockHitResult hitResult, PortalGunPortalEntity replacingPortal, int requestedWidth, int requestedHeight) { + private Vec3 worldLook(LivingEntity entity) { + Vec3 look = entity.getLookAngle(); + return AntarchyGravityApi.isGravityInverted(entity) + ? com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil.vecPlayerToWorld( + look, AntarchyGravityApi.getGravityDirection(entity)) + : look; + } + + private PortalGunPlacement findPlacement(Level level, LivingEntity shooter, UUID gunId, PortalGunPortalEntity.PortalSide side, BlockHitResult hitResult, PortalGunPortalEntity replacingPortal, int requestedWidth, int requestedHeight) { int maxWidth = Mth.clamp(requestedWidth, 1, 16); int maxHeight = Mth.clamp(requestedHeight, 2, 16); boolean canResize = AntarchySettings.portalGunCanPortalsResizeWhenCreated(); @@ -367,7 +368,7 @@ public class PortalGunItem extends Item implements GeoItem { if (!canResize && (width != maxWidth || height != maxHeight)) { continue; } - PortalGunPlacement placement = this.findPlacementForSize(level, shooter, ownerId, channelName, side, hitResult, replacingPortal, width, height); + PortalGunPlacement placement = this.findPlacementForSize(level, shooter, gunId, side, hitResult, replacingPortal, width, height); if (placement != null) { return placement; } @@ -376,7 +377,7 @@ public class PortalGunItem extends Item implements GeoItem { return null; } - private PortalGunPlacement findPlacementForSize(Level level, LivingEntity shooter, UUID ownerId, String channelName, PortalGunPortalEntity.PortalSide side, BlockHitResult hitResult, PortalGunPortalEntity replacingPortal, int width, int height) { + private PortalGunPlacement findPlacementForSize(Level level, LivingEntity shooter, UUID gunId, PortalGunPortalEntity.PortalSide side, BlockHitResult hitResult, PortalGunPortalEntity replacingPortal, int width, int height) { Direction facing = hitResult.getDirection(); Direction heightAxis = this.resolveUpAxis(shooter, facing); Direction widthAxis = PortalGunPlacement.widthAxis(facing, heightAxis); @@ -410,7 +411,7 @@ public class PortalGunItem extends Item implements GeoItem { BlockState supportState = level.getBlockState(supportPos); BlockState portalState = level.getBlockState(portalPos); if (!supportState.isFaceSturdy(level, supportPos, facing) - || !this.isPortalSpaceAvailable(level, portalPos, portalState, ownerId, channelName, side, facing)) { + || !this.isPortalSpaceAvailable(level, portalPos, portalState, gunId, side, facing)) { valid = false; break; } @@ -505,13 +506,13 @@ public class PortalGunItem extends Item implements GeoItem { return horizontal; } - private boolean isPortalSpaceAvailable(Level level, BlockPos pos, BlockState state, UUID ownerId, String channelName, PortalGunPortalEntity.PortalSide side, Direction face) { + private boolean isPortalSpaceAvailable(Level level, BlockPos pos, BlockState state, UUID gunId, PortalGunPortalEntity.PortalSide side, Direction face) { BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof PortalGunPortalCellAccess portalCell) { PortalGunPortalFaceRecord record = portalCell.portalGun$getFaceRecord(face); if (record == null) { if (blockEntity instanceof PortalGunPortalMasterBlockEntity master && master.getPortalId() != null && master.getFacing() == face) { - return ownerId != null && ownerId.equals(master.getOwnerId()) && channelName.equals(master.getChannelName()) && master.getSide() == side; + return gunId != null && gunId.equals(master.getGunId()) && master.getSide() == side; } if (blockEntity instanceof PortalGunPortalBaseBlockEntity base && base.getPortalId() != null) { BlockEntity masterEntity = level.getBlockEntity(base.getMasterPos()); @@ -519,23 +520,21 @@ public class PortalGunItem extends Item implements GeoItem { return false; } return master.getFacing() != face - || (ownerId != null - && ownerId.equals(base.getOwnerId()) - && channelName.equals(master.getChannelName()) + || (gunId != null + && gunId.equals(master.getGunId()) && base.getSide() == side && master.getSide() == side); } return true; } - return ownerId != null - && ownerId.equals(record.ownerId()) - && channelName.equals(record.channelName()) + return gunId != null + && gunId.equals(record.gunId()) && record.side() == side; } return state.getCollisionShape(level, pos).isEmpty(); } - private boolean placePortalBlocks(ServerLevel level, UUID ownerId, UUID gunId, String ownerIdentity, String channelName, PortalGunPortalEntity.PortalSide side, PortalGunPortalEntity portal, PortalGunPlacement placement) { + private boolean placePortalBlocks(ServerLevel level, UUID ownerId, UUID gunId, PortalGunPortalEntity.PortalSide side, PortalGunPortalEntity portal, PortalGunPlacement placement) { int pairTime = level.getServer().getTickCount(); for (int i = 0; i < placement.portalSpots().length; i++) { BlockPos spot = placement.portalSpots()[i]; @@ -557,9 +556,8 @@ public class PortalGunItem extends Item implements GeoItem { if (!(existing instanceof PortalGunPortalCellAccess cell) || !cell.portalGun$putFaceRecord(new PortalGunPortalFaceRecord( ownerId, - ownerIdentity, gunId, - channelName, + this.variant, portal.getUUID(), portal.getLinkedPortalId(), side, @@ -578,7 +576,7 @@ public class PortalGunItem extends Item implements GeoItem { } if (masterRole && existing instanceof PortalGunPortalMasterBlockEntity master && (master.getPortalId() == null || master.getPortalId().equals(portal.getUUID()))) { - master.configure(ownerId, gunId, ownerIdentity, channelName, portal.getUUID(), side, placement.facing(), placement.upAxis(), placement.basePos(), placement.portalSpots(), placement.compensatedSpots(), pairTime, placement.width(), placement.height()); + master.configure(ownerId, gunId, this.variant, portal.getUUID(), side, placement.facing(), placement.upAxis(), placement.basePos(), placement.portalSpots(), placement.compensatedSpots(), pairTime, placement.width(), placement.height()); } else if (!masterRole && existing instanceof PortalGunPortalBaseBlockEntity base && (base.getPortalId() == null || base.getPortalId().equals(portal.getUUID()))) { base.configure(ownerId, portal.getUUID(), side, placement.masterPos()); @@ -656,12 +654,8 @@ public class PortalGunItem extends Item implements GeoItem { } else { gunId = UUID.randomUUID(); } - String channelName = "Random Channel #" + gunId.hashCode(); net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> { tag.putUUID(GUN_ID_TAG, gunId); - if (!tag.contains(CHANNEL_NAME_TAG)) { - tag.putString(CHANNEL_NAME_TAG, channelName); - } if (!tag.contains(LAST_SIDE_TAG)) { tag.putString(LAST_SIDE_TAG, PortalGunPortalEntity.PortalSide.BLUE.name()); } @@ -669,30 +663,16 @@ public class PortalGunItem extends Item implements GeoItem { return gunId; } - private UUID ensureGunId(ItemStack stack, UUID ownerId, String ownerName) { + private UUID ensureGunId(ItemStack stack, UUID ownerId) { UUID gunId = this.ensureGunId(stack); net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> { if (!tag.contains(OWNER_ID_TAG)) { tag.putString(OWNER_ID_TAG, ownerId.toString()); - tag.putString(OWNER_NAME_TAG, ownerName); } }); return gunId; } - public static String getChannelName(ItemStack stack) { - net.minecraft.world.item.component.CustomData customData = stack.get(DataComponents.CUSTOM_DATA); - if (customData == null) { - return ""; - } - return customData.copyTag().getString(CHANNEL_NAME_TAG); - } - - public static String getPortalOwnerName(ItemStack stack) { - net.minecraft.world.item.component.CustomData customData = stack.get(DataComponents.CUSTOM_DATA); - return customData == null ? "" : customData.copyTag().getString(OWNER_NAME_TAG); - } - public static UUID ensureGunIdentity(ItemStack stack) { if (stack.isEmpty() || !(stack.getItem() instanceof PortalGunItem item)) { return null; @@ -704,7 +684,7 @@ public class PortalGunItem extends Item implements GeoItem { if (stack.isEmpty() || !(stack.getItem() instanceof PortalGunItem item)) { return null; } - return item.ensureGunId(stack, owner.getUUID(), owner.getGameProfile().getName()); + return item.ensureGunId(stack, owner.getUUID()); } public static UUID getPortalOwnerId(ItemStack stack, UUID fallback) { @@ -713,9 +693,6 @@ public class PortalGunItem extends Item implements GeoItem { return fallback; } String owner = customData.copyTag().getString(OWNER_ID_TAG); - if ("Global".equals(owner)) { - return GLOBAL_OWNER_ID; - } try { return owner.isEmpty() ? fallback : UUID.fromString(owner); } catch (IllegalArgumentException ignored) { @@ -723,32 +700,6 @@ public class PortalGunItem extends Item implements GeoItem { } } - public static String getPortalOwnerIdentity(ItemStack stack, UUID fallback) { - net.minecraft.world.item.component.CustomData customData = stack.get(DataComponents.CUSTOM_DATA); - if (customData == null) { - return String.valueOf(fallback); - } - String owner = customData.copyTag().getString(OWNER_ID_TAG); - return owner.isEmpty() ? String.valueOf(fallback) : owner; - } - - public static ItemStack createGlobalVariant(Item item, String channelName) { - ItemStack stack = new ItemStack(item); - UUID gunId = UUID.nameUUIDFromBytes(("Global\u0000" + channelName).getBytes(StandardCharsets.UTF_8)); - net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> { - tag.putUUID(GUN_ID_TAG, gunId); - tag.putString(OWNER_ID_TAG, "Global"); - tag.putString(OWNER_NAME_TAG, "Global"); - tag.putString(CHANNEL_NAME_TAG, channelName); - tag.putInt(PORTAL_WIDTH_TAG, 1); - tag.putInt(PORTAL_HEIGHT_TAG, 2); - tag.putInt(GRAB_STRENGTH_TAG, 4); - tag.putString(LAST_SIDE_TAG, PortalGunPortalEntity.PortalSide.BLUE.name()); - tag.putBoolean("lastFired", true); - }); - return stack; - } - private boolean matchesGunId(ItemStack stack, UUID gunId) { if (stack.isEmpty() || stack.getItem() != this) { return false; @@ -767,21 +718,16 @@ public class PortalGunItem extends Item implements GeoItem { return UseAnim.NONE; } + private Component portalColorName(PortalGunPortalEntity.PortalSide side) { + return Component.translatable(this.variant.colorTranslationKey(side)) + .withStyle(style -> style.withColor(net.minecraft.network.chat.TextColor.fromRgb(this.variant.color(side)))); + } + @Override public void appendHoverText(ItemStack stack, Item.TooltipContext context, List tooltipComponents, TooltipFlag tooltipFlag) { - tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.primary").withStyle(ChatFormatting.GRAY)); - tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.secondary").withStyle(ChatFormatting.GRAY)); - String ownerName = getPortalOwnerName(stack); - if (!ownerName.isEmpty()) { - tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.owner", ownerName).withStyle(ChatFormatting.GRAY)); - } - String channelName = getChannelName(stack); - if (!channelName.isEmpty()) { - tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.channel", channelName).withStyle(ChatFormatting.GRAY)); - } + tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.primary", this.portalColorName(PortalGunPortalEntity.PortalSide.BLUE)).withStyle(ChatFormatting.GRAY)); + tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.secondary", this.portalColorName(PortalGunPortalEntity.PortalSide.ORANGE)).withStyle(ChatFormatting.GRAY)); tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.reset").withStyle(ChatFormatting.DARK_GRAY)); - tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.size", getPortalWidth(stack), getPortalHeight(stack)).withStyle(ChatFormatting.GRAY)); - tooltipComponents.add(Component.translatable("tooltip.antarchy.portal_gun.grab_strength", getGrabStrength(stack)).withStyle(ChatFormatting.GRAY)); } @Override @@ -809,7 +755,7 @@ public class PortalGunItem extends Item implements GeoItem { @Override public net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer getGeoItemRenderer() { if (this.renderer == null) { - this.renderer = new AnimatedHeldItemRenderer<>(new ResourceBackedGeoItemModel<>(MODEL_LOCATION, TEXTURE_LOCATION, ANIMATION_LOCATION)); + this.renderer = new AnimatedHeldItemRenderer<>(new ResourceBackedGeoItemModel<>(MODEL_LOCATION, PortalGunItem.this.variant.modelTexture(), ANIMATION_LOCATION)); } return this.renderer; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabPayload.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabPayload.java deleted file mode 100644 index 410ba1c3..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabPayload.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.craisinlord.antarchy.content.network; - -import com.craisinlord.antarchy.Antarchy; -import io.netty.buffer.ByteBuf; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; - -public record PortalGunGrabPayload() implements CustomPacketPayload { - public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "portal_gun_grab")); - public static final StreamCodec STREAM_CODEC = StreamCodec.unit(new PortalGunGrabPayload()); - - @Override - public Type type() { - return TYPE; - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabStatePayload.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabStatePayload.java deleted file mode 100644 index 04097b63..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunGrabStatePayload.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.craisinlord.antarchy.content.network; - -import com.craisinlord.antarchy.Antarchy; -import io.netty.buffer.ByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; - -public record PortalGunGrabStatePayload(boolean active) implements CustomPacketPayload { - public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "portal_gun_grab_state")); - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.BOOL, PortalGunGrabStatePayload::active, PortalGunGrabStatePayload::new - ); - - @Override - public Type type() { - return TYPE; - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunTransitPayload.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunTransitPayload.java new file mode 100644 index 00000000..8e6cd584 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/network/PortalGunTransitPayload.java @@ -0,0 +1,43 @@ +package com.craisinlord.antarchy.content.network; + +import com.craisinlord.antarchy.Antarchy; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; + +public record PortalGunTransitPayload(int portalId, Vec3 start, Vec3 end, Vec3 velocity) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "portal_gun_transit")); + public static final StreamCodec STREAM_CODEC = StreamCodec.of(PortalGunTransitPayload::write, PortalGunTransitPayload::read); + + private static void write(ByteBuf buffer, PortalGunTransitPayload payload) { + buffer.writeInt(payload.portalId()); + writeVec(buffer, payload.start()); + writeVec(buffer, payload.end()); + writeVec(buffer, payload.velocity()); + } + + private static PortalGunTransitPayload read(ByteBuf buffer) { + int portalId = buffer.readInt(); + Vec3 start = readVec(buffer); + Vec3 end = readVec(buffer); + Vec3 velocity = readVec(buffer); + return new PortalGunTransitPayload(portalId, start, end, velocity); + } + + private static void writeVec(ByteBuf buffer, Vec3 vector) { + buffer.writeDouble(vector.x); + buffer.writeDouble(vector.y); + buffer.writeDouble(vector.z); + } + + private static Vec3 readVec(ByteBuf buffer) { + return new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + } + + @Override + public Type type() { + return TYPE; + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunCollisionHelper.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunCollisionHelper.java index bad8617d..63ffe32b 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunCollisionHelper.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunCollisionHelper.java @@ -43,9 +43,6 @@ public final class PortalGunCollisionHelper { return collided; } PortalGunWorldPortalShape shape = portal.getWorldPortalShape(); - if (canWalkIntoFloorPortal(startBox, movement, portal, shape)) { - return movement; - } Vec3 normal = portal.getNormalVec().normalize(); double desiredNormal = movement.dot(normal); double collidedNormal = collided.dot(normal); @@ -60,29 +57,6 @@ public final class PortalGunCollisionHelper { return applyBorderCollision(entity, startBox, adjusted, portal); } - private static boolean canWalkIntoFloorPortal(AABB startBox, Vec3 movement, PortalGunPortalEntity portal, PortalGunWorldPortalShape shape) { - Vec3 normal = portal.getNormalVec().normalize(); - if (Math.abs(normal.y) < 0.9D) { - return false; - } - AABB endBox = startBox.move(movement); - return overlapsPortalOpeningFromSurface(startBox, shape) || overlapsPortalOpeningFromSurface(endBox, shape); - } - - private static boolean overlapsPortalOpeningFromSurface(AABB box, PortalGunWorldPortalShape shape) { - if (!shape.intersectsPortalColumn(box, EDGE_PADDING, EDGE_PADDING, PLANE_TOLERANCE)) { - return false; - } - double minDepth = Double.POSITIVE_INFINITY; - double maxDepth = Double.NEGATIVE_INFINITY; - for (Vec3 corner : corners(box)) { - double depth = shape.localCoords(corner).depth(); - minDepth = Math.min(minDepth, depth); - maxDepth = Math.max(maxDepth, depth); - } - return maxDepth > 0.0D && minDepth >= -PLANE_TOLERANCE; - } - private static boolean canUsePortalPassThrough(Entity entity, AABB startBox, Vec3 movement, PortalGunPortalEntity portal, PortalGunWorldPortalShape shape) { AABB endBox = startBox.move(movement); if (!portal.getPortalInsides(entity).intersects(startBox) diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunGrabManager.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunGrabManager.java deleted file mode 100644 index 084a842d..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunGrabManager.java +++ /dev/null @@ -1,280 +0,0 @@ -package com.craisinlord.antarchy.content.portalgun; - -import com.craisinlord.antarchy.content.item.PortalGunItem; -import com.craisinlord.antarchy.content.AntarchyTags; -import com.craisinlord.antarchy.Antarchy; -import com.craisinlord.antarchy.config.AntarchySettings; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.item.FallingBlockEntity; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.MoverType; -import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.block.RenderShape; -import net.minecraft.world.level.ClipContext; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.HitResult; -import net.minecraft.world.phys.Vec3; -import java.util.function.BiConsumer; -import com.craisinlord.antarchy.content.network.PortalGunGrabStatePayload; - -public final class PortalGunGrabManager { - private static final double REACH = 5.0D; - private static final double BASE_HOLD_DISTANCE = 3.5D; - private static final double MAX_HOLD_DISTANCE = 6.0D; - private static final Map GRABS = new HashMap<>(); - private static BiConsumer stateSender = (player, payload) -> {}; - - private PortalGunGrabManager() { - } - - public static void setStateSender(BiConsumer sender) { - stateSender = sender; - } - - public static void toggle(ServerPlayer player) { - GrabState active = GRABS.remove(player.getUUID()); - if (active != null) { - release(active); - stateSender.accept(player, new PortalGunGrabStatePayload(false)); - return; - } - ItemStack gunStack = getHeldPortalGun(player); - if (gunStack.isEmpty()) { - return; - } - int grabStrength = PortalGunItem.getGrabStrength(gunStack); - Entity target = findTarget(player, grabStrength); - if (target == null) { - target = findBlockTarget(player, grabStrength); - if (target == null) { - return; - } - } - for (Map.Entry entry : new HashMap<>(GRABS).entrySet()) { - if (entry.getValue().target() == target) { - GRABS.remove(entry.getKey()); - release(entry.getValue()); - ServerPlayer previousHolder = player.serverLevel().getServer().getPlayerList().getPlayer(entry.getKey()); - if (previousHolder != null) { - stateSender.accept(previousHolder, new PortalGunGrabStatePayload(false)); - } - } - } - double holdDistance = BASE_HOLD_DISTANCE; - if (target.getBbWidth() > 2.0F) { - holdDistance = Math.min(MAX_HOLD_DISTANCE, holdDistance + target.getBbWidth() - 2.0D); - } - GrabState state = new GrabState(player.getUUID(), player.serverLevel(), target, holdDistance, target.isNoGravity()); - GRABS.put(player.getUUID(), state); - target.setNoGravity(true); - stateSender.accept(player, new PortalGunGrabStatePayload(true)); - } - - public static void tick(MinecraftServer server) { - for (Map.Entry entry : new HashMap<>(GRABS).entrySet()) { - GrabState state = entry.getValue(); - ServerPlayer player = server.getPlayerList().getPlayer(state.playerId()); - Entity target = state.target(); - if (player == null || !player.isAlive() || player.serverLevel() != state.level() || !isHoldingPortalGun(player) - || !target.isAlive() || target.isRemoved() || target.level() != state.level() - || target.distanceTo(player) > state.holdDistance() + 6.25D) { - GRABS.remove(entry.getKey()); - release(state); - if (player != null) { - stateSender.accept(player, new PortalGunGrabStatePayload(false)); - } - continue; - } - Vec3 holdPosition = player.getEyePosition(1.0F).add(player.getLookAngle().scale(state.holdDistance())); - if (target.position().distanceTo(holdPosition) > 5.0D) { - target.teleportTo(player.getX(), player.getY(), player.getZ()); - } - Vec3 velocity = holdPosition.subtract(target.getX(), target.getBoundingBox().getCenter().y, target.getZ()); - target.setDeltaMovement(velocity); - target.move(MoverType.SELF, velocity); - velocity = holdPosition.subtract(target.getX(), target.getBoundingBox().getCenter().y, target.getZ()); - target.setDeltaMovement(velocity); - target.setNoGravity(true); - if (target instanceof FallingBlockEntity fallingBlock) { - fallingBlock.time = 2; - } - if (target instanceof AbstractHurtingProjectile projectile) { - projectile.accelerationPower = 0.0D; - } - target.fallDistance = (float) -(velocity.y * velocity.y); - target.setOnGround(false); - target.hasImpulse = true; - target.hurtMarked = true; - } - } - - public static void clear(MinecraftServer server) { - for (GrabState state : GRABS.values()) { - release(state); - ServerPlayer player = server.getPlayerList().getPlayer(state.playerId()); - if (player != null) { - stateSender.accept(player, new PortalGunGrabStatePayload(false)); - } - } - GRABS.clear(); - } - - private static Entity findTarget(ServerPlayer player, int grabStrength) { - Vec3 start = player.getEyePosition(); - Vec3 look = player.getLookAngle(); - Vec3 end = start.add(look.scale(REACH)); - BlockHitResult blockHit = player.serverLevel().clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player)); - double maxDistance = blockHit.getType() == HitResult.Type.BLOCK ? start.distanceTo(blockHit.getLocation()) : REACH; - AABB searchBounds = player.getBoundingBox().expandTowards(look.scale(maxDistance)).inflate(1.0D); - EntityHitResult closest = null; - double closestDistance = maxDistance * maxDistance; - for (Entity candidate : player.serverLevel().getEntities(player, searchBounds, entity -> canGrab(entity, grabStrength))) { - var hit = candidate.getBoundingBox().inflate(candidate.getPickRadius()).clip(start, end); - if (hit.isEmpty()) { - continue; - } - double distance = start.distanceToSqr(hit.get()); - if (distance < closestDistance) { - closestDistance = distance; - closest = new EntityHitResult(candidate, hit.get()); - } - } - return closest == null ? null : closest.getEntity(); - } - - private static Entity findBlockTarget(ServerPlayer player, int grabStrength) { - if (grabStrength < 2) { - return null; - } - Vec3 start = player.getEyePosition(); - Vec3 end = start.add(player.getLookAngle().scale(REACH)); - BlockHitResult hit = player.serverLevel().clip(new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); - if (hit.getType() != HitResult.Type.BLOCK) { - return null; - } - BlockPos pos = hit.getBlockPos(); - ServerLevel level = player.serverLevel(); - BlockState state = level.getBlockState(pos); - if (state.isAir() || state.is(AntarchyTags.Blocks.GRAVITY_GUN_BLACKLIST)) { - return null; - } - BlockPos basePos = pos; - BlockPos upperPos = null; - if (state.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF)) { - basePos = state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.UPPER ? pos.below() : pos; - BlockState baseState = level.getBlockState(basePos); - BlockPos candidateUpper = basePos.above(); - BlockState upperState = level.getBlockState(candidateUpper); - if (!baseState.is(state.getBlock()) || !baseState.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF) - || baseState.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) != DoubleBlockHalf.LOWER - || !upperState.is(state.getBlock()) || !upperState.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF) - || upperState.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) != DoubleBlockHalf.UPPER) { - return null; - } - state = baseState; - upperPos = candidateUpper; - } - if (state.getDestroySpeed(level, basePos) < 0.0F) { - return null; - } - if (AntarchySettings.portalGunEntityGrabWeightBase() == 0 - && !Antarchy.MODID.equals(BuiltInRegistries.BLOCK.getKey(state.getBlock()).getNamespace())) { - return null; - } - BlockEntity blockEntity = level.getBlockEntity(basePos); - if (blockEntity != null && grabStrength < 3) { - return null; - } - if (!state.isSolidRender(level, basePos) - && state.getRenderShape() != RenderShape.ENTITYBLOCK_ANIMATED - && !state.is(Blocks.SNOW) - && !state.is(Blocks.GLOWSTONE) - && !state.is(Blocks.CAKE) - && !state.is(Blocks.TNT) - && !state.is(Blocks.ICE) - && !state.is(BlockTags.SLABS) - && !state.is(Blocks.ANVIL) - && !state.is(BlockTags.STAIRS)) { - return null; - } - CompoundTag blockEntityData = blockEntity == null ? null : blockEntity.saveWithId(level.registryAccess()); - if (blockEntity != null) { - level.removeBlockEntity(basePos); - } - if (upperPos != null) { - level.removeBlock(upperPos, false); - } - FallingBlockEntity fallingBlock = FallingBlockEntity.fall(level, basePos, state); - if (fallingBlock == null) { - return null; - } - if (blockEntityData != null) { - fallingBlock.blockData = blockEntityData; - } - fallingBlock.setDeltaMovement(Vec3.ZERO); - fallingBlock.setNoGravity(true); - fallingBlock.hurtMarked = true; - return fallingBlock; - } - - private static boolean canGrab(Entity entity, int grabStrength) { - if (!entity.isAlive() || entity instanceof Player || entity instanceof PortalGunPortalEntity || entity.isPassenger()) { - return false; - } - double volume = entity.getBbWidth() * entity.getBbHeight() * entity.getBbWidth(); - double strengthScale = switch (grabStrength) { - case 1 -> 1.0D; - case 2 -> 1.5D; - case 3 -> 2.25D; - default -> 3.0D; - }; - int grabWeightBase = AntarchySettings.portalGunEntityGrabWeightBase(); - boolean modEntityExempt = grabWeightBase == 0 - && Antarchy.MODID.equals(BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).getNamespace()); - return (modEntityExempt || Math.cbrt(volume) < grabWeightBase * strengthScale / 100.0D) && entity.isPickable(); - } - - private static ItemStack getHeldPortalGun(ServerPlayer player) { - if (player.getMainHandItem().getItem() instanceof PortalGunItem) { - return player.getMainHandItem(); - } - if (player.getOffhandItem().getItem() instanceof PortalGunItem) { - return player.getOffhandItem(); - } - return ItemStack.EMPTY; - } - - private static boolean isHoldingPortalGun(ServerPlayer player) { - return !getHeldPortalGun(player).isEmpty(); - } - - private static void release(GrabState state) { - Entity target = state.target(); - if (target.isAlive() && !target.isRemoved()) { - target.setNoGravity(state.hadNoGravity()); - target.hasImpulse = true; - target.hurtMarked = true; - } - } - - private record GrabState(UUID playerId, ServerLevel level, Entity target, double holdDistance, boolean hadNoGravity) { - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java index 84e94568..d5333c4f 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java @@ -27,20 +27,15 @@ public final class PortalGunIndicatorSync { if (stack.isEmpty()) { return; } - UUID ownerId = PortalGunItem.getPortalOwnerId(stack, player.getUUID()); boolean blue = PortalGunSavedData.getPortalId( player.serverLevel().getServer(), - ownerId, request.gunId(), - PortalGunItem.getChannelName(stack), PortalGunPortalEntity.PortalSide.BLUE, player.serverLevel().dimension().location() ).isPresent(); boolean orange = PortalGunSavedData.getPortalId( player.serverLevel().getServer(), - ownerId, request.gunId(), - PortalGunItem.getChannelName(stack), PortalGunPortalEntity.PortalSide.ORANGE, player.serverLevel().dimension().location() ).isPresent(); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java index a888ddbd..c8219617 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java @@ -1,22 +1,26 @@ package com.craisinlord.antarchy.content.portalgun; import com.craisinlord.antarchy.Antarchy; +import com.craisinlord.antarchy.config.AntarchySettings; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; import com.craisinlord.antarchy.content.block.entity.PortalGunPortalBaseBlockEntity; import com.craisinlord.antarchy.content.block.entity.PortalGunPortalCellAccess; import com.craisinlord.antarchy.content.block.entity.PortalGunPortalFaceRecord; import com.craisinlord.antarchy.content.block.entity.PortalGunPortalMasterBlockEntity; import com.craisinlord.antarchy.mixins.AbstractArrowAccessor; import com.craisinlord.antarchy.mixins.FallingBlockEntityAccessor; +import com.craisinlord.antarchy.mixins.ServerGamePacketListenerTeleportAccessor; +import com.craisinlord.antarchy.mixins.gravity.ChunkMapAccessor; +import com.craisinlord.antarchy.mixins.gravity.ServerEntityAccessor; +import com.craisinlord.antarchy.mixins.gravity.TrackedEntityAccessor; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Random; import java.util.Set; import java.util.UUID; -import java.awt.Color; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.registries.BuiltInRegistries; @@ -40,11 +44,13 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import software.bernie.geckolib.animatable.GeoEntity; import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; @@ -64,14 +70,11 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { private static final EntityDataAccessor SIDE = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor> OWNER_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.OPTIONAL_UUID); private static final EntityDataAccessor> GUN_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.OPTIONAL_UUID); - private static final EntityDataAccessor CHANNEL_NAME = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.STRING); private static final EntityDataAccessor FACING = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor UP_AXIS = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor> LINKED_PORTAL = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.OPTIONAL_UUID); private static final EntityDataAccessor LINKED_PORTAL_ENTITY_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); - private static final EntityDataAccessor CHANNEL_RED = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); - private static final EntityDataAccessor CHANNEL_GREEN = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); - private static final EntityDataAccessor CHANNEL_BLUE = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor PORTAL_WIDTH = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor PORTAL_HEIGHT = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor OPENING_ANIMATION_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); @@ -81,14 +84,14 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { public static final int TELEPORT_COOLDOWN_TICKS = 3; private static final String DEBUG_TRAVERSAL_PROPERTY = "antarchy.portalGun.debugTraversal"; private static final double PORTAL_INSIDE_SHIFT = 0.05D; - private static final Set LOGGED_CROSSING_PATHS = new HashSet<>(); private static final double HALF_DEPTH = 0.35D; + private static final double MAX_CLIENT_TRANSIT_START_ERROR_SQR = 1.0D; + private static final double MAX_CLIENT_TRANSIT_MOVEMENT_SQR = 100.0D; + private static final double PROJECTILE_PLANE_TOLERANCE = 0.1D; private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); private final Map teleportCooldowns = new HashMap<>(); private UUID ownerId; - private String ownerIdentity; private UUID gunId; - private String channelName; private UUID linkedPortalId; private int ageTicks; private int lastOpeningAnimationId; @@ -98,6 +101,12 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { private BlockPos basePos = BlockPos.ZERO; private BlockPos[] portalSpots = new BlockPos[] {BlockPos.ZERO, BlockPos.ZERO}; private Set compensatedSpots = Set.of(); + private PortalGunWorldPortalShape cachedShape; + private Vec3 cachedShapePosition; + private int cachedShapeFacing; + private int cachedShapeUpAxis; + private int cachedShapeWidth; + private int cachedShapeHeight; public PortalGunPortalEntity(EntityType entityType, Level level) { super(entityType, level); @@ -111,36 +120,27 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { builder.define(SIDE, PortalSide.BLUE.ordinal()); builder.define(OWNER_ID, Optional.empty()); builder.define(GUN_ID, Optional.empty()); - builder.define(CHANNEL_NAME, ""); builder.define(FACING, Direction.NORTH.get3DDataValue()); builder.define(UP_AXIS, Direction.UP.get3DDataValue()); builder.define(LINKED_PORTAL, Optional.empty()); builder.define(LINKED_PORTAL_ENTITY_ID, -1); - builder.define(CHANNEL_RED, 58); - builder.define(CHANNEL_GREEN, 166); - builder.define(CHANNEL_BLUE, 255); + builder.define(VARIANT, PortalGunVariant.DEFAULT.id()); builder.define(PORTAL_WIDTH, 1); builder.define(PORTAL_HEIGHT, 2); builder.define(OPENING_ANIMATION_ID, 0); } - public void configure(UUID ownerId, UUID gunId, String ownerIdentity, String channelName, PortalSide side, PortalGunPlacement placement) { + public void configure(UUID ownerId, UUID gunId, PortalGunVariant variant, PortalSide side, PortalGunPlacement placement) { this.ownerId = ownerId; - this.ownerIdentity = ownerIdentity; this.gunId = gunId; - this.channelName = channelName; this.entityData.set(OWNER_ID, Optional.ofNullable(ownerId)); this.entityData.set(GUN_ID, Optional.ofNullable(gunId)); - this.entityData.set(CHANNEL_NAME, channelName == null ? "" : channelName); + this.entityData.set(VARIANT, (variant == null ? PortalGunVariant.DEFAULT : variant).id()); this.entityData.set(SIDE, side.ordinal()); this.entityData.set(FACING, placement.facing().get3DDataValue()); this.entityData.set(UP_AXIS, placement.upAxis().get3DDataValue()); this.entityData.set(PORTAL_WIDTH, placement.width()); this.entityData.set(PORTAL_HEIGHT, placement.height()); - int[] channelColor = generateChannelColor(ownerIdentity, channelName, side); - this.entityData.set(CHANNEL_RED, channelColor[0]); - this.entityData.set(CHANNEL_GREEN, channelColor[1]); - this.entityData.set(CHANNEL_BLUE, channelColor[2]); this.supportOrigin = placement.supportOrigin().immutable(); this.masterPos = placement.masterPos().immutable(); this.basePos = placement.basePos().immutable(); @@ -191,50 +191,12 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { return this.entityData.get(GUN_ID).orElse(this.gunId); } - public String getChannelName() { - String synchronizedName = this.entityData.get(CHANNEL_NAME); - return synchronizedName.isEmpty() ? this.channelName : synchronizedName; + public PortalGunVariant getVariant() { + return PortalGunVariant.byId(this.entityData.get(VARIANT)); } - public void adoptChannelIdentity(UUID gunId, String channelName) { - if (this.gunId == null && gunId != null) { - this.gunId = gunId; - this.entityData.set(GUN_ID, Optional.of(gunId)); - } - if (channelName != null && !channelName.isEmpty() && !channelName.equals(this.channelName)) { - this.channelName = channelName; - this.entityData.set(CHANNEL_NAME, channelName); - } - if (this.level() instanceof ServerLevel serverLevel && serverLevel.hasChunkAt(this.masterPos) - && serverLevel.getBlockEntity(this.masterPos) instanceof PortalGunPortalMasterBlockEntity master - && this.getUUID().equals(master.getPortalId())) { - master.adoptChannelIdentity(gunId, channelName); - } - } - - public void adoptGunId(UUID gunId) { - if (this.gunId != null || gunId == null) { - return; - } - this.gunId = gunId; - this.entityData.set(GUN_ID, Optional.of(gunId)); - if (this.level() instanceof ServerLevel serverLevel && serverLevel.hasChunkAt(this.masterPos) - && serverLevel.getBlockEntity(this.masterPos) instanceof com.craisinlord.antarchy.content.block.entity.PortalGunPortalMasterBlockEntity master - && this.getUUID().equals(master.getPortalId())) { - master.adoptGunId(gunId); - } - } - - public int getChannelRed() { - return this.entityData.get(CHANNEL_RED); - } - - public int getChannelGreen() { - return this.entityData.get(CHANNEL_GREEN); - } - - public int getChannelBlue() { - return this.entityData.get(CHANNEL_BLUE); + public int getPortalColor() { + return this.getVariant().color(this.getPortalSide()); } public BlockPos getBasePos() { @@ -278,17 +240,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { if (linkedId == null) { return null; } - Entity linkedEntity; if (this.level() instanceof ServerLevel serverLevel) { - linkedEntity = serverLevel.getEntity(linkedId); - } else { - int linkedEntityId = this.entityData.get(LINKED_PORTAL_ENTITY_ID); - if (linkedEntityId < 0) { - return null; - } - linkedEntity = this.level().getEntity(linkedEntityId); + return serverLevel.getEntity(linkedId) instanceof PortalGunPortalEntity portal && !portal.isRemoved() ? portal : null; } - return linkedEntity instanceof PortalGunPortalEntity portal && !portal.isRemoved() ? portal : null; + return PortalGunPortalRegistry.find(this.level(), linkedId); } public Vec3 getNormalVec() { @@ -304,7 +259,23 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { } public PortalGunWorldPortalShape getWorldPortalShape() { - return new PortalGunWorldPortalShape(this.position(), this.getNormalVec().normalize(), this.getUpVec().normalize(), this.getWidthVec().normalize(), this.getPortalWidth() / 2.0D, this.getPortalHeight() / 2.0D, HALF_DEPTH); + Vec3 position = this.position(); + int facing = this.entityData.get(FACING); + int upAxis = this.entityData.get(UP_AXIS); + int width = this.getPortalWidth(); + int height = this.getPortalHeight(); + PortalGunWorldPortalShape shape = this.cachedShape; + if (shape == null || !position.equals(this.cachedShapePosition) || facing != this.cachedShapeFacing + || upAxis != this.cachedShapeUpAxis || width != this.cachedShapeWidth || height != this.cachedShapeHeight) { + shape = new PortalGunWorldPortalShape(position, this.getNormalVec().normalize(), this.getUpVec().normalize(), this.getWidthVec().normalize(), width / 2.0D, height / 2.0D, HALF_DEPTH); + this.cachedShape = shape; + this.cachedShapePosition = position; + this.cachedShapeFacing = facing; + this.cachedShapeUpAxis = upAxis; + this.cachedShapeWidth = width; + this.cachedShapeHeight = height; + } + return shape; } public AABB getPlane() { @@ -354,72 +325,66 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { return entity instanceof LivingEntity living ? living.getEyeHeight(living.getPose()) : entity.getEyeHeight(); } - public PortalCrossing resolveCrossing(Entity entity, AABB previousBox, AABB currentBox) { - Vec3 previousProbe = this.teleportProbePosition(entity, previousBox); - Vec3 currentProbe = this.teleportProbePosition(entity, currentBox); - if (entity instanceof Player) { - PortalGunWorldPortalShape shape = this.getWorldPortalShape(); - Vec3 center = currentBox.getCenter(); - PortalGunWorldPortalShape.PortalLocalCoords localCenter = shape.localCoords(center); - double previousDepth = shape.localCoords(previousBox.getCenter()).depth(); - double currentDepth = localCenter.depth(); - double halfX = (currentBox.maxX - currentBox.minX) * 0.5D; - double halfY = (currentBox.maxY - currentBox.minY) * 0.5D; - double halfZ = (currentBox.maxZ - currentBox.minZ) * 0.5D; - double depthExtent = halfX * Math.abs(shape.normal().x) + halfY * Math.abs(shape.normal().y) + halfZ * Math.abs(shape.normal().z); - if (previousDepth <= 0.0D || currentDepth >= previousDepth - 1.0E-6D - || currentDepth - depthExtent > 0.02D || currentDepth < -shape.halfDepth()) { - return null; - } - double widthExtent = halfX * Math.abs(shape.right().x) + halfY * Math.abs(shape.right().y) + halfZ * Math.abs(shape.right().z); - double heightExtent = halfX * Math.abs(shape.up().x) + halfY * Math.abs(shape.up().y) + halfZ * Math.abs(shape.up().z); - if (Math.abs(localCenter.horizontal()) + widthExtent > shape.halfWidth() + 1.0E-3D - || Math.abs(localCenter.vertical()) + heightExtent > shape.halfHeight() + 1.0E-3D) { - return null; - } - return new PortalCrossing(currentProbe, Math.max(0.05D, shape.localCoords(currentProbe).depth() + 0.05D)); + public PortalCrossing resolveCrossing(Entity entity, AABB previousBox, AABB currentBox, Vec3 attemptedMovement) { + PortalGunWorldPortalShape shape = this.getWorldPortalShape(); + if (!PortalGunTransitMath.crossesWithBody(shape, previousBox, currentBox, attemptedMovement)) { + return null; } - return this.crossesPortal(previousProbe, currentProbe) ? new PortalCrossing(currentProbe, 0.0D) : null; + return new PortalCrossing(this.teleportProbePosition(entity, currentBox)); } - public Vec3 resolveCrossingProbe(Entity entity) { - AABB currentBox = entity.getBoundingBox(); - AABB previousBox = currentBox.move(entity.xo - entity.getX(), entity.yo - entity.getY(), entity.zo - entity.getZ()); - PortalCrossing crossing = this.resolveCrossing(entity, previousBox, currentBox); - return crossing == null ? null : crossing.probe(); + public PortalTransit computeTransit(PortalGunPortalEntity destination, AABB box, Vec3 velocity, Vec3 look) { + PortalGunWorldPortalShape source = this.getWorldPortalShape(); + PortalGunWorldPortalShape target = destination.getWorldPortalShape(); + AABB exitBox = PortalGunTransitMath.exitBox(source, target, box); + Vec3 exitVelocity = PortalGunTransitMath.exitVelocity(source, target, velocity, + AntarchySettings.portalGunMinFloorExitSpeed(), AntarchySettings.portalGunMaxExitSpeed()); + Vec3 exitLook = PortalGunTransitMath.transformVector(source, target, look).normalize(); + return new PortalTransit(exitBox, PortalGunTransitMath.feetPosition(exitBox), exitVelocity, exitLook); } - public PortalTransitTransform previewTransit(Entity entity, PortalGunPortalEntity destination, PortalCrossing crossing, Vec3 movement) { - Vec3 sourcePlaneCenter = this.position().add(this.getNormalVec().normalize().scale(crossing.normalOffset())); - Vec3 destinationPlaneCenter = destination.position().add(destination.getNormalVec().normalize().scale(crossing.normalOffset())); - Vec3 relativeProbe = crossing.probe().subtract(sourcePlaneCenter); - Vec3 transformedProbe = PortalGunTransformUtil.transformPosition(this, destination, relativeProbe); - Vec3 entityOffset = PortalGunTransformUtil.transformVector(this, destination, entity.position().subtract(crossing.probe())); - Vec3 requestedPosition = destinationPlaneCenter.add(transformedProbe).add(entityOffset); - Vec3 transformedMovement = PortalGunTransformUtil.transformVector(this, destination, movement); - Vec3 exitPosition = putEntityWithinExitBounds(entity, requestedPosition, legacyExitBounds(destination, entity, destination.getNormalVec().normalize())); - return new PortalTransitTransform(requestedPosition, exitPosition, transformedMovement); + public PortalTransit computeTransit(Entity entity, PortalGunPortalEntity destination, AABB box, Vec3 velocity, Vec3 look) { + if (!AntarchyGravityApi.isGravityInverted(entity)) { + return computeTransit(destination, box, velocity, look); + } + PortalGunWorldPortalShape source = this.getWorldPortalShape(); + PortalGunWorldPortalShape target = destination.getWorldPortalShape(); + AABB exitBox = PortalGunTransitMath.exitBox(source, target, box); + Vec3 worldVelocity = PortalGunTransitMath.entityVelocityToWorld(entity, velocity); + Vec3 worldExitVelocity = PortalGunTransitMath.exitVelocity(source, target, worldVelocity, + AntarchySettings.portalGunMinFloorExitSpeed(), AntarchySettings.portalGunMaxExitSpeed()); + Vec3 exitVelocity = PortalGunTransitMath.entityVelocityFromWorld(entity, worldExitVelocity); + Vec3 worldLook = PortalGunTransitMath.entityVelocityToWorld(entity, look); + Vec3 worldExitLook = PortalGunTransitMath.transformVector(source, target, worldLook).normalize(); + Vec3 exitLook = PortalGunTransitMath.entityVelocityFromWorld(entity, worldExitLook); + return new PortalTransit(exitBox, PortalGunTransitMath.entityPosition(exitBox, entity), exitVelocity, exitLook); } - public static void teleportEntityAfterMovement(Entity entity, AABB previousBox, Vec3 resolvedMovement) { - if (entity instanceof ServerPlayer) { + public static void teleportEntityAfterMovement(Entity entity, AABB previousBox, Vec3 velocity) { + if (entity instanceof Player) { return; } - teleportAfterMovement(entity, previousBox, entity.getBoundingBox(), resolvedMovement); + teleportAfterMovement(entity, previousBox, entity.getBoundingBox(), velocity); } public static void teleportPlayerAfterMovementPacket(ServerPlayer player, AABB previousBox, Vec3 claimedMovement) { - teleportAfterMovement(player, previousBox, previousBox.move(claimedMovement), claimedMovement); + Vec3 transitVelocity = PortalGunTransitMath.entityVelocityFromWorld(player, claimedMovement); + teleportAfterMovement(player, previousBox, previousBox.move(claimedMovement), transitVelocity, claimedMovement); } - private static void teleportAfterMovement(Entity entity, AABB previousBox, AABB currentBox, Vec3 resolvedMovement) { + private static void teleportAfterMovement(Entity entity, AABB previousBox, AABB currentBox, Vec3 velocity) { + teleportAfterMovement(entity, previousBox, currentBox, velocity, + PortalGunTransitMath.entityVelocityToWorld(entity, velocity)); + } + + private static void teleportAfterMovement(Entity entity, AABB previousBox, AABB currentBox, Vec3 velocity, Vec3 attemptedMovement) { if (entity.level().isClientSide || !entity.isAlive() || entity.isPassenger() || entity instanceof PortalGunPortalEntity) { return; } - if (previousBox.getCenter().distanceToSqr(currentBox.getCenter()) <= 1.0E-10D) { + if (velocity.lengthSqr() <= 1.0E-12D && previousBox.getCenter().distanceToSqr(currentBox.getCenter()) <= 1.0E-10D) { return; } - AABB sweptBounds = previousBox.minmax(currentBox).inflate(1.0D); + AABB sweptBounds = previousBox.minmax(currentBox).expandTowards(attemptedMovement).inflate(1.0D); for (PortalGunPortalEntity portal : findPortalsNearBounds(entity.level(), sweptBounds)) { if (!(portal.level() instanceof ServerLevel serverLevel) || !portal.canTeleportEntity(entity)) { continue; @@ -428,28 +393,132 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { if (linked == null || !linked.isAlive()) { continue; } - PortalCrossing crossing = portal.resolveCrossing(entity, previousBox, currentBox); + PortalCrossing crossing = portal.resolveCrossing(entity, previousBox, currentBox, attemptedMovement); if (crossing != null) { if (entity instanceof Player && Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY)) { - Antarchy.LOGGER.info("Portal gun traversal accepted path=movement portal={} player={} probe={} offset={} linked={}", - portal.getUUID(), entity.getUUID(), crossing.probe(), crossing.normalOffset(), linked.getUUID()); + Antarchy.LOGGER.info("Portal gun traversal accepted path=server portal={} player={} probe={} linked={}", + portal.getUUID(), entity.getUUID(), crossing.probe(), linked.getUUID()); } - logCrossingPath(entity, "movement"); - portal.teleportEntity(entity, linked, crossing.probe(), resolvedMovement, crossing.normalOffset()); + portal.teleportEntity(entity, linked, currentBox, velocity, false); return; } } } + public static boolean handleClientTransit(ServerPlayer player, int portalId, Vec3 start, Vec3 end, Vec3 velocity) { + if (!player.isAlive() || player.isPassenger() || player.isSpectator()) { + return false; + } + if (((ServerGamePacketListenerTeleportAccessor) player.connection).antarchy$getAwaitingPositionFromClient() != null) { + return true; + } + if (!isFinite(start) || !isFinite(end) || !isFinite(velocity) + || start.distanceToSqr(player.position()) > MAX_CLIENT_TRANSIT_START_ERROR_SQR + || end.distanceToSqr(start) > MAX_CLIENT_TRANSIT_MOVEMENT_SQR + || velocity.lengthSqr() > MAX_CLIENT_TRANSIT_MOVEMENT_SQR) { + return false; + } + if (!(player.level() instanceof ServerLevel serverLevel) + || !(serverLevel.getEntity(portalId) instanceof PortalGunPortalEntity portal) + || !portal.isAlive()) { + return false; + } + PortalGunPortalEntity linked = portal.findLinkedPortal(serverLevel); + if (linked == null || !linked.isAlive()) { + return false; + } + AABB startBox = player.getBoundingBox().move(start.subtract(player.position())); + AABB endBox = startBox.move(end.subtract(start)); + Vec3 crossingVelocity = PortalGunTransitMath.entityVelocityToWorld(player, velocity); + if (portal.resolveCrossing(player, startBox, endBox, crossingVelocity) == null) { + return false; + } + if (Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY)) { + Antarchy.LOGGER.info("Portal gun traversal accepted path=client portal={} player={} end={} velocity={} linked={}", + portal.getUUID(), player.getUUID(), end, velocity, linked.getUUID()); + } + portal.teleportEntity(player, linked, endBox, velocity, true); + return true; + } + + public static boolean passProjectileThroughPortal(Projectile projectile, BlockHitResult hit) { + if (projectile instanceof PortalGunProjectileEntity || projectile.isRemoved() || projectile.isPassenger()) { + return false; + } + Vec3 location = hit.getLocation(); + Vec3 velocity = projectile.getDeltaMovement(); + for (PortalGunPortalEntity portal : findPortalsNearBounds(projectile.level(), new AABB(location, location).inflate(0.5D))) { + if (portal.getFacingDirection() != hit.getDirection() || portal.isTeleportCoolingDown(projectile)) { + continue; + } + PortalGunWorldPortalShape shape = portal.getWorldPortalShape(); + PortalGunWorldPortalShape.PortalLocalCoords coords = shape.localCoords(location); + if (Math.abs(coords.depth()) > PROJECTILE_PLANE_TOLERANCE + || Math.abs(coords.horizontal()) > shape.halfWidth() + || Math.abs(coords.vertical()) > shape.halfHeight() + || velocity.dot(shape.normal()) >= 0.0D) { + continue; + } + PortalGunPortalEntity linked = projectile.level() instanceof ServerLevel serverLevel ? portal.findLinkedPortal(serverLevel) : portal.getLinkedPortal(); + if (linked == null || !linked.isAlive()) { + continue; + } + AABB crossingBox = projectile.getBoundingBox().move(location.subtract(projectile.position())); + if (projectile.level().isClientSide) { + PortalTransit transit = portal.computeTransit(projectile, linked, crossingBox, velocity, projectile.getLookAngle()); + Vec3 exit = transit.position(); + projectile.setPos(exit.x, exit.y, exit.z); + projectile.xo = exit.x; + projectile.yo = exit.y; + projectile.zo = exit.z; + projectile.setDeltaMovement(transit.velocity()); + orientAlongVelocity(projectile, transit.velocity()); + projectile.setPortalCooldown(TELEPORT_COOLDOWN_TICKS); + } else { + portal.teleportEntity(projectile, linked, crossingBox, velocity, false); + } + return true; + } + return false; + } + + private static void orientAlongVelocity(Entity entity, Vec3 velocity) { + if (velocity.lengthSqr() < 1.0E-12D) { + return; + } + float yaw = (float) Math.toDegrees(Math.atan2(velocity.x, velocity.z)); + float pitch = (float) Math.toDegrees(Math.atan2(velocity.y, velocity.horizontalDistance())); + entity.setYRot(yaw); + entity.setXRot(pitch); + entity.yRotO = yaw; + entity.xRotO = pitch; + } + + private static boolean isFinite(Vec3 vector) { + return Double.isFinite(vector.x) && Double.isFinite(vector.y) && Double.isFinite(vector.z); + } + public static List findPortalsNearBounds(Level level, AABB bounds) { - List portals = new java.util.ArrayList<>(); - AABB searchBounds = bounds.inflate(10.0D); - for (PortalGunPortalEntity portal : level.getEntitiesOfClass(PortalGunPortalEntity.class, searchBounds, PortalGunPortalEntity::isAlive)) { - if (portal.getWorldPortalShape().getBoundsForCulling().intersects(bounds)) { + List portals = null; + for (PortalGunPortalEntity portal : PortalGunPortalRegistry.all(level)) { + if (portal.isAlive() && portal.getWorldPortalShape().getBoundsForCulling().intersects(bounds)) { + if (portals == null) { + portals = new java.util.ArrayList<>(2); + } portals.add(portal); } } - return portals; + return portals == null ? List.of() : portals; + } + + @Override + public void setLevelCallback(net.minecraft.world.level.entity.EntityInLevelCallback callback) { + super.setLevelCallback(callback); + if (callback == net.minecraft.world.level.entity.EntityInLevelCallback.NULL) { + PortalGunPortalRegistry.untrack(this); + } else { + PortalGunPortalRegistry.track(this); + } } public boolean containsPoint(Vec3 position) { @@ -490,6 +559,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { @Override public void tick() { super.tick(); + if (!this.isRemoved()) { + PortalGunPortalRegistry.track(this); + } int openingAnimationId = this.entityData.get(OPENING_ANIMATION_ID); if (openingAnimationId != this.lastOpeningAnimationId) { this.lastOpeningAnimationId = openingAnimationId; @@ -505,16 +577,8 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { if (!(this.level() instanceof ServerLevel serverLevel)) { return; } - if (this.ownerId != null) { - PortalGunSavedData.getChannelNameForPortal(serverLevel.getServer(), this.ownerId, serverLevel.dimension().location(), this.getUUID()) - .ifPresent(channelName -> this.adoptChannelIdentity(this.gunId, channelName)); - if (this.gunId == null) { - PortalGunSavedData.getGunIdForPortal(serverLevel.getServer(), this.ownerId, serverLevel.dimension().location(), this.getUUID()) - .ifPresent(gunId -> this.adoptChannelIdentity(gunId, this.channelName)); - } - } this.tickTeleportCooldowns(); - if (this.ownerId == null || !this.isStillRegistered(serverLevel)) { + if (this.gunId == null || !this.isStillRegistered(serverLevel)) { this.discard(); return; } @@ -540,7 +604,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { } private boolean isStillRegistered(ServerLevel level) { - return this.ownerId != null && PortalGunSavedData.isRegistered(level, this.ownerId, this.gunId, this.channelName, this.getPortalSide(), this.getUUID()); + return PortalGunSavedData.isRegistered(level, this.gunId, this.getPortalSide(), this.getUUID()); } private boolean hasValidSurface() { @@ -576,36 +640,15 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { } private void tickTeleport(PortalGunPortalEntity linked) { - List entities = this.level().getEntities(this, this.getScanRange(), this::canTeleportEntity); + List entities = this.level().getEntities(this, this.getScanRange(), entity -> !(entity instanceof Player) && this.canTeleportEntity(entity)); for (Entity entity : entities) { AABB currentBox = entity.getBoundingBox(); AABB previousBox = currentBox.move(entity.xo - entity.getX(), entity.yo - entity.getY(), entity.zo - entity.getZ()); - PortalCrossing crossing = this.resolveCrossing(entity, previousBox, currentBox); + PortalCrossing crossing = this.resolveCrossing(entity, previousBox, currentBox, entity.getDeltaMovement()); if (crossing == null) { - if (entity instanceof Player && Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY) && this.ageTicks % 20 == 0) { - Vec3 probe = this.teleportProbePosition(entity, currentBox); - double depth = this.getWorldPortalShape().localCoords(probe).depth(); - if (depth < 1.5D) { - Antarchy.LOGGER.info("Portal gun traversal waiting portal={} player={} depth={} position={} linked={}", - this.getUUID(), entity.getUUID(), depth, entity.position(), linked.getUUID()); - } - } continue; } - if (entity instanceof Player && Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY)) { - Antarchy.LOGGER.info("Portal gun traversal accepted portal={} player={} probe={} offset={} linked={}", - this.getUUID(), entity.getUUID(), crossing.probe(), crossing.normalOffset(), linked.getUUID()); - } - logCrossingPath(entity, "portal_tick"); - Vec3 resolvedMovement = entity.position().subtract(entity.xo, entity.yo, entity.zo); - this.teleportEntity(entity, linked, crossing.probe(), resolvedMovement, crossing.normalOffset()); - } - } - - private static void logCrossingPath(Entity entity, String path) { - String entityType = BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); - if (LOGGED_CROSSING_PATHS.add(entityType + ":" + path)) { - Antarchy.LOGGER.info("Portal gun entity crossing path entityType={} path={}", entityType, path); + this.teleportEntity(entity, linked, currentBox, entity.getDeltaMovement(), false); } } @@ -620,56 +663,81 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { return this.teleportCooldowns.containsKey(entity.getUUID()) || entity.getPortalCooldown() > 0; } - private void teleportEntity(Entity entity, PortalGunPortalEntity destination, Vec3 currentProbe, Vec3 entryMotion, double normalOffset) { + private void teleportEntity(Entity entity, PortalGunPortalEntity destination, AABB crossingBox, Vec3 velocity, boolean clientAuthoritative) { List group = new java.util.ArrayList<>(); collectTeleportGroup(entity, null, group); Vec3 rootOriginalPosition = entity.position(); - PortalTransitTransform transitTransform = this.previewTransit(entity, destination, new PortalCrossing(currentProbe, normalOffset), entryMotion); - Vec3 exitNormal = destination.getNormalVec().normalize(); - Vec3 requestedExitPos = transitTransform.requestedPosition(); - Vec3 exitPos = transitTransform.exitPosition(); - Vec3 transformedMotion = transitTransform.movement(); + PortalTransit transit = this.computeTransit(entity, destination, crossingBox, velocity, entity.getLookAngle()); + Vec3 exitPos = transit.position(); this.level().playSound(null, this.getX(), this.getY(), this.getZ(), sound("portal_enter"), SoundSource.PLAYERS, 0.7F, 0.96F + this.random.nextFloat() * 0.08F); for (EntityTeleportState state : group) { - Entity member = state.entity(); - member.stopRiding(); + state.entity().stopRiding(); } for (EntityTeleportState state : group) { Entity member = state.entity(); - Vec3 memberOffset = PortalGunTransformUtil.transformVector(this, destination, state.position().subtract(rootOriginalPosition)); - Vec3 memberExitPos = putEntityWithinExitBounds(member, requestedExitPos.add(memberOffset), legacyExitBounds(destination, member, exitNormal)); - Vec3 memberLook = PortalGunTransformUtil.transformVector(this, destination, state.look()).normalize(); - Vec3 memberMotion = member == entity - ? transformedMotion - : PortalGunTransformUtil.transformVector(this, destination, state.motion()); + boolean root = member == entity; + Vec3 memberExitPos = root + ? exitPos + : exitPos.add(PortalGunTransformUtil.transformVector(this, destination, state.position().subtract(rootOriginalPosition))); + Vec3 memberLook; + if (root) { + memberLook = transit.look(); + } else if (AntarchyGravityApi.isGravityInverted(member)) { + Vec3 worldLook = PortalGunTransitMath.entityVelocityToWorld(member, state.look()); + memberLook = PortalGunTransitMath.entityVelocityFromWorld(member, + PortalGunTransformUtil.transformVector(this, destination, worldLook).normalize()); + } else { + memberLook = PortalGunTransformUtil.transformVector(this, destination, state.look()).normalize(); + } + Vec3 memberMotion; + if (root) { + memberMotion = transit.velocity(); + } else if (AntarchyGravityApi.isGravityInverted(member)) { + Vec3 worldMotion = PortalGunTransitMath.entityVelocityToWorld(member, state.motion()); + memberMotion = PortalGunTransitMath.entityVelocityFromWorld(member, + PortalGunTransformUtil.transformVector(this, destination, worldMotion)); + } else { + memberMotion = PortalGunTransformUtil.transformVector(this, destination, state.motion()); + } float yaw = PortalGunTransformUtil.yawFromLook(memberLook); float pitch = PortalGunTransformUtil.pitchFromLook(memberLook); - if (member instanceof ServerPlayer player && destination.level() instanceof ServerLevel destinationLevel) { + float fallDistance = PortalGunTransitMath.exitFallDistance(member.fallDistance, + AntarchyGravityApi.isGravityInverted(member) ? PortalGunTransitMath.entityVelocityToWorld(member, memberMotion) : memberMotion, + member); + if (member instanceof ServerPlayer player && root && clientAuthoritative) { + player.moveTo(memberExitPos.x, memberExitPos.y, memberExitPos.z, yaw, pitch); + player.setYHeadRot(yaw); + player.setDeltaMovement(memberMotion); + player.connection.resetPosition(); + player.serverLevel().getChunkSource().move(player); + } else if (member instanceof ServerPlayer player && destination.level() instanceof ServerLevel destinationLevel) { player.teleportTo(destinationLevel, memberExitPos.x, memberExitPos.y, memberExitPos.z, yaw, pitch); + player.setDeltaMovement(memberMotion); + player.hasImpulse = true; + player.connection.send(new ClientboundSetEntityMotionPacket(player)); } else { member.teleportTo(memberExitPos.x, memberExitPos.y, memberExitPos.z); member.setYRot(yaw); member.setXRot(pitch); member.setYHeadRot(yaw); member.setYBodyRot(yaw); - } - member.setDeltaMovement(memberMotion); - member.hasImpulse = true; - member.hurtMarked = true; - if (member instanceof ServerPlayer player) { - player.connection.send(new ClientboundSetEntityMotionPacket(player)); + member.setDeltaMovement(memberMotion); + member.hasImpulse = true; + member.hurtMarked = true; } member.xo = member.getX(); member.yo = member.getY(); member.zo = member.getZ(); member.yRotO = yaw; member.xRotO = pitch; + if (member instanceof Projectile) { + orientAlongVelocity(member, memberMotion); + } member.setOnGround(false); member.horizontalCollision = false; member.verticalCollision = false; member.verticalCollisionBelow = false; - float verticalMotion = (float) memberMotion.y; - member.fallDistance = 0.1F * (verticalMotion / -0.1F * verticalMotion / -0.1F); + member.fallDistance = fallDistance; this.applyTeleportCooldown(member, destination); this.handleSpecialEntityPostTeleport(member); } @@ -684,12 +752,22 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { if (!(member instanceof ServerPlayer)) { destinationLevel.getChunkSource().broadcastAndSend(member, new ClientboundTeleportEntityPacket(member)); destinationLevel.getChunkSource().broadcastAndSend(member, new ClientboundSetEntityMotionPacket(member)); + syncTrackedPosition(destinationLevel, member); } } } destination.level().playSound(null, exitPos.x, exitPos.y, exitPos.z, sound("portal_exit"), SoundSource.PLAYERS, 0.7F, 0.96F + this.random.nextFloat() * 0.08F); } + private static void syncTrackedPosition(ServerLevel level, Entity entity) { + Object tracked = ((ChunkMapAccessor) level.getChunkSource().chunkMap).antarchy$getEntityMap().get(entity.getId()); + if (tracked instanceof TrackedEntityAccessor trackedEntity) { + ServerEntityAccessor serverEntity = (ServerEntityAccessor) trackedEntity.antarchy$getServerEntity(); + serverEntity.antarchy$getPositionCodec().setBase(entity.trackingPosition()); + serverEntity.antarchy$setLastSentMovement(entity.getDeltaMovement()); + } + } + private void collectTeleportGroup(Entity entity, Entity vehicle, List group) { group.add(new EntityTeleportState(entity, vehicle, entity.position(), entity.getLookAngle(), entity.getDeltaMovement())); for (Entity passenger : entity.getPassengers()) { @@ -697,37 +775,6 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { } } - private static Vec3 putEntityWithinExitBounds(Entity entity, Vec3 position, AABB exitBounds) { - AABB entityBounds = entity.getBoundingBox().move(position.x - entity.getX(), position.y - entity.getY(), position.z - entity.getZ()); - double x = position.x; - double y = position.y; - double z = position.z; - if (entityBounds.maxX > exitBounds.maxX) { - x += exitBounds.maxX - entityBounds.maxX; - } - if (entityBounds.minX < exitBounds.minX) { - x += exitBounds.minX - entityBounds.minX; - } - if (y + entity.getEyeHeight() > exitBounds.maxY) { - y += exitBounds.maxY - y - entity.getEyeHeight(); - } - if (y < exitBounds.minY) { - y += exitBounds.minY - y + 0.001D; - } - if (entityBounds.maxZ > exitBounds.maxZ) { - z += exitBounds.maxZ - entityBounds.maxZ; - } - if (entityBounds.minZ < exitBounds.minZ) { - z += exitBounds.minZ - entityBounds.minZ; - } - return new Vec3(x, y, z); - } - - private static AABB legacyExitBounds(PortalGunPortalEntity destination, Entity entity, Vec3 exitNormal) { - double maxDimension = Math.max(entity.getBbWidth(), entity.getBbHeight()); - return destination.getScanRange().expandTowards(exitNormal.scale(-maxDimension)); - } - private void tickTeleportCooldowns() { Iterator> iterator = this.teleportCooldowns.entrySet().iterator(); while (iterator.hasNext()) { @@ -783,15 +830,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { if (this.ownerId != null) { tag.putUUID("OwnerId", this.ownerId); } - if (this.ownerIdentity != null) { - tag.putString("OwnerIdentity", this.ownerIdentity); - } if (this.gunId != null) { tag.putUUID("GunId", this.gunId); } - if (this.channelName != null) { - tag.putString("ChannelName", this.channelName); - } if (this.linkedPortalId != null) { tag.putUUID("LinkedPortalId", this.linkedPortalId); } @@ -800,9 +841,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { tag.putInt("Side", this.getPortalSide().ordinal()); tag.putInt("Facing", this.getFacingDirection().get3DDataValue()); tag.putInt("UpAxis", this.getUpAxis().get3DDataValue()); - tag.putInt("ChannelRed", this.getChannelRed()); - tag.putInt("ChannelGreen", this.getChannelGreen()); - tag.putInt("ChannelBlue", this.getChannelBlue()); + tag.putInt("Variant", this.getVariant().id()); tag.putInt("PortalWidth", this.getPortalWidth()); tag.putInt("PortalHeight", this.getPortalHeight()); tag.putInt("SupportX", this.supportOrigin.getX()); @@ -839,12 +878,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { if (tag.hasUUID("OwnerId")) { this.ownerId = tag.getUUID("OwnerId"); } - this.ownerIdentity = tag.contains("OwnerIdentity") ? tag.getString("OwnerIdentity") : String.valueOf(this.ownerId); this.gunId = tag.hasUUID("GunId") ? tag.getUUID("GunId") : null; - this.channelName = tag.contains("ChannelName") ? tag.getString("ChannelName") : this.gunId == null ? "" : "Random Channel #" + this.gunId.hashCode(); this.entityData.set(OWNER_ID, Optional.ofNullable(this.ownerId)); this.entityData.set(GUN_ID, Optional.ofNullable(this.gunId)); - this.entityData.set(CHANNEL_NAME, this.channelName); if (tag.hasUUID("LinkedPortalId")) { this.linkedPortalId = tag.getUUID("LinkedPortalId"); this.entityData.set(LINKED_PORTAL, Optional.of(this.linkedPortalId)); @@ -854,16 +890,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { this.entityData.set(SIDE, tag.getInt("Side")); this.entityData.set(FACING, tag.getInt("Facing")); this.entityData.set(UP_AXIS, tag.getInt("UpAxis")); - if (this.ownerId != null && ("Global".equals(this.ownerIdentity) || !tag.contains("ChannelRed"))) { - int[] channelColor = generateChannelColor(this.ownerIdentity, this.channelName, this.getPortalSide()); - this.entityData.set(CHANNEL_RED, channelColor[0]); - this.entityData.set(CHANNEL_GREEN, channelColor[1]); - this.entityData.set(CHANNEL_BLUE, channelColor[2]); - } else if (tag.contains("ChannelRed")) { - this.entityData.set(CHANNEL_RED, tag.getInt("ChannelRed")); - this.entityData.set(CHANNEL_GREEN, tag.getInt("ChannelGreen")); - this.entityData.set(CHANNEL_BLUE, tag.getInt("ChannelBlue")); - } + this.entityData.set(VARIANT, PortalGunVariant.byId(tag.getInt("Variant")).id()); this.supportOrigin = new BlockPos(tag.getInt("SupportX"), tag.getInt("SupportY"), tag.getInt("SupportZ")); this.masterPos = new BlockPos(tag.getInt("MasterX"), tag.getInt("MasterY"), tag.getInt("MasterZ")); this.basePos = new BlockPos(tag.getInt("BaseX"), tag.getInt("BaseY"), tag.getInt("BaseZ")); @@ -892,7 +919,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { UUID ownerId = this.ownerId; boolean destroyPortal = reason.shouldDestroy(); if (destroyPortal && !level.isClientSide && ownerId != null && level instanceof ServerLevel serverLevel) { - PortalGunSavedData.clearPortal(serverLevel.getServer(), ownerId, this.gunId, this.channelName, this.getPortalSide(), this.getUUID(), serverLevel.dimension().location()); + PortalGunSavedData.clearPortal(serverLevel.getServer(), this.gunId, this.getPortalSide(), this.getUUID(), serverLevel.dimension().location()); } super.remove(reason); if (destroyPortal && !level.isClientSide && ownerId != null && level instanceof ServerLevel serverLevel) { @@ -971,40 +998,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity { .orElseThrow(() -> new IllegalStateException("Missing portal gun sound event: " + soundId)); } - private static int[] generateChannelColor(String ownerIdentity, String channelName, PortalSide side) { - if ("Global".equals(ownerIdentity)) { - int[] globalColors = switch (channelName) { - case "Chell" -> new int[] {361215, 16756742}; - case "Atlas" -> new int[] {5482192, 4064209}; - case "P-body" -> new int[] {16373344, 8394260}; - default -> null; - }; - if (globalColors != null) { - int color = globalColors[side == PortalSide.BLUE ? 0 : 1]; - return new int[] {color >> 16 & 0xFF, color >> 8 & 0xFF, color & 0xFF}; - } - } - String owner = String.valueOf(ownerIdentity); - String identity = owner + "_" + String.valueOf(channelName); - Random random = new Random(); - random.setSeed((long) Math.abs(identity.hashCode() * owner.hashCode())); - int firstColor = Math.round(1.6777215E7F * random.nextFloat()); - float[] hsb = Color.RGBtoHSB(firstColor >> 16 & 0xFF, firstColor >> 8 & 0xFF, firstColor & 0xFF, null); - hsb[2] = 0.65F + 0.25F * hsb[2]; - int portalAColor = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]); - float oppositeHue = hsb[0] + 0.5F; - if (oppositeHue > 1.0F) { - oppositeHue -= 1.0F; - } - int portalBColor = Color.HSBtoRGB(oppositeHue, hsb[1], hsb[2]); - int color = side == PortalSide.BLUE ? portalAColor : portalBColor; - return new int[] {color >> 16 & 0xFF, color >> 8 & 0xFF, color & 0xFF}; + public record PortalCrossing(Vec3 probe) { } - public record PortalCrossing(Vec3 probe, double normalOffset) { - } - - public record PortalTransitTransform(Vec3 requestedPosition, Vec3 exitPosition, Vec3 movement) { + public record PortalTransit(AABB exitBox, Vec3 position, Vec3 velocity, Vec3 look) { } private record EntityTeleportState(Entity entity, Entity vehicle, Vec3 position, Vec3 look, Vec3 motion) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalRegistry.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalRegistry.java new file mode 100644 index 00000000..3b46b343 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalRegistry.java @@ -0,0 +1,81 @@ +package com.craisinlord.antarchy.content.portalgun; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; + +public final class PortalGunPortalRegistry { + private static final Map> LEVELS = Collections.synchronizedMap(new WeakHashMap<>()); + + private PortalGunPortalRegistry() { + } + + static void track(PortalGunPortalEntity portal) { + Level level = portal.level(); + if (level == null) { + return; + } + Map portals; + synchronized (LEVELS) { + portals = LEVELS.computeIfAbsent(level, ignored -> new ConcurrentHashMap<>()); + } + portals.put(portal.getUUID(), portal); + } + + static void untrack(PortalGunPortalEntity portal) { + Map portals = portalsIn(portal.level()); + if (portals != null) { + portals.remove(portal.getUUID(), portal); + } + } + + public static Collection all(Level level) { + Map portals = portalsIn(level); + return portals == null ? List.of() : portals.values(); + } + + public static PortalGunPortalEntity find(Level level, UUID portalId) { + if (portalId == null) { + return null; + } + Map portals = portalsIn(level); + if (portals == null) { + return null; + } + PortalGunPortalEntity portal = portals.get(portalId); + return portal != null && portal.isAlive() ? portal : null; + } + + public static List near(Level level, AABB bounds) { + Map portals = portalsIn(level); + if (portals == null || portals.isEmpty()) { + return List.of(); + } + List nearby = null; + for (PortalGunPortalEntity portal : portals.values()) { + if (portal.isAlive() && portal.getPortalInsides().intersects(bounds)) { + if (nearby == null) { + nearby = new ArrayList<>(2); + } + nearby.add(portal); + } + } + return nearby == null ? List.of() : nearby; + } + + private static Map portalsIn(Level level) { + if (level == null) { + return null; + } + synchronized (LEVELS) { + return LEVELS.get(level); + } + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunProjectileEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunProjectileEntity.java index cce00a1d..477a8d2e 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunProjectileEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunProjectileEntity.java @@ -1,6 +1,9 @@ package com.craisinlord.antarchy.content.portalgun; import com.craisinlord.antarchy.content.item.PortalGunItem; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityTransition; import com.craisinlord.antarchy.config.AntarchySettings; import java.util.Comparator; import java.util.LinkedHashMap; @@ -61,6 +64,10 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile { private static final EntityDataAccessor PROJECTILE_SPEED = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.FLOAT); private static final EntityDataAccessor PASS_THROUGH_GLASS = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor PASS_THROUGH_LIQUID = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.BOOLEAN); + private static final int TRAIL_PARTICLES_PER_TICK = 4; + private static final float TRAIL_DUST_SCALE = 0.45F; + private static final float IMPACT_DUST_SCALE = 0.8F; + private static final int IMPACT_PARTICLES = 14; public static final double MIN_LAUNCH_SPEED = 4.98D; public static final double LAUNCH_SPEED_VARIANCE = 0.02D; public static final double MAX_TRAVEL_DISTANCE = 10000.0D; @@ -109,6 +116,7 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile { } public void configure(PortalGunPortalEntity.PortalSide side, UUID gunId, ItemStack gunStack) { + AntarchyGravityApi.setAirborneGravityDirection(this, AntarchyGravityDirection.DOWN, false, AntarchyGravityTransition.INSTANT); this.entityData.set(SIDE, side.ordinal()); this.gunId = gunId; this.setItem(gunStack.copyWithCount(1)); @@ -134,6 +142,10 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile { return this.entityData.get(PROJECTILE_SPEED); } + public PortalGunVariant getVariant() { + return this.getItem().getItem() instanceof PortalGunItem portalGun ? portalGun.getVariant() : PortalGunVariant.DEFAULT; + } + public PortalGunPortalEntity.PortalSide getPortalSide() { return this.entityData.get(SIDE) == PortalGunPortalEntity.PortalSide.ORANGE.ordinal() ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE; } @@ -265,14 +277,12 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile { ); } } - if (this.level().isClientSide) { + if (this.level().isClientSide && this.tickCount > 1) { + net.minecraft.core.particles.DustParticleOptions dust = this.trailDust(TRAIL_DUST_SCALE); Vec3 point = this.position(); - if (this.getPortalSide() == PortalGunPortalEntity.PortalSide.BLUE) { - this.level().addParticle(net.minecraft.core.particles.ParticleTypes.SOUL_FIRE_FLAME, point.x, point.y, point.z, 0.0D, 0.0D, 0.0D); - this.level().addParticle(net.minecraft.core.particles.ParticleTypes.END_ROD, point.x, point.y, point.z, 0.0D, 0.0D, 0.0D); - } else { - this.level().addParticle(net.minecraft.core.particles.ParticleTypes.FLAME, point.x, point.y, point.z, 0.0D, 0.0D, 0.0D); - this.level().addParticle(net.minecraft.core.particles.ParticleTypes.CRIT, point.x, point.y, point.z, 0.0D, 0.0D, 0.0D); + for (int i = 0; i < TRAIL_PARTICLES_PER_TICK; i++) { + Vec3 trailPoint = point.subtract(motion.scale((double) i / TRAIL_PARTICLES_PER_TICK)); + this.level().addParticle(dust, trailPoint.x, trailPoint.y, trailPoint.z, 0.0D, 0.0D, 0.0D); } } } @@ -368,13 +378,13 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile { } private void spawnImpactParticles(ServerLevel level, Vec3 impactPos) { - if (this.getPortalSide() == PortalGunPortalEntity.PortalSide.BLUE) { - level.sendParticles(net.minecraft.core.particles.ParticleTypes.SOUL_FIRE_FLAME, impactPos.x, impactPos.y, impactPos.z, 10, 0.08D, 0.08D, 0.08D, 0.01D); - level.sendParticles(net.minecraft.core.particles.ParticleTypes.END_ROD, impactPos.x, impactPos.y, impactPos.z, 6, 0.04D, 0.04D, 0.04D, 0.01D); - return; - } - level.sendParticles(net.minecraft.core.particles.ParticleTypes.FLAME, impactPos.x, impactPos.y, impactPos.z, 10, 0.08D, 0.08D, 0.08D, 0.01D); - level.sendParticles(net.minecraft.core.particles.ParticleTypes.CRIT, impactPos.x, impactPos.y, impactPos.z, 6, 0.04D, 0.04D, 0.04D, 0.01D); + level.sendParticles(this.trailDust(IMPACT_DUST_SCALE), impactPos.x, impactPos.y, impactPos.z, IMPACT_PARTICLES, 0.12D, 0.12D, 0.12D, 0.02D); + } + + private net.minecraft.core.particles.DustParticleOptions trailDust(float scale) { + int color = this.getVariant().color(this.getPortalSide()); + return new net.minecraft.core.particles.DustParticleOptions( + new org.joml.Vector3f((color >> 16 & 0xFF) / 255.0F, (color >> 8 & 0xFF) / 255.0F, (color & 0xFF) / 255.0F), scale); } private void syncSpawnPosition(Vec3 pos) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunSavedData.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunSavedData.java index 35620513..e48dbaf6 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunSavedData.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunSavedData.java @@ -2,9 +2,7 @@ package com.craisinlord.antarchy.content.portalgun; import java.util.HashMap; import java.util.HashSet; -import java.nio.charset.StandardCharsets; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -18,17 +16,13 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.level.saveddata.SavedData; public final class PortalGunSavedData extends SavedData { - private static final String ID = "antarchy_portal_gun_pairs"; + private static final String ID = "antarchy_portal_gun_pairs_v2"; private static final String ENTRIES_KEY = "Entries"; - private static final String OWNER_KEY = "Owner"; private static final String DIMENSION_KEY = "Dimension"; private static final String GUN_KEY = "Gun"; private static final String BLUE_KEY = "Blue"; private static final String ORANGE_KEY = "Orange"; - private static final String CHANNELS_KEY = "Channels"; private final Map pairs = new HashMap<>(); - private final Map legacyPairs = new HashMap<>(); - private final Map channelGunIds = new HashMap<>(); public static PortalGunSavedData create() { return new PortalGunSavedData(); @@ -38,23 +32,13 @@ public final class PortalGunSavedData extends SavedData { PortalGunSavedData data = new PortalGunSavedData(); for (net.minecraft.nbt.Tag rawEntry : tag.getList(ENTRIES_KEY, net.minecraft.nbt.Tag.TAG_COMPOUND)) { CompoundTag entryTag = (CompoundTag) rawEntry; - UUID owner = entryTag.getUUID(OWNER_KEY); + ResourceLocation dimension = ResourceLocation.tryParse(entryTag.getString(DIMENSION_KEY)); + if (dimension == null || !entryTag.hasUUID(GUN_KEY)) { + continue; + } UUID blue = entryTag.hasUUID(BLUE_KEY) ? entryTag.getUUID(BLUE_KEY) : null; UUID orange = entryTag.hasUUID(ORANGE_KEY) ? entryTag.getUUID(ORANGE_KEY) : null; - PairRecord record = new PairRecord(blue, orange); - ResourceLocation dimension = entryTag.contains(DIMENSION_KEY) ? ResourceLocation.tryParse(entryTag.getString(DIMENSION_KEY)) : null; - if (dimension == null) { - data.legacyPairs.put(owner, record); - } else { - UUID gunId = entryTag.hasUUID(GUN_KEY) ? entryTag.getUUID(GUN_KEY) : null; - data.pairs.put(new PairKey(owner, dimension, gunId), record); - } - } - for (net.minecraft.nbt.Tag rawChannel : tag.getList(CHANNELS_KEY, net.minecraft.nbt.Tag.TAG_COMPOUND)) { - CompoundTag channelTag = (CompoundTag) rawChannel; - if (channelTag.hasUUID(OWNER_KEY) && channelTag.hasUUID(GUN_KEY) && channelTag.contains("Channel")) { - data.channelGunIds.put(new OwnerChannelKey(channelTag.getUUID(OWNER_KEY), channelTag.getString("Channel")), channelTag.getUUID(GUN_KEY)); - } + data.pairs.put(new PairKey(dimension, entryTag.getUUID(GUN_KEY)), new PairRecord(blue, orange)); } return data; } @@ -64,42 +48,20 @@ public final class PortalGunSavedData extends SavedData { ListTag entries = new ListTag(); for (Map.Entry entry : this.pairs.entrySet()) { CompoundTag entryTag = new CompoundTag(); - entryTag.putUUID(OWNER_KEY, entry.getKey().owner()); entryTag.putString(DIMENSION_KEY, entry.getKey().dimension().toString()); - if (entry.getKey().gunId() != null) { - entryTag.putUUID(GUN_KEY, entry.getKey().gunId()); + entryTag.putUUID(GUN_KEY, entry.getKey().gunId()); + if (entry.getValue().bluePortalId() != null) { + entryTag.putUUID(BLUE_KEY, entry.getValue().bluePortalId()); + } + if (entry.getValue().orangePortalId() != null) { + entryTag.putUUID(ORANGE_KEY, entry.getValue().orangePortalId()); } - writePair(entryTag, entry.getValue()); entries.add(entryTag); } - for (Map.Entry entry : this.legacyPairs.entrySet()) { - CompoundTag entryTag = new CompoundTag(); - entryTag.putUUID(OWNER_KEY, entry.getKey()); - writePair(entryTag, entry.getValue()); - entries.add(entryTag); - } - ListTag channels = new ListTag(); - for (Map.Entry entry : this.channelGunIds.entrySet()) { - CompoundTag channelTag = new CompoundTag(); - channelTag.putUUID(OWNER_KEY, entry.getKey().owner()); - channelTag.putString("Channel", entry.getKey().channelName()); - channelTag.putUUID(GUN_KEY, entry.getValue()); - channels.add(channelTag); - } tag.put(ENTRIES_KEY, entries); - tag.put(CHANNELS_KEY, channels); return tag; } - private static void writePair(CompoundTag tag, PairRecord record) { - if (record.bluePortalId() != null) { - tag.putUUID(BLUE_KEY, record.bluePortalId()); - } - if (record.orangePortalId() != null) { - tag.putUUID(ORANGE_KEY, record.orangePortalId()); - } - } - private static PortalGunSavedData get(MinecraftServer server) { return server.overworld().getDataStorage().computeIfAbsent( new SavedData.Factory<>(PortalGunSavedData::create, PortalGunSavedData::load, null), @@ -107,132 +69,57 @@ public final class PortalGunSavedData extends SavedData { ); } - public static Optional getPortalId(MinecraftServer server, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side, ResourceLocation dimension) { - PortalGunSavedData data = get(server); - UUID resolvedGunId = data.resolveChannelGunId(owner, channelName, gunId); - data.migrateLegacyPair(server, owner); - data.adoptLegacyPairs(server, owner, resolvedGunId, channelName); - PairRecord record = data.pairs.get(new PairKey(owner, dimension, resolvedGunId)); + public static Optional getPortalId(MinecraftServer server, UUID gunId, PortalGunPortalEntity.PortalSide side, ResourceLocation dimension) { + if (gunId == null) { + return Optional.empty(); + } + PairRecord record = get(server).pairs.get(new PairKey(dimension, gunId)); if (record == null) { return Optional.empty(); } - data.synchronizeLoadedPortal(server, owner, dimension, record.bluePortalId(), resolvedGunId, channelName); - data.synchronizeLoadedPortal(server, owner, dimension, record.orangePortalId(), resolvedGunId, channelName); return Optional.ofNullable(side == PortalGunPortalEntity.PortalSide.BLUE ? record.bluePortalId() : record.orangePortalId()); } - public static Optional getPortalId(MinecraftServer server, UUID owner, UUID gunId, PortalGunPortalEntity.PortalSide side, ResourceLocation dimension) { - return getPortalId(server, owner, gunId, String.valueOf(gunId), side, dimension); + public static boolean isRegistered(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side, UUID portalId) { + return portalId != null && getPortalId(level.getServer(), gunId, side, level.dimension().location()).map(portalId::equals).orElse(false); } - public static Optional getGunIdForPortal(MinecraftServer server, UUID owner, ResourceLocation dimension, UUID portalId) { - PortalGunSavedData data = get(server); - data.migrateLegacyPair(server, owner); - for (Map.Entry entry : data.pairs.entrySet()) { - PairKey key = entry.getKey(); - if (key.owner().equals(owner) && key.dimension().equals(dimension) && key.gunId() != null - && (portalId.equals(entry.getValue().bluePortalId()) || portalId.equals(entry.getValue().orangePortalId()))) { - return Optional.of(key.gunId()); - } + public static void setPortal(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side, UUID portalId) { + if (gunId == null) { + return; } - return Optional.empty(); - } - - public static Optional getChannelNameForPortal(MinecraftServer server, UUID owner, ResourceLocation dimension, UUID portalId) { - PortalGunSavedData data = get(server); - for (Map.Entry entry : data.pairs.entrySet()) { - PairKey key = entry.getKey(); - if (!key.owner().equals(owner) || !key.dimension().equals(dimension) - || (!portalId.equals(entry.getValue().bluePortalId()) && !portalId.equals(entry.getValue().orangePortalId()))) { - continue; - } - return data.channelGunIds.entrySet().stream() - .filter(channel -> channel.getKey().owner().equals(owner) && channel.getValue().equals(key.gunId())) - .map(channel -> channel.getKey().channelName()) - .findFirst(); - } - return Optional.empty(); - } - - public static boolean isRegistered(ServerLevel level, UUID owner, UUID gunId, PortalGunPortalEntity.PortalSide side, UUID portalId) { - return isRegistered(level, owner, gunId, String.valueOf(gunId), side, portalId); - } - - public static boolean isRegistered(ServerLevel level, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side, UUID portalId) { - return getPortalId(level.getServer(), owner, gunId, channelName, side, level.dimension().location()).map(portalId::equals).orElse(false); - } - - public static void setPortal(ServerLevel level, UUID owner, UUID gunId, PortalGunPortalEntity.PortalSide side, UUID portalId) { - setPortal(level, owner, gunId, String.valueOf(gunId), side, portalId); - } - - public static void setPortal(ServerLevel level, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side, UUID portalId) { PortalGunSavedData data = get(level.getServer()); - ResourceLocation dimension = level.dimension().location(); - UUID resolvedGunId = data.resolveChannelGunId(owner, channelName, gunId); - data.migrateLegacyPair(level.getServer(), owner); - data.adoptLegacyPairs(level.getServer(), owner, resolvedGunId, channelName); - PairKey key = new PairKey(owner, dimension, resolvedGunId); + PairKey key = new PairKey(level.dimension().location(), gunId); PairRecord current = data.pairs.getOrDefault(key, new PairRecord(null, null)); - PairRecord updated = side == PortalGunPortalEntity.PortalSide.BLUE + data.put(key, side == PortalGunPortalEntity.PortalSide.BLUE ? new PairRecord(portalId, current.orangePortalId()) - : new PairRecord(current.bluePortalId(), portalId); - if (updated.bluePortalId() == null && updated.orangePortalId() == null) { - data.pairs.remove(key); - } else { - data.pairs.put(key, updated); + : new PairRecord(current.bluePortalId(), portalId)); + } + + public static void clearPortal(MinecraftServer server, UUID gunId, PortalGunPortalEntity.PortalSide side, UUID portalId, ResourceLocation dimension) { + if (gunId == null) { + return; } - data.setDirty(); - } - - public static void clearPortal(MinecraftServer server, UUID owner, UUID gunId, PortalGunPortalEntity.PortalSide side, UUID portalId, ResourceLocation dimension) { - clearPortal(server, owner, gunId, String.valueOf(gunId), side, portalId, dimension); - } - - public static void clearPortal(MinecraftServer server, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side, UUID portalId, ResourceLocation dimension) { PortalGunSavedData data = get(server); - UUID resolvedGunId = data.resolveChannelGunId(owner, channelName, gunId); - data.migrateLegacyPair(server, owner); - data.adoptLegacyPairs(server, owner, resolvedGunId, channelName); - PairKey key = new PairKey(owner, dimension, resolvedGunId); + PairKey key = new PairKey(dimension, gunId); PairRecord current = data.pairs.get(key); if (current == null) { return; } - UUID blue = current.bluePortalId(); - UUID orange = current.orangePortalId(); - if (side == PortalGunPortalEntity.PortalSide.BLUE && portalId.equals(blue)) { - blue = null; - } - if (side == PortalGunPortalEntity.PortalSide.ORANGE && portalId.equals(orange)) { - orange = null; - } - if (blue == null && orange == null) { - data.pairs.remove(key); - } else { - data.pairs.put(key, new PairRecord(blue, orange)); - } - data.setDirty(); + UUID blue = side == PortalGunPortalEntity.PortalSide.BLUE && portalId.equals(current.bluePortalId()) ? null : current.bluePortalId(); + UUID orange = side == PortalGunPortalEntity.PortalSide.ORANGE && portalId.equals(current.orangePortalId()) ? null : current.orangePortalId(); + data.put(key, new PairRecord(blue, orange)); } - public static void clearAllPortals(ServerLevel level, UUID owner, UUID gunId) { - clearAllPortals(level, owner, gunId, String.valueOf(gunId)); - } - - public static void clearAllPortals(ServerLevel level, UUID owner, UUID gunId, String channelName) { + public static void clearAllPortals(ServerLevel level, UUID gunId) { + if (gunId == null) { + return; + } MinecraftServer server = level.getServer(); PortalGunSavedData data = get(server); - UUID resolvedGunId = data.resolveChannelGunId(owner, channelName, gunId); - data.migrateLegacyPair(server, owner); - data.adoptLegacyPairs(server, owner, resolvedGunId, channelName); Set portalIds = new HashSet<>(); - PairRecord legacy = gunId == null ? data.legacyPairs.remove(owner) : null; - if (legacy != null) { - addPortalIds(portalIds, legacy); - } data.pairs.entrySet().removeIf(entry -> { - if (!entry.getKey().owner().equals(owner) || !entry.getKey().dimension().equals(level.dimension().location()) - || !Objects.equals(entry.getKey().gunId(), resolvedGunId)) { + if (!entry.getKey().gunId().equals(gunId)) { return false; } addPortalIds(portalIds, entry.getValue()); @@ -244,20 +131,15 @@ public final class PortalGunSavedData extends SavedData { } } - public static void clearPortalSide(ServerLevel level, UUID owner, UUID gunId, PortalGunPortalEntity.PortalSide side) { - clearPortalSide(level, owner, gunId, String.valueOf(gunId), side); - } - - public static void clearPortalSide(ServerLevel level, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side) { + public static void clearPortalSide(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side) { + if (gunId == null) { + return; + } MinecraftServer server = level.getServer(); PortalGunSavedData data = get(server); - UUID resolvedGunId = data.resolveChannelGunId(owner, channelName, gunId); - data.migrateLegacyPair(server, owner); - data.adoptLegacyPairs(server, owner, resolvedGunId, channelName); Set portalIds = new HashSet<>(); for (Map.Entry entry : new HashMap<>(data.pairs).entrySet()) { - PairKey key = entry.getKey(); - if (!key.owner().equals(owner) || !key.dimension().equals(level.dimension().location()) || !Objects.equals(key.gunId(), resolvedGunId)) { + if (!entry.getKey().gunId().equals(gunId)) { continue; } PairRecord pair = entry.getValue(); @@ -266,23 +148,17 @@ public final class PortalGunSavedData extends SavedData { continue; } portalIds.add(removed); - PairRecord remaining = side == PortalGunPortalEntity.PortalSide.BLUE + data.put(entry.getKey(), side == PortalGunPortalEntity.PortalSide.BLUE ? new PairRecord(null, pair.orangePortalId()) - : new PairRecord(pair.bluePortalId(), null); - if (remaining.bluePortalId() == null && remaining.orangePortalId() == null) { - data.pairs.remove(key); - } else { - data.pairs.put(key, remaining); - } + : new PairRecord(pair.bluePortalId(), null)); } - data.setDirty(); for (UUID portalId : portalIds) { discardIfLoaded(server, portalId); } } - public static PortalGunPortalEntity findLoadedPortal(ServerLevel level, UUID owner, UUID gunId, PortalGunPortalEntity.PortalSide side) { - Optional portalId = getPortalId(level.getServer(), owner, gunId, side, level.dimension().location()); + public static PortalGunPortalEntity findLoadedPortal(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side) { + Optional portalId = getPortalId(level.getServer(), gunId, side, level.dimension().location()); if (portalId.isEmpty()) { return null; } @@ -290,143 +166,13 @@ public final class PortalGunSavedData extends SavedData { return entity instanceof PortalGunPortalEntity portal && !portal.isRemoved() ? portal : null; } - public static PortalGunPortalEntity findLoadedPortal(ServerLevel level, UUID owner, UUID gunId, String channelName, PortalGunPortalEntity.PortalSide side) { - Optional portalId = getPortalId(level.getServer(), owner, gunId, channelName, side, level.dimension().location()); - if (portalId.isEmpty()) { - return null; - } - Entity entity = level.getEntity(portalId.get()); - return entity instanceof PortalGunPortalEntity portal && !portal.isRemoved() ? portal : null; - } - - private UUID resolveChannelGunId(UUID owner, String channelName, UUID gunId) { - if (channelName == null || channelName.isEmpty()) { - return gunId; - } - OwnerChannelKey key = new OwnerChannelKey(owner, channelName); - UUID existing = this.channelGunIds.get(key); - if (existing != null) { - return existing; - } - UUID channelGunId = UUID.nameUUIDFromBytes((owner + "\u0000" + channelName).getBytes(StandardCharsets.UTF_8)); - this.channelGunIds.put(key, channelGunId); - if (gunId != null && !gunId.equals(channelGunId)) { - this.migrateGunPairs(owner, gunId, channelGunId); + private void put(PairKey key, PairRecord record) { + if (record.bluePortalId() == null && record.orangePortalId() == null) { + this.pairs.remove(key); + } else { + this.pairs.put(key, record); } this.setDirty(); - return channelGunId; - } - - private void migrateGunPairs(UUID owner, UUID previousGunId, UUID channelGunId) { - for (Map.Entry entry : new HashMap<>(this.pairs).entrySet()) { - PairKey previousKey = entry.getKey(); - if (!previousKey.owner().equals(owner) || !previousGunId.equals(previousKey.gunId())) { - continue; - } - PairKey channelKey = new PairKey(owner, previousKey.dimension(), channelGunId); - PairRecord existing = this.pairs.get(channelKey); - PairRecord migrated = mergePairs(existing, entry.getValue()); - this.pairs.remove(previousKey); - this.pairs.put(channelKey, migrated); - } - } - - private static PairRecord mergePairs(PairRecord preferred, PairRecord fallback) { - if (preferred == null) { - return fallback; - } - return new PairRecord( - preferred.bluePortalId() == null ? fallback.bluePortalId() : preferred.bluePortalId(), - preferred.orangePortalId() == null ? fallback.orangePortalId() : preferred.orangePortalId() - ); - } - - private void migrateLegacyPair(MinecraftServer server, UUID owner) { - PairRecord legacy = this.legacyPairs.get(owner); - if (legacy == null) { - return; - } - ServerLevel blueLevel = findPortalLevel(server, legacy.bluePortalId()); - ServerLevel orangeLevel = findPortalLevel(server, legacy.orangePortalId()); - UUID legacyBlue = legacy.bluePortalId(); - UUID legacyOrange = legacy.orangePortalId(); - if (blueLevel != null) { - Entity blueEntity = blueLevel.getEntity(legacyBlue); - UUID blueGunId = blueEntity instanceof PortalGunPortalEntity portal ? portal.getGunId() : null; - PairKey key = new PairKey(owner, blueLevel.dimension().location(), blueGunId); - this.pairs.put(key, withPortal(this.pairs.get(key), PortalGunPortalEntity.PortalSide.BLUE, legacyBlue)); - legacyBlue = null; - } - if (orangeLevel != null) { - Entity orangeEntity = orangeLevel.getEntity(legacyOrange); - UUID orangeGunId = orangeEntity instanceof PortalGunPortalEntity portal ? portal.getGunId() : null; - PairKey key = new PairKey(owner, orangeLevel.dimension().location(), orangeGunId); - this.pairs.put(key, withPortal(this.pairs.get(key), PortalGunPortalEntity.PortalSide.ORANGE, legacyOrange)); - legacyOrange = null; - } - if (!Objects.equals(legacy.bluePortalId(), legacyBlue) || !Objects.equals(legacy.orangePortalId(), legacyOrange)) { - if (legacyBlue == null && legacyOrange == null) { - this.legacyPairs.remove(owner); - } else { - this.legacyPairs.put(owner, new PairRecord(legacyBlue, legacyOrange)); - } - this.setDirty(); - } - } - - private void adoptLegacyPairs(MinecraftServer server, UUID owner, UUID gunId, String channelName) { - if (gunId == null) { - return; - } - boolean changed = false; - for (Map.Entry entry : new HashMap<>(this.pairs).entrySet()) { - PairKey legacyKey = entry.getKey(); - if (!legacyKey.owner().equals(owner) || legacyKey.gunId() != null) { - continue; - } - PairKey ownedKey = new PairKey(owner, legacyKey.dimension(), gunId); - if (this.pairs.containsKey(ownedKey)) { - continue; - } - this.pairs.remove(legacyKey); - this.pairs.put(ownedKey, entry.getValue()); - synchronizeLoadedPortal(server, owner, legacyKey.dimension(), entry.getValue().bluePortalId(), gunId, channelName); - synchronizeLoadedPortal(server, owner, legacyKey.dimension(), entry.getValue().orangePortalId(), gunId, channelName); - changed = true; - } - if (changed) { - this.setDirty(); - } - } - - private static void synchronizeLoadedPortal(MinecraftServer server, UUID owner, ResourceLocation dimension, UUID portalId, UUID gunId, String channelName) { - if (portalId == null) { - return; - } - ServerLevel level = server.getLevel(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.DIMENSION, dimension)); - if (level == null || !(level.getEntity(portalId) instanceof PortalGunPortalEntity portal) || !owner.equals(portal.getOwnerId())) { - return; - } - portal.adoptChannelIdentity(gunId, channelName); - } - - private static PairRecord withPortal(PairRecord current, PortalGunPortalEntity.PortalSide side, UUID portalId) { - PairRecord pair = current == null ? new PairRecord(null, null) : current; - return side == PortalGunPortalEntity.PortalSide.BLUE - ? new PairRecord(pair.bluePortalId() == null ? portalId : pair.bluePortalId(), pair.orangePortalId()) - : new PairRecord(pair.bluePortalId(), pair.orangePortalId() == null ? portalId : pair.orangePortalId()); - } - - private static ServerLevel findPortalLevel(MinecraftServer server, UUID portalId) { - if (portalId == null) { - return null; - } - for (ServerLevel level : server.getAllLevels()) { - if (level.getEntity(portalId) instanceof PortalGunPortalEntity portal && !portal.isRemoved()) { - return level; - } - } - return null; } private static void addPortalIds(Set portalIds, PairRecord pair) { @@ -439,16 +185,15 @@ public final class PortalGunSavedData extends SavedData { } private static void discardIfLoaded(MinecraftServer server, UUID portalId) { - ServerLevel level = findPortalLevel(server, portalId); - if (level != null && level.getEntity(portalId) instanceof PortalGunPortalEntity portal) { - portal.discard(); + for (ServerLevel level : server.getAllLevels()) { + if (level.getEntity(portalId) instanceof PortalGunPortalEntity portal && !portal.isRemoved()) { + portal.discard(); + return; + } } } - private record PairKey(UUID owner, ResourceLocation dimension, UUID gunId) { - } - - private record OwnerChannelKey(UUID owner, String channelName) { + private record PairKey(ResourceLocation dimension, UUID gunId) { } private record PairRecord(UUID bluePortalId, UUID orangePortalId) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitHandler.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitHandler.java new file mode 100644 index 00000000..24914ab3 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitHandler.java @@ -0,0 +1,18 @@ +package com.craisinlord.antarchy.content.portalgun; + +import com.craisinlord.antarchy.content.network.PortalGunTransitPayload; +import net.minecraft.server.level.ServerPlayer; + +public final class PortalGunTransitHandler { + private PortalGunTransitHandler() { + } + + public static void handle(ServerPlayer player, PortalGunTransitPayload payload) { + if (player == null) { + return; + } + if (!PortalGunPortalEntity.handleClientTransit(player, payload.portalId(), payload.start(), payload.end(), payload.velocity())) { + player.connection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot()); + } + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitMath.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitMath.java new file mode 100644 index 00000000..fd77677d --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunTransitMath.java @@ -0,0 +1,138 @@ +package com.craisinlord.antarchy.content.portalgun; + +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public final class PortalGunTransitMath { + public static final double EXIT_CLEARANCE = 0.02D; + public static final double LEADING_FACE_TOLERANCE = 0.05D; + private static final double UPWARD_EXIT_NORMAL_Y = 0.5D; + + private PortalGunTransitMath() { + } + + public static double extentAlong(AABB box, Vec3 axis) { + return (box.maxX - box.minX) * 0.5D * Math.abs(axis.x) + + (box.maxY - box.minY) * 0.5D * Math.abs(axis.y) + + (box.maxZ - box.minZ) * 0.5D * Math.abs(axis.z); + } + + public static boolean fitsOpening(PortalGunWorldPortalShape shape, AABB box, double tolerance) { + PortalGunWorldPortalShape.PortalLocalCoords center = shape.localCoords(box.getCenter()); + return Math.abs(center.horizontal()) + extentAlong(box, shape.right()) <= shape.halfWidth() + tolerance + && Math.abs(center.vertical()) + extentAlong(box, shape.up()) <= shape.halfHeight() + tolerance; + } + + public static boolean centredOverOpening(PortalGunWorldPortalShape shape, AABB box) { + PortalGunWorldPortalShape.PortalLocalCoords center = shape.localCoords(box.getCenter()); + return Math.abs(center.horizontal()) <= shape.halfWidth() && Math.abs(center.vertical()) <= shape.halfHeight(); + } + + public static boolean crossesWithBody(PortalGunWorldPortalShape shape, AABB previousBox, AABB currentBox, Vec3 attemptedMovement) { + double previousDepth = shape.localCoords(previousBox.getCenter()).depth(); + double currentDepth = shape.localCoords(currentBox.getCenter()).depth(); + if (previousDepth <= 0.0D) { + return false; + } + boolean movingInward = attemptedMovement.dot(shape.normal()) < -1.0E-6D || currentDepth < previousDepth - 1.0E-6D; + if (!movingInward) { + return false; + } + if (currentDepth - extentAlong(currentBox, shape.normal()) > LEADING_FACE_TOLERANCE) { + return false; + } + return centredOverOpening(shape, currentBox); + } + + public static Vec3 transformVector(PortalGunWorldPortalShape source, PortalGunWorldPortalShape destination, Vec3 vector) { + return PortalGunTransformUtil.transformVector(source, destination, vector); + } + + public static AABB exitBox(PortalGunWorldPortalShape source, PortalGunWorldPortalShape destination, AABB box) { + PortalGunWorldPortalShape.PortalLocalCoords local = source.localCoords(box.getCenter()); + double horizontal = clampLateral(-local.horizontal(), destination.halfWidth(), extentAlong(box, destination.right())); + double vertical = clampLateral(local.vertical(), destination.halfHeight(), extentAlong(box, destination.up())); + double depth = extentAlong(box, destination.normal()) + EXIT_CLEARANCE; + Vec3 center = destination.center() + .add(destination.right().scale(horizontal)) + .add(destination.up().scale(vertical)) + .add(destination.normal().scale(depth)); + Vec3 offset = center.subtract(box.getCenter()); + return box.move(offset); + } + + public static Vec3 feetPosition(AABB box) { + return new Vec3((box.minX + box.maxX) * 0.5D, box.minY, (box.minZ + box.maxZ) * 0.5D); + } + + public static Vec3 entityPosition(AABB box, Entity entity) { + return entityPosition(box, AntarchyGravityApi.isGravityInverted(entity)); + } + + public static Vec3 entityPosition(AABB box, boolean inverted) { + if (!inverted) { + return feetPosition(box); + } + return new Vec3((box.minX + box.maxX) * 0.5D, box.maxY, (box.minZ + box.maxZ) * 0.5D); + } + + public static Vec3 entityVelocityToWorld(Entity entity, Vec3 velocity) { + return entityVelocityToWorld(velocity, AntarchyGravityApi.isGravityInverted(entity)); + } + + public static Vec3 entityVelocityToWorld(Vec3 velocity, boolean inverted) { + if (!inverted) { + return velocity; + } + return AntarchyGravityRotationUtil.vecPlayerToWorld(velocity, AntarchyGravityDirection.UP); + } + + public static Vec3 entityVelocityFromWorld(Entity entity, Vec3 velocity) { + return entityVelocityFromWorld(velocity, AntarchyGravityApi.isGravityInverted(entity)); + } + + public static Vec3 entityVelocityFromWorld(Vec3 velocity, boolean inverted) { + if (!inverted) { + return velocity; + } + return AntarchyGravityRotationUtil.vecWorldToPlayer(velocity, AntarchyGravityDirection.UP); + } + + public static Vec3 exitVelocity(PortalGunWorldPortalShape source, PortalGunWorldPortalShape destination, Vec3 velocity, double minUpwardExitSpeed, double maxExitSpeed) { + Vec3 exit = transformVector(source, destination, velocity); + Vec3 normal = destination.normal(); + if (minUpwardExitSpeed > 0.0D && normal.y > UPWARD_EXIT_NORMAL_Y) { + double outward = exit.dot(normal); + if (outward < minUpwardExitSpeed) { + exit = exit.add(normal.scale(minUpwardExitSpeed - outward)); + } + } + if (maxExitSpeed > 0.0D && exit.lengthSqr() > maxExitSpeed * maxExitSpeed) { + exit = exit.normalize().scale(maxExitSpeed); + } + return exit; + } + + public static float exitFallDistance(float fallDistance, Vec3 exitVelocity) { + return exitVelocity.y < 0.0D ? fallDistance : 0.0F; + } + + public static float exitFallDistance(float fallDistance, Vec3 exitVelocity, Entity entity) { + if (!AntarchyGravityApi.isGravityInverted(entity)) { + return exitFallDistance(fallDistance, exitVelocity); + } + return exitVelocity.y > 0.0D ? fallDistance : 0.0F; + } + + private static double clampLateral(double coordinate, double halfSize, double extent) { + double limit = halfSize - extent; + if (limit <= 0.0D) { + return 0.0D; + } + return Math.max(-limit, Math.min(limit, coordinate)); + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunVariant.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunVariant.java new file mode 100644 index 00000000..2870d594 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunVariant.java @@ -0,0 +1,66 @@ +package com.craisinlord.antarchy.content.portalgun; + +import com.craisinlord.antarchy.Antarchy; +import net.minecraft.resources.ResourceLocation; + +public enum PortalGunVariant { + DEFAULT("", 0x40A0FF, 0xFF961E, "blue", "orange"), + ATLAS("atlas", 0x53A6D0, 0x6A2BE0, "blue", "purple"), + P_BODY("p_body", 0xF9D660, 0xC0282A, "yellow", "red"); + + private final String key; + private final int blueColor; + private final int orangeColor; + private final String blueColorName; + private final String orangeColorName; + private final ResourceLocation crosshairTexture; + private final ResourceLocation modelTexture; + private final ResourceLocation blueVortexTexture; + private final ResourceLocation orangeVortexTexture; + + PortalGunVariant(String key, int blueColor, int orangeColor, String blueColorName, String orangeColorName) { + this.key = key; + this.blueColor = blueColor; + this.orangeColor = orangeColor; + this.blueColorName = blueColorName; + this.orangeColorName = orangeColorName; + String prefix = key.isEmpty() ? "" : key + "_"; + this.crosshairTexture = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/gui/portal_gun_" + prefix + "crosshair.png"); + this.modelTexture = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/models/item/portal_gun" + (key.isEmpty() ? "" : "_" + key) + ".png"); + this.blueVortexTexture = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/portal_gun/portal_" + prefix + "blue_vortex.png"); + this.orangeVortexTexture = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/portal_gun/portal_" + prefix + "orange_vortex.png"); + } + + public String key() { + return this.key; + } + + public int color(PortalGunPortalEntity.PortalSide side) { + return side == PortalGunPortalEntity.PortalSide.BLUE ? this.blueColor : this.orangeColor; + } + + public String colorTranslationKey(PortalGunPortalEntity.PortalSide side) { + return "tooltip.antarchy.portal_gun.color." + (side == PortalGunPortalEntity.PortalSide.BLUE ? this.blueColorName : this.orangeColorName); + } + + public ResourceLocation crosshairTexture() { + return this.crosshairTexture; + } + + public ResourceLocation modelTexture() { + return this.modelTexture; + } + + public ResourceLocation vortexTexture(PortalGunPortalEntity.PortalSide side) { + return side == PortalGunPortalEntity.PortalSide.BLUE ? this.blueVortexTexture : this.orangeVortexTexture; + } + + public int id() { + return this.ordinal(); + } + + public static PortalGunVariant byId(int id) { + PortalGunVariant[] values = values(); + return id >= 0 && id < values.length ? values[id] : DEFAULT; + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunWorldPortalShape.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunWorldPortalShape.java index 89a043d3..9d83dbb3 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunWorldPortalShape.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunWorldPortalShape.java @@ -52,6 +52,19 @@ public record PortalGunWorldPortalShape( }; } + public Vec3[] getOutline(double normalOffset, int segments, double radiusHorizontal, double radiusVertical) { + int count = Math.max(3, segments); + Vec3 center = this.center.add(this.normal.scale(normalOffset)); + Vec3[] outline = new Vec3[count]; + for (int index = 0; index < count; index++) { + double angle = Math.PI * 2.0D * index / count; + outline[index] = center + .add(this.right.scale(Math.cos(angle) * radiusHorizontal)) + .add(this.up.scale(Math.sin(angle) * radiusVertical)); + } + return outline; + } + public PortalLocalCoords localCoords(Vec3 position) { Vec3 relative = position.subtract(this.center); return new PortalLocalCoords(relative.dot(this.right), relative.dot(this.up), relative.dot(this.normal)); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/KingsTreeGridFeature.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/KingsTreeGridFeature.java index 1dfec542..09a56cea 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/KingsTreeGridFeature.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/KingsTreeGridFeature.java @@ -28,10 +28,12 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; /** Places the authored King's Tree as independently generated chunk slices on a fixed world grid. */ public final class KingsTreeGridFeature extends Feature { private static final Map> CLAIMED_TREE_KINGS = new WeakHashMap<>(); + private static final ConcurrentLinkedQueue PENDING_KING_SPAWNS = new ConcurrentLinkedQueue<>(); private static final int TREE_MIN_X = -191; private static final int TREE_MAX_X = 192; private static final int TREE_MIN_Z = -227; @@ -108,53 +110,70 @@ public final class KingsTreeGridFeature extends Feature new java.util.HashSet<>()).add(treeKey)) { - return; - } - } - Vec3 treeCenter = new Vec3(centerX + 0.5D, 0.0D, centerZ + 0.5D); - AABB searchBox = new AABB( - centerX - 512.0D, level.getMinBuildHeight(), centerZ - 512.0D, - centerX + 512.0D, level.getMaxBuildHeight(), centerZ + 512.0D); - List treeKings = serverLevel.getEntitiesOfClass(KingEntity.class, searchBox, - king -> king.isAlive() && king.isTreePatrolFor(treeCenter)); - if (!treeKings.isEmpty()) { - // Repair older worlds that already contain duplicate tree-bound Kings. - for (int index = 1; index < treeKings.size(); index++) { - treeKings.get(index).discard(); - } + synchronized (CLAIMED_TREE_KINGS) { + if (!CLAIMED_TREE_KINGS.computeIfAbsent(serverLevel, ignored -> new java.util.HashSet<>()).add(treeKey)) { return; } - KingEntity king = AntarchyObjects.KING.get().create(serverLevel); - if (king == null) { - synchronized (CLAIMED_TREE_KINGS) { - CLAIMED_TREE_KINGS.getOrDefault(serverLevel, Set.of()).remove(treeKey); - } - return; - } - double minimumY = baseY + 24.0D; - double maximumY = baseY + 304.0D; - // Introduce the King high in the canopy, where his tree patrol is most visible. - double spawnY = minimumY + (maximumY - minimumY) * 0.65D; - Vec3 spawn = findSafeKingSpawn(serverLevel, king, centerX, centerZ, spawnY); - king.moveTo(spawn.x, spawn.y, spawn.z, - (float) (Math.atan2(centerZ + 0.5D - spawn.z, centerX + 0.5D - spawn.x) - * 180.0D / Math.PI) - 90.0F, - 0.0F); - king.setTreePatrolHome(treeCenter, minimumY, maximumY, 0.0D); - king.setPersistenceRequired(); - serverLevel.addFreshEntity(king); } + PENDING_KING_SPAWNS.add(new PendingKingSpawn(serverLevel, centerX, centerZ, baseY)); + } + + public static void tickPendingSpawns(ServerLevel level) { + int pendingCount = PENDING_KING_SPAWNS.size(); + for (int index = 0; index < pendingCount; index++) { + PendingKingSpawn pending = PENDING_KING_SPAWNS.poll(); + if (pending == null) { + return; + } + if (pending.level() != level || !spawnTreeKing(pending)) { + PENDING_KING_SPAWNS.add(pending); + } + } + } + + private static boolean spawnTreeKing(PendingKingSpawn pending) { + ServerLevel serverLevel = pending.level(); + int centerX = pending.centerX(); + int centerZ = pending.centerZ(); + int baseY = pending.baseY(); + Vec3 treeCenter = new Vec3(centerX + 0.5D, 0.0D, centerZ + 0.5D); + AABB searchBox = new AABB( + centerX - 512.0D, serverLevel.getMinBuildHeight(), centerZ - 512.0D, + centerX + 512.0D, serverLevel.getMaxBuildHeight(), centerZ + 512.0D); + List treeKings = serverLevel.getEntitiesOfClass(KingEntity.class, searchBox, + king -> king.isAlive() && king.isTreePatrolFor(treeCenter)); + if (!treeKings.isEmpty()) { + for (int index = 1; index < treeKings.size(); index++) { + treeKings.get(index).discard(); + } + return true; + } + KingEntity king = AntarchyObjects.KING.get().create(serverLevel); + if (king == null) { + return true; + } + double minimumY = baseY + 24.0D; + double maximumY = baseY + 304.0D; + double spawnY = minimumY + (maximumY - minimumY) * 0.65D; + Vec3 spawn = findSafeKingSpawn(serverLevel, king, centerX, centerZ, spawnY); + if (spawn == null) { + return false; + } + king.moveTo(spawn.x, spawn.y, spawn.z, + (float) (Math.atan2(centerZ + 0.5D - spawn.z, centerX + 0.5D - spawn.x) + * 180.0D / Math.PI) - 90.0F, + 0.0F); + king.setTreePatrolHome(treeCenter, minimumY, maximumY, 0.0D); + king.setPersistenceRequired(); + serverLevel.addFreshEntity(king); + return true; } private static Vec3 findSafeKingSpawn(ServerLevel level, KingEntity king, @@ -169,7 +188,7 @@ public final class KingsTreeGridFeature extends Feature> 4; chunkX <= max.getX() >> 4; chunkX++) { + for (int chunkZ = min.getZ() >> 4; chunkZ <= max.getZ() >> 4; chunkZ++) { + if (chunkSource.getChunkNow(chunkX, chunkZ) == null) { + return false; + } + } + } + return true; + } + + private record PendingKingSpawn(ServerLevel level, int centerX, int centerZ, int baseY) { } private static ResourceLocation tileLocation(int tileX, int tileZ) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityCollisionMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityCollisionMixin.java index fadcd00e..d93e15c0 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityCollisionMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityCollisionMixin.java @@ -3,6 +3,7 @@ package com.craisinlord.antarchy.mixins; import com.craisinlord.antarchy.content.portalgun.PortalGunCollisionHelper; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.MoverType; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; @@ -12,34 +13,30 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(Entity.class) +@Mixin(value = Entity.class, priority = 1100) public abstract class PortalGunEntityCollisionMixin { @Unique private AABB antarchy$portalGunStartBox; @Unique private AABB antarchy$portalGunMoveStartBox; @Unique - private Vec3 antarchy$portalGunMoveStartPosition; + private Vec3 antarchy$portalGunMoveStartVelocity; @Inject(method = "move", at = @At("HEAD")) - private void antarchy$capturePortalGunMovementStart(net.minecraft.world.entity.MoverType type, Vec3 movement, CallbackInfo ci) { - Entity entity = (Entity) (Object) this; - this.antarchy$portalGunMoveStartBox = entity.getBoundingBox(); - this.antarchy$portalGunMoveStartPosition = entity.position(); + private void antarchy$capturePortalGunMovementStart(MoverType type, Vec3 movement, CallbackInfo ci) { + this.antarchy$portalGunMoveStartBox = ((Entity) (Object) this).getBoundingBox(); + this.antarchy$portalGunMoveStartVelocity = ((Entity) (Object) this).getDeltaMovement(); } @Inject(method = "move", at = @At("RETURN")) - private void antarchy$teleportMobOnPortalCrossing(net.minecraft.world.entity.MoverType type, Vec3 movement, CallbackInfo ci) { - Entity entity = (Entity) (Object) this; - if (this.antarchy$portalGunMoveStartBox != null && this.antarchy$portalGunMoveStartPosition != null) { - PortalGunPortalEntity.teleportEntityAfterMovement( - entity, - this.antarchy$portalGunMoveStartBox, - entity.position().subtract(this.antarchy$portalGunMoveStartPosition) - ); - } + private void antarchy$teleportMobOnPortalCrossing(MoverType type, Vec3 movement, CallbackInfo ci) { + AABB startBox = this.antarchy$portalGunMoveStartBox; + Vec3 startVelocity = this.antarchy$portalGunMoveStartVelocity; this.antarchy$portalGunMoveStartBox = null; - this.antarchy$portalGunMoveStartPosition = null; + this.antarchy$portalGunMoveStartVelocity = null; + if (startBox != null && startVelocity != null) { + PortalGunPortalEntity.teleportEntityAfterMovement((Entity) (Object) this, startBox, startVelocity); + } } @Inject(method = "collide", at = @At("HEAD")) @@ -53,8 +50,11 @@ public abstract class PortalGunEntityCollisionMixin { if (this.antarchy$portalGunStartBox == null) { return; } - Vec3 adjusted = PortalGunCollisionHelper.resolveCollision(entity, this.antarchy$portalGunStartBox, movement, cir.getReturnValue()); - cir.setReturnValue(adjusted); + Vec3 collided = cir.getReturnValue(); + Vec3 adjusted = PortalGunCollisionHelper.resolveCollision(entity, this.antarchy$portalGunStartBox, movement, collided); + if (adjusted != collided) { + cir.setReturnValue(adjusted); + } } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityInWallMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityInWallMixin.java index 1d0db749..43802a05 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityInWallMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunEntityInWallMixin.java @@ -15,7 +15,7 @@ public abstract class PortalGunEntityInWallMixin { if (entity.level() == null) { return; } - for (PortalGunPortalEntity portal : entity.level().getEntitiesOfClass(PortalGunPortalEntity.class, entity.getBoundingBox().inflate(2.0D), PortalGunPortalEntity::isAlive)) { + for (PortalGunPortalEntity portal : com.craisinlord.antarchy.content.portalgun.PortalGunPortalRegistry.near(entity.level(), entity.getBoundingBox().inflate(2.0D))) { if (portal.intersectsEntityBounds(entity) || portal.getCollisionRemovalAabbForEntity(entity).intersects(entity.getBoundingBox())) { cir.setReturnValue(false); return; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunProjectileHitMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunProjectileHitMixin.java new file mode 100644 index 00000000..85b1d297 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/PortalGunProjectileHitMixin.java @@ -0,0 +1,22 @@ +package com.craisinlord.antarchy.mixins; + +import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.projectile.ProjectileDeflection; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Projectile.class) +public abstract class PortalGunProjectileHitMixin { + @Inject(method = "hitTargetOrDeflectSelf", at = @At("HEAD"), cancellable = true) + private void antarchy$passThroughPortal(HitResult hit, CallbackInfoReturnable cir) { + if (hit.getType() == HitResult.Type.BLOCK && hit instanceof BlockHitResult blockHit + && PortalGunPortalEntity.passProjectileThroughPortal((Projectile) (Object) this, blockHit)) { + cir.setReturnValue(ProjectileDeflection.NONE); + } + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/LocalPlayerPortalTransitMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/LocalPlayerPortalTransitMixin.java new file mode 100644 index 00000000..f0161b1c --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/LocalPlayerPortalTransitMixin.java @@ -0,0 +1,37 @@ +package com.craisinlord.antarchy.mixins.client; + +import com.craisinlord.antarchy.content.client.PortalGunClientTransit; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LocalPlayer.class) +public abstract class LocalPlayerPortalTransitMixin { + @Unique + private AABB antarchy$portalTransitStartBox; + @Unique + private Vec3 antarchy$portalTransitStartVelocity; + + @Inject(method = "move", at = @At("HEAD")) + private void antarchy$capturePortalTransitStart(MoverType type, Vec3 movement, CallbackInfo ci) { + this.antarchy$portalTransitStartBox = ((LocalPlayer) (Object) this).getBoundingBox(); + this.antarchy$portalTransitStartVelocity = ((LocalPlayer) (Object) this).getDeltaMovement(); + } + + @Inject(method = "move", at = @At("RETURN")) + private void antarchy$applyPortalTransit(MoverType type, Vec3 movement, CallbackInfo ci) { + AABB startBox = this.antarchy$portalTransitStartBox; + Vec3 startVelocity = this.antarchy$portalTransitStartVelocity; + this.antarchy$portalTransitStartBox = null; + this.antarchy$portalTransitStartVelocity = null; + if (startBox != null && startVelocity != null && type == MoverType.SELF) { + PortalGunClientTransit.afterLocalMove((LocalPlayer) (Object) this, startBox, startVelocity); + } + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/MountedVehicleCameraMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/MountedVehicleCameraMixin.java index e72b132e..680aabce 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/MountedVehicleCameraMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/MountedVehicleCameraMixin.java @@ -1,6 +1,5 @@ package com.craisinlord.antarchy.mixins.client; -import com.craisinlord.antarchy.content.entity.DorrieEntity; import com.craisinlord.antarchy.content.entity.HerculesBeetleEntity; import net.minecraft.client.Camera; import net.minecraft.world.entity.Entity; @@ -40,10 +39,5 @@ public abstract class MountedVehicleCameraMixin { return; } -// if (vehicle instanceof DorrieEntity) { -// args.set(0, (Float) args.get(0) * 0.25F); -// args.set(1, (Float) args.get(1) + 0.1F); -// args.set(2, (Float) args.get(2) + 0.55F); -// } } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/PortalGunEntityTeleportPacketMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/PortalGunEntityTeleportPacketMixin.java index 4a96a9f9..cb70b7bf 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/PortalGunEntityTeleportPacketMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/PortalGunEntityTeleportPacketMixin.java @@ -54,7 +54,7 @@ public abstract class PortalGunEntityTeleportPacketMixin { double edgeAllowance = entityExtent * 0.5D; AABB search = entity.getBoundingBox().move(offset).inflate(entityExtent + PortalGunWorldPortalShape.DEFAULT_SCAN_DISTANCE); Vec3 probe = destination.add(0.0D, entity.getEyeHeight(), 0.0D); - for (PortalGunPortalEntity portal : entity.level().getEntitiesOfClass(PortalGunPortalEntity.class, search, Entity::isAlive)) { + for (PortalGunPortalEntity portal : com.craisinlord.antarchy.content.portalgun.PortalGunPortalRegistry.near(entity.level(), search)) { PortalGunWorldPortalShape.PortalLocalCoords coords = portal.getWorldPortalShape().localCoords(probe); if (coords.depth() >= -entityExtent - 0.5D && coords.depth() <= PortalGunWorldPortalShape.DEFAULT_SCAN_DISTANCE + 0.5D diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/ScreenEffectRendererPortalMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/ScreenEffectRendererPortalMixin.java index 49327550..60953279 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/ScreenEffectRendererPortalMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/client/ScreenEffectRendererPortalMixin.java @@ -4,7 +4,6 @@ import com.craisinlord.antarchy.content.client.PortalGunRollClientState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ScreenEffectRenderer; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.block.Blocks; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,7 +15,7 @@ public abstract class ScreenEffectRendererPortalMixin { private static void antarchy$ignorePortalViewBlock(Player player, CallbackInfoReturnable cir) { Minecraft minecraft = Minecraft.getInstance(); if (player != null && PortalGunRollClientState.isEntityInsidePortal(minecraft, player)) { - cir.setReturnValue(Blocks.AIR.defaultBlockState()); + cir.setReturnValue(null); } } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/BubbleColumnGravityMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/BubbleColumnGravityMixin.java new file mode 100644 index 00000000..4c7abbe5 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/BubbleColumnGravityMixin.java @@ -0,0 +1,33 @@ +package com.craisinlord.antarchy.mixins.gravity; + +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BubbleColumnBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(BubbleColumnBlock.class) +public abstract class BubbleColumnGravityMixin { + @Inject(method = "entityInside", at = @At("HEAD"), cancellable = true) + private void antarchy$applyBubbleForces(BlockState state, Level level, BlockPos pos, Entity entity, CallbackInfo ci) { + if (!AntarchyGravityApi.isGravityInverted(entity)) { + return; + } + + boolean drag = state.getValue(BubbleColumnBlock.DRAG_DOWN); + Vec3 velocity = AntarchyGravityApi.getWorldVelocity(entity); + double vertical = drag ? Math.max(-0.9D, velocity.y - 0.03D) : Math.min(1.8D, velocity.y + 0.1D); + AntarchyGravityApi.setWorldVelocity(entity, new Vec3(velocity.x, vertical, velocity.z)); + entity.onAboveBubbleCol(!drag); + if (drag) { + entity.resetFallDistance(); + } + ci.cancel(); + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java index 0cd093bc..152c4e41 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java @@ -4,7 +4,6 @@ import com.craisinlord.antarchy.content.fluid.AntarchyFluidChecks; import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection; import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; -// import com.craisinlord.antarchy.content.portalgun.PortalGunCollisionHelper; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import java.util.List; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/ServerEntityAccessor.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/ServerEntityAccessor.java index 0b4f0515..8c108616 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/ServerEntityAccessor.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/ServerEntityAccessor.java @@ -1,6 +1,8 @@ package com.craisinlord.antarchy.mixins.gravity; +import net.minecraft.network.protocol.game.VecDeltaCodec; import net.minecraft.server.level.ServerEntity; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -9,6 +11,12 @@ import org.spongepowered.asm.mixin.gen.Accessor; * Accessor for server entity tracking internals. */ public interface ServerEntityAccessor { + @Accessor("positionCodec") + VecDeltaCodec antarchy$getPositionCodec(); + + @Accessor("lastSentMovement") + void antarchy$setLastSentMovement(Vec3 lastSentMovement); + @Accessor("updateInterval") void antarchy$setUpdateInterval(int updateInterval); } diff --git a/common-1.21.1/src/main/resources/antarchy-common.mixins.json b/common-1.21.1/src/main/resources/antarchy-common.mixins.json index 6e332818..03768287 100644 --- a/common-1.21.1/src/main/resources/antarchy-common.mixins.json +++ b/common-1.21.1/src/main/resources/antarchy-common.mixins.json @@ -7,7 +7,9 @@ "AbstractMinecartMixin", "AbstractArrowAccessor", "PortalGunEntityCollisionMixin", + "PortalGunEntityInWallMixin", "PortalGunPlayerMovePacketMixin", + "PortalGunProjectileHitMixin", "ServerGamePacketListenerTeleportAccessor", "PortalGunZombieMixin", "FallingBlockEntityAccessor", @@ -71,6 +73,7 @@ "gravity.AbstractArrowGravityMixin", "gravity.BehaviorUtilsGravityMixin", "gravity.BucketItemGravityMixin", + "gravity.BubbleColumnGravityMixin", "gravity.ChunkMapAccessor", "gravity.CrossbowItemGravityMixin", "gravity.DirectionFacingMixin", @@ -171,6 +174,7 @@ "client.MountedVehicleCameraMixin", "client.ParalyzedMouseTurnMixin", "client.LocalPlayerPortalMixin", + "client.LocalPlayerPortalTransitMixin", "client.PortalGunEntityTeleportPacketMixin", "client.PortalGunZoomFovMixin", "client.LivingEntityPortalLerpAccessor", diff --git a/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json b/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json index b55fc033..630557e6 100644 --- a/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json +++ b/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json @@ -671,6 +671,8 @@ "tooltip.antarchy.reverie_bottle.release": "Right click to release the Reverie.", "item.antarchy.gravity_gun": "Gravity Gun", "item.antarchy.portal_gun": "Portal Gun", + "item.antarchy.portal_gun_atlas": "Atlas Portal Gun", + "item.antarchy.portal_gun_p_body": "P-body Portal Gun", "item.antarchy.diamond_minecart": "The Diamond Minecart", "item.antarchy.cogwheel_pet": "Cogwheel Pet", "item.antarchy.fire_dragon_pet": "Fire Dragon Pet", @@ -837,13 +839,14 @@ "tooltip.antarchy.gravity_gun.secondary": "Usage: pull in an entity or a valid block.", "tooltip.antarchy.gravity_gun.scroll": "Hold Ctrl and scroll to move the held target closer or farther away.", "tooltip.antarchy.gravity_gun.blacklist": "Does not affect blacklisted blocks or entities.", - "tooltip.antarchy.portal_gun.primary": "Attack: fire a blue portal.", - "tooltip.antarchy.portal_gun.secondary": "Use: fire an orange portal.", - "tooltip.antarchy.portal_gun.channel": "Channel: %s", - "tooltip.antarchy.portal_gun.owner": "Owner: %s", + "tooltip.antarchy.portal_gun.primary": "Attack: fire a %s portal.", + "tooltip.antarchy.portal_gun.secondary": "Use: fire a %s portal.", + "tooltip.antarchy.portal_gun.color.blue": "blue", + "tooltip.antarchy.portal_gun.color.orange": "orange", + "tooltip.antarchy.portal_gun.color.purple": "purple", + "tooltip.antarchy.portal_gun.color.yellow": "yellow", + "tooltip.antarchy.portal_gun.color.red": "red", "tooltip.antarchy.portal_gun.reset": "Sneak + use: fizzle your active portals.", - "tooltip.antarchy.portal_gun.size": "Portal size: %1$s x %2$s", - "tooltip.antarchy.portal_gun.grab_strength": "Grab strength: %s/4", "tooltip.antarchy.antimetal_inversion": "Inverts entites directly below it", "tooltip.antarchy.diamond_minecart.forward": "Will be implemented later.", "tooltip.antarchy.diamond_minecart.rails": " ", @@ -1250,7 +1253,6 @@ "advancements.antarchy.duct_tape.description": "and fixed it with the power of duct tape!", "key.categories.antarchy": "Antarchy", "key.antarchy.portal_gun_zoom": "Portal Gun Zoom", - "key.antarchy.portal_gun_grab": "Portal Gun Grab", "key.antarchy.portal_gun_reset": "Portal Gun Reset", "key.antarchy.brutalfly_flap": "Brutalfly Elytra: Flap", "advancements.antarchy.shrink_ray_craft.title": "Honey, I Shrunk the Mobs", diff --git a/common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas_gui.json b/common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas_gui.json new file mode 100644 index 00000000..aa681381 --- /dev/null +++ b/common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas_gui.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "gui_light": "front", + "textures": { + "layer0": "antarchy:item/portal_gun/portal_gun_atlas_item" + } +} diff --git a/common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body_gui.json b/common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body_gui.json new file mode 100644 index 00000000..b3b54a1c --- /dev/null +++ b/common-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body_gui.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "gui_light": "front", + "textures": { + "layer0": "antarchy:item/portal_gun/portal_gun_p_body_item" + } +} diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_atlas_blue_vortex.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_atlas_blue_vortex.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c61fa89eb22409930009aa049dd024086191b4 GIT binary patch literal 704 zcmV;x0zdtUP)Ix8050x_z>XKWp%5PDc39Dm@00R=_ko1b^=*x z$0%?_<5Kr@OJ<}DsYJNN@uRGe3m;*_o)Rg7M|hyzC1LBm{eiUFz-xJ0cVv1c96>Ux zFdZ`yOZxXdg;byyCWrQMy0c|J3^&%uW_U>4OPU7{=js4o<>x? zlTBmE9^q2~sJHqQELqx~LC+6JK3=23_W+0nBHQUiCTU)vz8jCMX9B8M81@2<A6Ae)_v_BxF>E2VeBjM9BAhk1su;i59kQM9+CL4U= z6P2iNstnr$9!9u*Pu3ZkdcVLPJdDtDN`byLGrcZUv}UB+Xn7%V#<{}utW1Hjc$$9p zY`I^W0i~`h2cv68?{fcBZbqk}=p|KFh@?g;-2Q@tlu&Z;*q)PkfDzslK%PIGh_NQDK(n58Wmth` zy(ExOg`(E?Sph52gsZG~V?z@tOC!|sCRDlhuW;36>{MtY}ivGMeqm@l)EHsy|+J*RvUONPwS3MuY@B= zW)-GmCSpnd9;`&OUd@op7!7QQnjv3|QkATkVy>(;cY8C#?Q}(~3}(m!Rtbei;Q8!B z3Xk;j(cYMjFInYPX-1S`Lg}7z3Ro}Q*lc&CWX-5_R(40IbnZ2d6sDnySkWJtPS4Yb zs&}$!EZHM`DggCXpMoVz+cW6-0m;W}RQMhM(LiK7oya833)FYxk@ZYK^$NpYpmAK4 z1?v6)Wx-Ps)HSX>PQeSxGRkgDE+zWbys}PkEk(ZtD@!?-0`@C+>AEc#USq+qGNVeX zDhZyj7SMHNxTKDfll~kDx{j7j*<+$1YKHa)q%_@o%624tS_Y(cMi7>q(i^gZJ;7vy zFMOgB6;735d%(j8x9`b1BUA4e*n@`=dQK_Ow`Qi-g^JdUbQ>)%B+fWjn4Xm>P!>#!OEaL(1m?dV07*qoM6N<$f=i}Eo&W#< literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_p_body_blue_vortex.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_p_body_blue_vortex.png new file mode 100644 index 0000000000000000000000000000000000000000..5f968f76b6a5afa0c3ca060c5c2fc1a491987d30 GIT binary patch literal 705 zcmV;y0zUnTP)1yNLG|m&v+b{*F-`>dTsoPJ@L57?FNjmkJtP6 z=iBe!==aC_%YA#MJ$q9PD|k=%NQv$LslwaXo|AZh5#AI)oOHRJr!B>m?C9h$lz^wfo@=kl}bjJk19rRSM33 z`QN(_N*^a2Lmrjw=>w1}Ngo*Gl-6%c0E1i>93KLlx~y(hGUa*&98<-OGW{gk#7-b9 z?HC1)Xk6-^Zpn<4A(aTXIDV8Ba^WLv*i#}!@CXl-yCiJAw?B|p8+a{G>yAvXgd<31 z6{ce*VoCoVtVFY3&5+9&4Qz;-AzzGAm8_X!uB;t}MwDSf>7H^5STEh!Yh(I1#j&(nyi zcd}_L*&}=^0QFX%f+b7aGwAsN$;WF{_#Ob!Kx8|e$Ry1R)OX{N^-MtZ3d3HYaa@%J z>iz&_!BY{`HLg8Q!3)YV%5F?9CHmI9vQBUhr4{u~Lqj+RZ?W1=ByhV}=fG~Ij3b|idS2BdaI5SEp|^ODlkI|fIzoDuv3s&KbmHal5e00000NkvXXu0mjfoCQR9 literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_p_body_orange_vortex.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/entity/portal_gun/portal_p_body_orange_vortex.png new file mode 100644 index 0000000000000000000000000000000000000000..301345a9ed7ed58b065b0319d754bc23ef156911 GIT binary patch literal 701 zcmV;u0z&6Xk$8B&RGi{nRGAs0TvhCL-x1ds4Qxl6*3CN;raKR$)43 zB9`>;!Admi)eO0e(ZGhN8S=#_Rmqwu=E_=gw>LA~PFKXrV1_(kl~8yDp3gp{@JK%& z?TzX9l2u-nW<(h#lVGKz%nJSCcg%>uA}OJti8WW@vvvO4GfkY)8VUWk70Y1YyZ3y&)^u6HGSv!Y3+G z;Zzy62Rw{$`<|>bGWC9eJ$M+Q=ad3{Yi4>~sA$bdx6$%K;*4{J=~G2gz9ihSY@JAGu%PzFqSdLt^h2gwfRU jJ1;3sy<>1h%NfBx=IO^$8`VjQ00000NkvXXu0mjfSQbvO literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_atlas_crosshair.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_atlas_crosshair.png new file mode 100644 index 0000000000000000000000000000000000000000..cc6ed5f553cfa2e37336980f998b38520dfbcfd6 GIT binary patch literal 286 zcmV+(0pb3MP)}fGl|85qp?9>vLImUxaHtGa`apLK!+;jygUKQA zbTZK82go5=+7AYqLk23L4l0L$(#PO(2q=9Fq(eZCfICDts&HgG1eQ?2IhN*04sJp>^`IK*Z=?k07*qoM6N<$f@c?V6951J literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_crosshair.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_crosshair.png new file mode 100644 index 0000000000000000000000000000000000000000..1adf142c8305ae800503704ba3b99e9911438f95 GIT binary patch literal 341 zcmeAS@N?(olHy`uVBq!ia0vp^NNn{1`ISV`@iy0XB4ude`@%$AjK*3j@E{-7)?oX!~avgFIa4i$LbL+&lND#l*MF?|aa))A#ugdV8cq zl+?doYq0L`J^z`L6>fWnZ}{`?I;Z_t>mZK}(u!;6Uw9{0YI`!;u&bo~>E?A=Iul-; zUmc}VrNbcGc;bR+s2xXY%1?z%7ajFg3xqnRytbOzp|wJxm*dk!Z@;76)A6e6<5uP2;fu^k=mdKI;Vst0KB4wLI3~& literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_p_body_crosshair.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/gui/portal_gun_p_body_crosshair.png new file mode 100644 index 0000000000000000000000000000000000000000..20d22c0c3fbbef612eb5586af3ea3bbc0798ff17 GIT binary patch literal 534 zcmV+x0_pvUP)+t7^Y{y=xw6L;L|4n|F)kWy@83kIm@jLd zf;1a5W*kIWW`EsBK(rbzOK*eNo1II0PC%#z7rHDx_qXY2p)N22!Ub##qfgCGRm@_w zB9pXN5NcoG^FFxi^k>lblQ2}mdcj&{7ChXWJy#B8kB z&GEsiyaoBew|06@QLL~2Mt$11zr17ARJMkygy<7a)EtObMUy_pY=7V<6(Kl0xljMK zGj}aL$mkEeQV=G-blzA_*cP4^^>hY8>5&@gs1VGx8pO^(DE(TkW-!JG5mO1`cDIvj z1!o|-T8wX-tppLq^JOBUy07*qoM6N<$f-;Zg2LJ#7 literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/item/portal_gun/portal_gun_atlas_item.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/item/portal_gun/portal_gun_atlas_item.png new file mode 100644 index 0000000000000000000000000000000000000000..bf83fce8dea718b1d8bdad62dbfa2e70f36adfcf GIT binary patch literal 415 zcmV;Q0bu@#P)) zy-R{o6vm(TMVhK9)V8vZAu1Z0`XC|5$rholhML0ugvJJk+WMeWq9F&NL876l8j27@ zv5@eqEW%WJEo*9d<2mq3f!NT{;DsOe-gC}#?sJcdKdwe?Ff=%-8^{bCE8BW4YR$LH zHlV+MR1k}wD@3Jm(KQa@ce`Lv&L!dW?CY*TOyHT~mgZKF9}f7^u+_{Bk>{dN(ljJ? zJcupNBI9x6F|a9ltJw+zI*~6>OkwEZ6^VRVV70~EjviaD2rM&m=$>DKZl4mg&JLD9 zrB#ZbKAZ6NQjlP=RFS<<%p;Xe3Jgp;CowV7FVG=l;@~u%L+Un#bh?1EiyMT3LG)dX z!QQr7#pE+#Z+#2i4WB@9CVQ=@Vegtk0XaE7L^67byMtZj=zc-*haFXTXDxGTGy=k* ziUS6}!|wIq%LdY*Uh!|a|8MXG00960ICf4l00006Nkl) z&nts*9LL|!b8y0On;Y}vAmpHwA5n@6ij|y9yNUb(iqo!cv^0|I%3*O)3I|%6#%O8J zHjUQoSvE$B%cJ+Fo<*%WI5_NEufE^!=ks}gzVGix#UEFtHt6i=HB4j%Bkm2O6s6|d zXm2-O-wL=4pDIM9aL&;WvNi93Nj@3H)&7L>5t$WurnsiM7UYKmzSL#2a6|A>7qYn= zCKqF99lb#Jvs zEP+a^6sJC`@bZ+Apq?$rp3&3L5>bJH@v$Kc^t1_d$e1`d4kw}AYKX-$I61q4-{*rX zaEKMW7wPl3v9soZcYRZ!IG(sx)N}8uLIF8C*h4fFz}@b)vYdKQoQZf5-dW3>8VZ7N zsN#UZ@34D0__B#KC|CSj?*AKn0RRC1{|P-CWB>pF21!IgR09Az&cY$T+zJ)|0000< KMNUMnLSTYrExca< literal 0 HcmV?d00001 diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/models/item/portal_gun_atlas.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/models/item/portal_gun_atlas.png new file mode 100644 index 0000000000000000000000000000000000000000..af3e1521da3109d0106689b5310a971c306824a0 GIT binary patch literal 3046 zcmV~Y7V{qd_q9o%2!$NWAxG-_01UD{RxNxHZT^i#o z{a6?`OacZmxR4+Tl4y`91A~u&JdzQ4qmRJ^8h-ue|K5Fv+g*LD>*H3{A^hJx=iGD8 zJ@=e*t8Z6T&$LMR@B0rtGQ0oWvva)g@=LRC{rbV#j~@No9Q47{0^}i&EMcmZR5xz; z)a>}NPaHr@CY_axj!Y@301jV$G#Z|puRC0P^5%_spVbkscCO@qvWY-a0a&l!clDuy z}* z>6dmcQ_VF;j$T`Ua0ZG28GsJ^oZgQ>asj05_Vk z0ERxf^BPT|-7bDEeESb_yYnsowpuO!bLeA-189tjX7>Z+$mnzIMnHd)3&18@hSX}; zQv}FpAA0PckhSB#JKJ-cBpART<8z;#4-KG^(eF4IfusV6?c%T?e*EPxOu+YU|Lg>a zroHFZk53Lxy`1BQ4*1ANKR1hkzC{+;?b`Vi1~kA9;i5p~{mAfZhDW)0+i_ z@T;>I3U)g*IQ_&w8i^4*SYQHZS`rJOkpXCA09rCy0l8y80#k0$a@!W%fB81AZRrE- zYQSy=+S$;^(E)b6c=|v%CwvHW;kjg6;5IUn2@Q04M-Gh)po0vW)&jYsD5iXu=SIy} zP8=;b;m1J#s=-1xW&;^>(9fKU>~S?&)JIb3Bbm?uJ_Is=4svK(M?3=aj{t(sXSrZi zNgj!_a?7KGu9eF!EpyraRe2?KRekiTjA7hZFfRZW8zzQC34GRrupj*x&_NeyJgs!; z7hR?0a3_#hfE~%8kpanQkvrlM*ed{bFDmTd5V~x00Hl8z(7_I4LL1PGqmOnKoZtHE z#A5T@;}aq5TPC9~)Geb|@vYA~*7v;vV0Qv`uLUQ64taL4<27t#tG!T!hE&Tnd-%mpD(Gj98KiZyW%6EBzJ($F9eCs+kO5@6mmofM z&UN*dUH<7?*M6?!4}1jV>SP;!g_nQmHs;J>j!_l>JDTSLBp{^W1r-4w1JLNHZ%A#W z0tj#Aa_bhJ7C`qkKsp2T)&DAfS1JG=0@=xO{)%UP9V5SJ&6Ntk8lxaMy(5RF%^l%0 z0%*Wx9zX-FA*3Z6O1oA8ko0iphjh*X;&UC~BQ3X%0knm5kV6j*l?#C6+hD|GR>%3g zA~1g+0GBwx2|SNqhTA^<;rTCt_%#sU-}U}Kk9n{E!102ggz?ic+354Zkk||v^D6*} zs=CP7SQSK7n?A0+2+RvW_vycQ!-poIY)%@Xdf*y#Rm5h67In zc`64u*)Ib+7Cgn{Tma~U#|AC@*aF*^_0F#Va+U`qd?wNYX!WJGjKu~Jood7Nn~%U= z0dN4~y?QKkf1<&NFgfBut# zT^d^?azH`>I`AYMKqI3Mzyo9!$eD{dZC_hFK2WfN=CyKo)}#KRwo`u7XHW90ES4Wz zf>m@w9p+-rP}U{Q=^u3ILzi<;tDe%i^n+CA`9{E;spDKfEdr}*&(8p>Du;SpB0(tY zBTW&5KKfpV&y@?Hj>)^Q!QqZW9)Ok)@BrBu4u4vA?+SoN%RGk&flLc3Yq@Ia00_-N z7VtF{Kx2a<0MJ85?+So-4s^Sj#6Tm1cBDt3cLks&l6WBA+iDT$WdZ2d#wra z=v@KCc705i7KZU^_pShxD&9i?;=SFCKRCQE2AS3CE8n{U zAkh4S6TD~wppiMMMWA;DaQ(H{P4uD(x0IogRa?G~>RkbN%Ib~4XbONwyLF=8G<0Vz zivr-bZuqODvT&s8m)RS0f9C~2GWj0QNgnV|%ux)Bl0qLk=mN%KW0Ahgmq(zp0^k7- z$s~ce$nOXMG>MHR6&Zc#pbMa}fh}wTWFca*uzv`2)irch0G!}?h1`M@J-F|Vy9&N< zhd@Rju;bvd32ZPz8IOCxonO0W2CVMb_|6KTEYQ4IiViIhO}h@p{Q6fcZrK(<%vqP! zAAxKOKs%KduynQ1>!2<>>-dn%*lY{H21p+RR_^?I5$H_;thY=by(j{`DFD5zw`d_Q zuNHx93qY@G(*l;K7J41jWoI29>KePQoz4n?@ArHk2fU6Q0-0SHze3{hCOvcjcKDY( z1Z2{QwX*x?KRi-A_1IsEP=~RC>`8y9ZL|OgDrj=iJec9NY@pY))gl9{>hLdl2z*rV zdbb6;UO)$kr$rx`(B#^4vK=jeoE%K`g`$apf)dm(o>nroDyY=?`=&p*0_a-;y7o6( z0DR{LT|4LVHy?p$0W?3Y&yY(5rX2PJoq#zA;UK*F)FO8bCjwI)dT2Qe0ZYRR!&!R2 zS5lYv{t-}DBztPd3!tZotIKUKfVv{tQ#)P&JxyF)ZhHaL70I63DJ_88H-0+%%(3qd z{+~_nY5vxByR-nVx#GmylQd=E^FRFU?ACAJ>&3Z7fJ+Mi+ehC0L7MDv)$tpPtKNTO zc78SKP~Emm3*ee7ZmN4ux0g`_N(&$(U*F-%8~@vWhs*_O5m>1Jay|#}F_5-o*A64F zQUQbmoE}yLya0xk&*ari`JR8*O%Kh$H$Qf6W`V_5UO!uedg#InUEU|Sc>XzDbX1JM zbo>9$7tddOc#dbcA1uHtuRl`&Xn+oo9xc33aqiM#cmCqZnQ+I?{y4Lc0qzG#j}~6= z`vi(oyq*4O>jx9zfz5ABz%QSWoRmRL$I550SqC)xv#+s zAomP4>|b&LoIZVecIM2Py$3MxpkY7Vd_xgPE`XRH$BrF~iCxx%2qYJPO}6EGux58L zh(K}yY;0@M~6 zG>kyobgczoUkuWNYAt|#mgSzT8UZhWRUVf+X#bW}z~iBU-y^Ck{25Fwe6Ng~Xh{QBkpUcE!z+g*M8c30m%!~9>JI(6#Q zsZ;;zTerJ!rbWVkU-|j@+1ckVmw5i#3$xGt=ohnZ{O<21XroRE(1&$&2}9K~-FW;R zvtvi!yazFzY-%|jnNbn}4jeihP0z_k4is-Yxly)R8`V{oM*b(83?vc2M*W&Y`wJEy z{aX(_OtAy$DOr5VoyL}gS06Z7dYV4GzW`LELv~bWAc+9;7SS#~3(n9GgmPX#+SH!U~|Em>_{m*E13GI2l(fb588pb-J$uC}$eZ(QFN9{j!d z!tDpr>WYJhj}#yr0WzQi$YGnyyBSC(K+2B)-;F!FBdt)ndHq@e>=5XH)q8z61IYxS z>tAlaL{VtBt6nPa|3PnezOCOkYvq3qee7_6j8n<%et;ewZI0~>=x;Is>|)E2O6__` zfR6I%Xa0@YI&R&*S^8vw0Tpz7?z8ie0Wvz;9eXp7M1a^X4hiw?kG_8bzWjlAPk>~~ zr{49Z$=;zC*SMhr-uT3OXED$=&jY(%J0D^o1N_hr=;n|u=lNV$eG&oK&Cg!kEFi)U zFI_L#?a1KFv;SI2j@ZEh10YkfumBkyKt>0UrK1$kJ9aZL!h zb~DhDo14TNJ-4}mRpF4-1@jgG}c2D-eXM@9#*L5ECff!E$ zm479gvO^y(6B19Rjd>F<}RX&}EwgAnl8Q4Swho`aq^1ZIpFzb?a{v zi_Pc$I1$3OMLOC-+bX$EY(uuOvF{Lo-3i#e7M%P!|P7*;<2;q28bf$HeG!apwjauR}%ju2hN(e*e}zRL?No&{~GLD9$hp^iQTI)G015>!te zb6NXEmw(!p^`C41Js$zN2H8bi;pHE>i!pN;W0VA7NAp~O1qfy8f=Ix}05W!JTc@%S z0m56k+`6Ss36O`HAe{k*8h?|x8xeqqKz6X4zv9_g$5@{?=SBpu&L9M*cl5}Vxg&f= zfDE|I17x5%gtBz&QZ7XR7Cqegp`3Gq_*@6XNXe~ZfNUWf^vLUm#spyTZ8BmyYvc92 zGElw`Ku8?m1fIt)!u#I&`tp}R{2GYw?|T2A$Gnd|cC6qhVf=JVK8AcSBsc4f@(RF0 zHJxOvuL#l9r}yhF10?};pZ>|mk553=@Yn$C)OXS0Z&4dQ`Ua1TLEmxoG5%DG!vT)n z45|Xb2G9pv`4Ab<ZoUAI2uKZSwQxbruZy~BWg|^6{y{-a0{X;*5ZwB1z1;jfx?0Fi< zQ#ruNei5*-;3*#G0zeyed{9y!TVjVY-|`BeV0l2oXCfs)R$FRGUwi<`sXp9(^%>Y9 z00$u6tLHOO4@Ec}p;s7MNETH(WI&sA^r5f(;1l2IWs_6MtzM8*OkKrN5`YEdAjBak z9GE(K7MI1-qLM6h0GWlR4I6ayp>NC=V}<&zW#S_Sfx2RljuJidQQNwfQ|{P(`upE0 z*rl;aq6aJ}z=k>t4v^8&2B-sc7U&s^F>PB{bz*?9g2uIa>dZ&&>sn6vO`ko<*O@Fo zwgh!-LmS3o%uv^-%;_KW8AG3APn(|7x%7k7;Q2OC$(& zLzE#g7-H;g#N3zwZ4BOr4-R)6@&K}8pbpTD;qa$<4~_slTIM-K2y~iIRmoLL2S8*F zvVgCt02v>U03fe321fwiIneE976us|vLihMgCl^Z$if5Fy=<0&K@vc}HfGA9Ox=-| zfx!_Vw(DcMv^0#@dT<2LQt=)FP~FSz45a=Y906jN{Fu%rf)jlV*3Q;reb8CEq1FdS z020kVIKhi102!U5Sq272fJcu!GSQ1B+)_qH*KGRUYj6bcC2KbWqagr~cH2a|%g~>< zEC|4D-SAgQRq05zukttM_TCA=V)8wnlRV&`n1c-S7KJu!um$wR$2@!2FU~-31mFP< zi^&2KBEKU5$SiDZQPI(c4YmLoANay2Ko=sW3)|O0ZaRnF2*3%RSI8|m(SvV&@Z$yF zw?m+#4cLCv@d<1)LLHBL!G}Nf)C^eLvDJGcKvkl7u@oChAenL*jQRDiSl+TFKrC3- zwV#1(380-y37EP{_p{>5l`ss}Te81=WIN){c5a{g0_!Sa|H`!qW@Wa34 zA)u2@td!qB{Q7)x;h8@dp$&Zn`IG&+mQezbRItiP^I(S8vVmUHR*4SOwc%g#5csIz z^==Dxy?_l+of3O=!Yb#UlkX@2atbgt7Dy8Vgc8)QI;C_fMX1#Ahi1Qa1Q^-^^c`=M z0DR{LeFx{`uRa4&0<3;mA0d|vOgZccIstPKB0%bDQ;FWOJ{g$m&_l^#2w0iAus%~C z_DtG}-ai7`%H%-(H~|K_aBYR{1ZXRh1NGws80f;a6}A(gtxOKoPbC3<{N4A=zV?N; zul+xpKG5}BI_ydUyy5tv;`qkFr3YGtgRdUjn0@BRQ77jT$*m;7624d7^|6Qc6|a5O zzLk%Y(*SM9Qb~Z5_pbnL59f^(0r76JZw`9|*Z@c0^LV9NLWzn=Zj4BWl&$(e=xhIZHjbfC}s1Xu3fQ;1$R z$iVdS=FQ?~=Qj&>`A?s|Qh7R zQWyL_fwB}Yr(gW~pC;fVpZ(QDc*~PNnE=&kuR`4Ya@zm?|6cL?Tek{!`EOr*u>k+M zceen@02_dvKwVfaf_!?fDw0}ffK?4%<@bBnwkF_9S2riZCoW%_0M%))Le)59ZqJ$k zV_ul9=I#XOD$|*clT3g!XU@#dojbSl0ERlqbbcOIMFx@y5c7BR=+T(kbpyyiG6C#j z+xh_J>>&mjNG8C>#zxS6Ta4+pTl{bC8Av7o6ABkRlxcIcn}Jn(Yeaxm2j%{|%YYN0 zyIf~EQY!@5+}zA^avoH529gQji(Q@6Az367fXRg<2xZzF!^%K10k*cb3ZQ8s1J%78 zRtAy@aQgJ=3D7i=f$FKHy^S2+W={3x_URc&CP4ZSi+fn|oH})Cvbe`MTDzKM?*!;- zqCQSM15SW=UPhyJ0*q#<;}dlP#Pc#5trK80OC6u66Cj?K(P*6jqgm?sL|Y{QH*vxn zJGLGV!L?xqx|UldfPFc{*1MjZk5`?6Rtdmx_8mc6$HtLQ23jY8oti%=vKh&%-YNm? zqhVXmYw8{i8EBONJjek!2FUhd4|+#F8EBON`Ao|rsha^OK;2BOshtxblZEXo3@1Qe zna^ZgCqO0((N`EwfW9)H$+%8{OctWAFq{B=Wj>Q}odB6EL|Tw9%+`zPF8 z?R)UKkRv0DxL5crkI(ace!P#bcaiOO8~FoK__fBN$zsA1aghiR=eyV;Mg26fMUtdQ ziL}UwEM%~y@JSF8{c8a+#Ewal6M12aqBw;jwmd!=ViIWlssM{_(ujHq&O}+9i>h#- zimi-~O-vdM>(BzcfFs6RK(rz*#HDD6rnrVCwo7~}#1zmt+E>JP$xrB{M3;4vx#C8& zMF-m0Tzu-pl+ZZYSHxFmo}_A8bM-D4kfZu(FaaA}+mu@`42k}J07cmzLm}8sa^FT}&jXIh(IXaKG z@Xx=5E?|~>-QmnSEYg^fE;#SaHwA3) zSr9Wuql2bHj;z0kMidbG5g4(Aq5lj+zlcJ=ibMZ1GUD$z^am0n9?6V&C^h1-+=v$w iBVNsncsc#o*YgjuD9+XSP?A6Z0000 PortalGunProjectileEntity.releaseAllProjectileTickets()); - ServerLifecycleEvents.SERVER_STOPPING.register(PortalGunGrabManager::clear); ServerLifecycleEvents.SERVER_STOPPING.register(com.craisinlord.antarchy.content.portalgun.PortalGunResetManager::clear); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { ChronosphereManager.refresh(handler.player); @@ -209,14 +206,13 @@ public final class AntarchyFabricEvents { }); ServerTickEvents.END_SERVER_TICK.register(server -> { - PortalGunGrabManager.tick(server); Set activeThisTick = new HashSet<>(); for (ServerLevel level : server.getAllLevels()) { CavarynHordeManager.tick(level); com.craisinlord.antarchy.content.horde.CavarynCreatureSpawner.tick(level); ThoraxisUndersideManager.tick(level); + com.craisinlord.antarchy.content.worldgen.elythia.KingsTreeGridFeature.tickPendingSpawns(level); tickInvertedPlayers(level, activeThisTick); - tickDuctTapePlayers(level); tickIchorPlayers(level); tickBloodglassRecharge(level); AttitudeAdjusterSlamManager.tick(level); @@ -338,14 +334,6 @@ public final class AntarchyFabricEvents { } } - private static void tickDuctTapePlayers(ServerLevel level) { - for (Player player : level.players()) { - if (DuctTapeBlock.shouldTickStuckEntity(player)) { - DuctTapeBlock.tickStuckEntity(player); - } - } - } - private static void tickIchorPlayers(ServerLevel level) { if (!AntarchySettings.ichorWitherEnabled()) { return; diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java index 3e98e667..fd945a85 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java @@ -625,15 +625,14 @@ public final class AntarchyFabricClientBootstrap { DorrieJumpHudRenderer.render(guiGraphics); HerculesBeetleChargeHudRenderer.render(guiGraphics); com.craisinlord.antarchy.content.client.KingJudgmentFlashHudRenderer.render(guiGraphics); + com.craisinlord.antarchy.content.client.PortalGunCrosshairRenderer.render(guiGraphics); }); WorldRenderEvents.LAST.register(context -> { BloodCrystalKatanaTrailHandler.render(context); ScorpionWhipTetherRenderHandler.render(context); WormHookTetherRenderHandler.render(context); - if (com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer.isEnabled()) { - com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer.render(context.camera(), context.positionMatrix(), context.projectionMatrix(), context.tickCounter()); - } + com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer.render(context.camera(), context.positionMatrix(), context.projectionMatrix(), context.tickCounter()); }); } diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyKeyBindings.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyKeyBindings.java index 6eb99e73..92714e01 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyKeyBindings.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyKeyBindings.java @@ -51,14 +51,8 @@ public final class AntarchyKeyBindings { ); public static final KeyMapping PORTAL_GUN_ZOOM = new KeyMapping( "key.antarchy.portal_gun_zoom", - InputConstants.Type.MOUSE, - GLFW.GLFW_MOUSE_BUTTON_MIDDLE, - CATEGORY - ); - public static final KeyMapping PORTAL_GUN_GRAB = new KeyMapping( - "key.antarchy.portal_gun_grab", InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_G, + GLFW.GLFW_KEY_Z, CATEGORY ); public static final KeyMapping PORTAL_GUN_RESET = new KeyMapping( @@ -78,7 +72,6 @@ public final class AntarchyKeyBindings { KeyBindingHelper.registerKeyBinding(ROYAL_INVERSION_TOGGLE); KeyBindingHelper.registerKeyBinding(ROYAL_BOUNDARY); KeyBindingHelper.registerKeyBinding(PORTAL_GUN_ZOOM); - KeyBindingHelper.registerKeyBinding(PORTAL_GUN_GRAB); KeyBindingHelper.registerKeyBinding(PORTAL_GUN_RESET); } @@ -110,10 +103,6 @@ public final class AntarchyKeyBindings { return Minecraft.getInstance().screen == null && PORTAL_GUN_ZOOM.consumeClick(); } - public static boolean consumePortalGunGrabPressed() { - return Minecraft.getInstance().screen == null && PORTAL_GUN_GRAB.consumeClick(); - } - public static boolean consumePortalGunResetPressed() { return Minecraft.getInstance().screen == null && PORTAL_GUN_RESET.consumeClick(); } diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/DorrieJumpClientHandler.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/DorrieJumpClientHandler.java index 37f9b3af..b60f94c1 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/DorrieJumpClientHandler.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/DorrieJumpClientHandler.java @@ -27,14 +27,12 @@ public final class DorrieJumpClientHandler { return; } - // Space bar → upward movement. boolean pressingJump = mc.options.keyJump.isDown(); if (pressingJump != wasPressingJump) { ClientPlayNetworking.send(new DorrieJumpInputPayload(pressingJump)); wasPressingJump = pressingJump; } - // Left ctrl → charge jump. boolean pressingCharge = AntarchyKeyBindings.isMountSpecialPressed(); if (pressingCharge != wasPressingCharge) { ClientPlayNetworking.send(new DorrieChargeJumpPayload(pressingCharge)); diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/PortalGunClientHandler.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/PortalGunClientHandler.java index 59be6aba..7b3ef0ca 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/PortalGunClientHandler.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/PortalGunClientHandler.java @@ -3,7 +3,6 @@ package com.craisinlord.antarchy.fabric.client; import com.craisinlord.antarchy.content.item.PortalGunItem; import com.craisinlord.antarchy.content.client.PortalGunZoomClientState; import com.craisinlord.antarchy.content.network.PortalGunPrimaryPayload; -import com.craisinlord.antarchy.content.network.PortalGunGrabPayload; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.minecraft.client.Minecraft; @@ -20,23 +19,19 @@ public final class PortalGunClientHandler { private static void tickMouse(Minecraft mc) { if (mc.player == null) { - com.craisinlord.antarchy.content.client.PortalGunGrabClientState.clear(); com.craisinlord.antarchy.content.client.PortalGunResetClientState.clear(); } boolean hasPortalGun = mc.player != null && (mc.player.getMainHandItem().getItem() instanceof PortalGunItem || mc.player.getOffhandItem().getItem() instanceof PortalGunItem); boolean gameplayInput = mc.screen == null; boolean held = hasPortalGun && gameplayInput; boolean zoomPressed = AntarchyKeyBindings.consumePortalGunZoomPressed(); - PortalGunZoomClientState.tick(mc, hasPortalGun, zoomPressed && gameplayInput); + PortalGunZoomClientState.tick(mc, held, zoomPressed && gameplayInput); boolean resetActive = com.craisinlord.antarchy.content.client.PortalGunResetClientState.tick( mc, held, AntarchyKeyBindings.isPortalGunResetDown(), ClientPlayNetworking::send ); - if (held && AntarchyKeyBindings.consumePortalGunGrabPressed()) { - ClientPlayNetworking.send(new PortalGunGrabPayload()); - } if (mc.player == null || mc.level == null || mc.screen != null) { lastAttackDown = false; return; diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/SeparateLargeItemModels.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/SeparateLargeItemModels.java index 14dc8a2a..b50944f5 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/SeparateLargeItemModels.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/SeparateLargeItemModels.java @@ -20,6 +20,8 @@ public final class SeparateLargeItemModels { entry(AntarchyFabricItems.GROWTH_RAY.get(), "grow_ray_gui"), entry(AntarchyFabricItems.KRAKENS_GRASP.get(), "krakens_grasp_gui"), entry(AntarchyFabricItems.PORTAL_GUN.get(), "portal_gun_gui"), + entry(AntarchyFabricItems.PORTAL_GUN_ATLAS.get(), "portal_gun_atlas_gui"), + entry(AntarchyFabricItems.PORTAL_GUN_P_BODY.get(), "portal_gun_p_body_gui"), entry(AntarchyFabricItems.ROYAL_ASSAILANT_BATTLEAXE.get(), "royal_assailant_battleaxe_gui"), entry(AntarchyFabricItems.ROYAL_ASSAILANT_STAFF.get(), "royal_assailant_staff_gui"), entry(AntarchyFabricItems.ROYAL_GUARDIAN_SWORD.get(), "royal_guardian_sword_gui"), diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/DuctTapeInputMixin.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/DuctTapeInputMixin.java deleted file mode 100644 index 5aa823ad..00000000 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/DuctTapeInputMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.craisinlord.antarchy.fabric.mixin.client; - -import com.craisinlord.antarchy.content.block.DuctTapeBlock; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.Input; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Input.class) -public abstract class DuctTapeInputMixin { - - @Inject(method = "tick", at = @At("RETURN")) - private void blockInputInDuctTape(boolean isSneaking, float slowFactor, CallbackInfo ci) { - Minecraft mc = Minecraft.getInstance(); - if (mc.player == null || mc.level == null) return; - if (!mc.player.isNoGravity() && !DuctTapeBlock.isTouchingTape(mc.level, mc.player)) return; - - Input self = (Input) (Object) this; - self.left = false; - self.right = false; - self.up = false; - self.down = false; - self.leftImpulse = 0.0F; - self.forwardImpulse = 0.0F; - self.jumping = false; - self.shiftKeyDown = false; - } -} diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/RenderTargetDepthStencilMixin.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/RenderTargetDepthStencilMixin.java new file mode 100644 index 00000000..a37f1034 --- /dev/null +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/RenderTargetDepthStencilMixin.java @@ -0,0 +1,28 @@ +package com.craisinlord.antarchy.fabric.mixin.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.pipeline.RenderTarget; +import java.nio.IntBuffer; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(RenderTarget.class) +public abstract class RenderTargetDepthStencilMixin { + @WrapOperation(method = "createBuffers", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texImage2D(IIIIIIIILjava/nio/IntBuffer;)V")) + private void antarchy$allocateDepthStencil(int target, int level, int internalFormat, int width, int height, int border, int format, int type, + IntBuffer pixels, Operation original) { + if (internalFormat == GL11.GL_DEPTH_COMPONENT) { + original.call(target, level, GL30.GL_DEPTH24_STENCIL8, width, height, border, GL30.GL_DEPTH_STENCIL, GL30.GL_UNSIGNED_INT_24_8, pixels); + return; + } + original.call(target, level, internalFormat, width, height, border, format, type, pixels); + } + + @WrapOperation(method = "createBuffers", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_glFramebufferTexture2D(IIIII)V")) + private void antarchy$attachDepthStencil(int target, int attachment, int textureTarget, int texture, int level, Operation original) { + original.call(target, attachment == GL30.GL_DEPTH_ATTACHMENT ? GL30.GL_DEPTH_STENCIL_ATTACHMENT : attachment, textureTarget, texture, level); + } +} diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricClientNetworking.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricClientNetworking.java index 53f1cba8..0466ff56 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricClientNetworking.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricClientNetworking.java @@ -45,8 +45,6 @@ public final class AntarchyFabricClientNetworking { com.craisinlord.antarchy.content.client.PortalGunIndicatorClientState.setRequestSender(ClientPlayNetworking::send); ClientPlayNetworking.registerGlobalReceiver(PortalGunIndicatorPayload.TYPE, (payload, context) -> context.client().execute(() -> com.craisinlord.antarchy.content.client.PortalGunIndicatorClientState.update(payload))); - ClientPlayNetworking.registerGlobalReceiver(PortalGunGrabStatePayload.TYPE, (payload, context) -> - context.client().execute(() -> com.craisinlord.antarchy.content.client.PortalGunGrabClientState.update(payload.active()))); ClientPlayNetworking.registerGlobalReceiver(GravityStatePayload.TYPE, (payload, context) -> context.client().execute(() -> AntarchyFabricNetworking.handleGravityState(context.player(), payload))); ClientPlayNetworking.registerGlobalReceiver(BloodglassStatePayload.TYPE, (payload, context) -> diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricNetworking.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricNetworking.java index 6291f2c4..e6d38d58 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricNetworking.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/network/AntarchyFabricNetworking.java @@ -50,7 +50,6 @@ public final class AntarchyFabricNetworking { registerServerReceivers(); com.craisinlord.antarchy.content.network.AntarchyGameNetworkHandler.setResultSender(ServerPlayNetworking::send); com.craisinlord.antarchy.content.portalgun.PortalGunIndicatorSync.setSender(ServerPlayNetworking::send); - com.craisinlord.antarchy.content.portalgun.PortalGunGrabManager.setStateSender(ServerPlayNetworking::send); } public static void bootstrapMultipartCommon() { @@ -76,7 +75,6 @@ public final class AntarchyFabricNetworking { private static void registerPayloadTypes() { PayloadTypeRegistry.playS2C().register(AntarchyGameResultPayload.TYPE, AntarchyGameResultPayload.STREAM_CODEC); PayloadTypeRegistry.playS2C().register(PortalGunIndicatorPayload.TYPE, PortalGunIndicatorPayload.STREAM_CODEC); - PayloadTypeRegistry.playS2C().register(PortalGunGrabStatePayload.TYPE, PortalGunGrabStatePayload.STREAM_CODEC); PayloadTypeRegistry.playS2C().register(GravityStatePayload.TYPE, GravityStatePayload.STREAM_CODEC); PayloadTypeRegistry.playS2C().register(BloodglassStatePayload.TYPE, BloodglassStatePayload.STREAM_CODEC); PayloadTypeRegistry.playS2C().register(TigerEyeCamouflageStatePayload.TYPE, TigerEyeCamouflageStatePayload.STREAM_CODEC); @@ -92,8 +90,8 @@ public final class AntarchyFabricNetworking { PayloadTypeRegistry.playC2S().register(GravityGunPrimaryPayload.TYPE, GravityGunPrimaryPayload.STREAM_CODEC); PayloadTypeRegistry.playC2S().register(PortalGunPrimaryPayload.TYPE, PortalGunPrimaryPayload.STREAM_CODEC); + PayloadTypeRegistry.playC2S().register(com.craisinlord.antarchy.content.network.PortalGunTransitPayload.TYPE, com.craisinlord.antarchy.content.network.PortalGunTransitPayload.STREAM_CODEC); PayloadTypeRegistry.playC2S().register(PortalGunIndicatorRequestPayload.TYPE, PortalGunIndicatorRequestPayload.STREAM_CODEC); - PayloadTypeRegistry.playC2S().register(PortalGunGrabPayload.TYPE, PortalGunGrabPayload.STREAM_CODEC); PayloadTypeRegistry.playC2S().register(PortalGunResetPayload.TYPE, PortalGunResetPayload.STREAM_CODEC); PayloadTypeRegistry.playC2S().register(EyeOfStormPrimaryPayload.TYPE, EyeOfStormPrimaryPayload.STREAM_CODEC); PayloadTypeRegistry.playC2S().register(OpenGiantFryingPanPayload.TYPE, OpenGiantFryingPanPayload.STREAM_CODEC); @@ -128,10 +126,15 @@ public final class AntarchyFabricNetworking { context.server().execute(() -> handleGravityGunPrimary(context.player(), payload))); ServerPlayNetworking.registerGlobalReceiver(PortalGunPrimaryPayload.TYPE, (payload, context) -> context.server().execute(() -> handlePortalGunPrimary(context.player(), payload))); + ServerPlayNetworking.registerGlobalReceiver(com.craisinlord.antarchy.content.network.PortalGunTransitPayload.TYPE, (payload, context) -> { + if (context.server().isSameThread()) { + com.craisinlord.antarchy.content.portalgun.PortalGunTransitHandler.handle(context.player(), payload); + } else { + context.server().execute(() -> com.craisinlord.antarchy.content.portalgun.PortalGunTransitHandler.handle(context.player(), payload)); + } + }); ServerPlayNetworking.registerGlobalReceiver(PortalGunIndicatorRequestPayload.TYPE, (payload, context) -> context.server().execute(() -> com.craisinlord.antarchy.content.portalgun.PortalGunIndicatorSync.handleRequest(context.player(), payload))); - ServerPlayNetworking.registerGlobalReceiver(PortalGunGrabPayload.TYPE, (payload, context) -> - context.server().execute(() -> com.craisinlord.antarchy.content.portalgun.PortalGunGrabManager.toggle(context.player()))); ServerPlayNetworking.registerGlobalReceiver(PortalGunResetPayload.TYPE, (payload, context) -> context.server().execute(() -> com.craisinlord.antarchy.content.portalgun.PortalGunResetManager.handleInput(context.player(), payload.action()))); ServerPlayNetworking.registerGlobalReceiver(EyeOfStormPrimaryPayload.TYPE, (payload, context) -> diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java index f960daba..0ff44e48 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java @@ -1561,7 +1561,28 @@ public final class AntarchyFabricItems { AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE, AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, - AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE + AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, + com.craisinlord.antarchy.content.portalgun.PortalGunVariant.DEFAULT + )); + public static final DeferredItem PORTAL_GUN_ATLAS = ITEMS.register("portal_gun_atlas", + () -> new PortalGunItem( + new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), + AntarchyFabricEntities.PORTAL_GUN_PORTAL, + AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE, + AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, + AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, + AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, + com.craisinlord.antarchy.content.portalgun.PortalGunVariant.ATLAS + )); + public static final DeferredItem PORTAL_GUN_P_BODY = ITEMS.register("portal_gun_p_body", + () -> new PortalGunItem( + new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), + AntarchyFabricEntities.PORTAL_GUN_PORTAL, + AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE, + AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, + AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, + AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, + com.craisinlord.antarchy.content.portalgun.PortalGunVariant.P_BODY )); public static final DeferredItem EYE_OF_THE_STORM = ITEMS.register("eye_of_the_storm", diff --git a/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json b/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json index 9f839d94..adad33c4 100644 --- a/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json +++ b/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json @@ -27,12 +27,12 @@ "infinity.AmendmentRareOresMixin" ], "client": [ + "client.RenderTargetDepthStencilMixin", "client.SeparateLargeItemModelsMixin", "client.SeparateLargeItemGuiLightingMixin", "client.CameraShakeMixin", "client.BrutalflyElytraExperienceBarMixin", "client.BloodglassChatOrderMixin", - "client.DuctTapeInputMixin", "client.LiquidFogMixin", "client.GravityGunMouseScrollMixin", "client.KeybindingConflictFixMixin", diff --git a/fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json b/fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json new file mode 100644 index 00000000..a3b81466 --- /dev/null +++ b/fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json @@ -0,0 +1,3 @@ +{ + "parent": "antarchy:item/portal_gun_held_geo" +} diff --git a/fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json b/fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json new file mode 100644 index 00000000..a3b81466 --- /dev/null +++ b/fabric-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json @@ -0,0 +1,3 @@ +{ + "parent": "antarchy:item/portal_gun_held_geo" +} diff --git a/logs/latest.log b/logs/latest.log new file mode 100644 index 00000000..e69de29b diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java index 37e8c373..0236328d 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java @@ -671,8 +671,9 @@ public final class AntarchyConfigModuleNeoforge { AntarchySettings.setPortalGunSeeThroughPortals(AntarchyMiscConfig.portalGunSeeThroughPortals()); AntarchySettings.setPortalGunFancyPortals(AntarchyMiscConfig.portalGunFancyPortals()); AntarchySettings.setPortalGunMaxShootDistance(AntarchyMiscConfig.portalGunMaxShootDistance()); - AntarchySettings.setPortalGunEntityGrabWeightBase(AntarchyMiscConfig.portalGunEntityGrabWeightBase()); - AntarchySettings.setPortalGunIndicatorSize(AntarchyMiscConfig.portalGunIndicatorSize()); + AntarchySettings.setPortalGunMinFloorExitSpeed(AntarchyMiscConfig.portalGunMinFloorExitSpeed()); + AntarchySettings.setPortalGunMaxLiveViews(AntarchyMiscConfig.portalGunMaxLiveViews()); + AntarchySettings.setPortalGunMaxExitSpeed(AntarchyMiscConfig.portalGunMaxExitSpeed()); // Misc diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java index 8e9b2e29..f54e5950 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java @@ -39,8 +39,9 @@ public final class AntarchyMiscConfig { private static final ModConfigSpec.BooleanValue PORTAL_GUN_SEE_THROUGH_PORTALS; private static final ModConfigSpec.BooleanValue PORTAL_GUN_FANCY_PORTALS; private static final ModConfigSpec.IntValue PORTAL_GUN_MAX_SHOOT_DISTANCE; - private static final ModConfigSpec.IntValue PORTAL_GUN_ENTITY_GRAB_WEIGHT_BASE; - private static final ModConfigSpec.IntValue PORTAL_GUN_INDICATOR_SIZE; + private static final ModConfigSpec.DoubleValue PORTAL_GUN_MIN_FLOOR_EXIT_SPEED; + private static final ModConfigSpec.IntValue PORTAL_GUN_MAX_LIVE_VIEWS; + private static final ModConfigSpec.DoubleValue PORTAL_GUN_MAX_EXIT_SPEED; // Diamond Minecart private static final ModConfigSpec.BooleanValue DIAMOND_MINECART_ENABLED; @@ -146,8 +147,9 @@ public final class AntarchyMiscConfig { PORTAL_GUN_SEE_THROUGH_PORTALS = b.define("seeThroughPortals", true); PORTAL_GUN_FANCY_PORTALS = b.define("fancyPortals", true); PORTAL_GUN_MAX_SHOOT_DISTANCE = b.defineInRange("maxShootDistance", 10000, 1, Integer.MAX_VALUE); - PORTAL_GUN_ENTITY_GRAB_WEIGHT_BASE = b.defineInRange("entityGrabWeightBase", 100, 0, 1000); - PORTAL_GUN_INDICATOR_SIZE = b.defineInRange("indicatorSize", 30, 0, 100); + PORTAL_GUN_MAX_LIVE_VIEWS = b.comment("How many portals can show a live see-through view at once. Each one re-renders the world, so higher values cost frame rate. 0 shows only the animated surface.").defineInRange("maxLiveViews", 8, 0, 32); + PORTAL_GUN_MIN_FLOOR_EXIT_SPEED = b.comment("Minimum speed in blocks/tick when leaving an upward-facing portal, so the traveller clears it. 0 disables.").defineInRange("minFloorExitSpeed", 0.6D, 0.0D, 4.0D); + PORTAL_GUN_MAX_EXIT_SPEED = b.comment("Maximum speed in blocks/tick when leaving a portal. 0 keeps momentum uncapped.").defineInRange("maxExitSpeed", 0.0D, 0.0D, 100.0D); b.pop(); @@ -224,8 +226,9 @@ public final class AntarchyMiscConfig { public static boolean portalGunSeeThroughPortals() { return PORTAL_GUN_SEE_THROUGH_PORTALS.get(); } public static boolean portalGunFancyPortals() { return PORTAL_GUN_FANCY_PORTALS.get(); } public static int portalGunMaxShootDistance() { return PORTAL_GUN_MAX_SHOOT_DISTANCE.get(); } - public static int portalGunEntityGrabWeightBase() { return PORTAL_GUN_ENTITY_GRAB_WEIGHT_BASE.get(); } - public static int portalGunIndicatorSize() { return PORTAL_GUN_INDICATOR_SIZE.get(); } + public static double portalGunMinFloorExitSpeed() { return PORTAL_GUN_MIN_FLOOR_EXIT_SPEED.get(); } + public static int portalGunMaxLiveViews() { return PORTAL_GUN_MAX_LIVE_VIEWS.get(); } + public static double portalGunMaxExitSpeed() { return PORTAL_GUN_MAX_EXIT_SPEED.get(); } static boolean diamondMinecartEnabled() { return DIAMOND_MINECART_ENABLED.get(); } static boolean diamondMinecartPlacesRails() { return DIAMOND_MINECART_PLACES_RAILS.get(); } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyKeyBindings.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyKeyBindings.java index 86a23f83..1abc6bc4 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyKeyBindings.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyKeyBindings.java @@ -65,13 +65,6 @@ public final class AntarchyKeyBindings { InputConstants.MOUSE_BUTTON_MIDDLE, CATEGORY ); - public static final KeyMapping PORTAL_GUN_GRAB = new KeyMapping( - "key.antarchy.portal_gun_grab", - KeyConflictContext.IN_GAME, - InputConstants.Type.KEYSYM, - InputConstants.KEY_G, - CATEGORY - ); public static final KeyMapping PORTAL_GUN_RESET = new KeyMapping( "key.antarchy.portal_gun_reset", KeyConflictContext.IN_GAME, @@ -91,7 +84,6 @@ public final class AntarchyKeyBindings { event.register(ROYAL_INVERSION_TOGGLE); event.register(ROYAL_BOUNDARY); event.register(PORTAL_GUN_ZOOM); - event.register(PORTAL_GUN_GRAB); event.register(PORTAL_GUN_RESET); } @@ -119,10 +111,6 @@ public final class AntarchyKeyBindings { return PORTAL_GUN_ZOOM.consumeClick(); } - public static boolean consumePortalGunGrabPressed() { - return PORTAL_GUN_GRAB.consumeClick(); - } - public static boolean consumePortalGunResetPressed() { return PORTAL_GUN_RESET.consumeClick(); } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java index 637588a5..e57c4806 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java @@ -384,6 +384,11 @@ public final class AntarchyNeoForgeClient { @SubscribeEvent public static void registerGuiLayers(RegisterGuiLayersEvent event) { + event.registerAbove( + VanillaGuiLayers.CROSSHAIR, + ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "portal_gun_crosshair"), + (guiGraphics, partialTick) -> com.craisinlord.antarchy.content.client.PortalGunCrosshairRenderer.render(guiGraphics) + ); event.registerAboveAll( ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dread_darkness"), (guiGraphics, partialTick) -> DreadHudRenderer.render(guiGraphics) @@ -626,6 +631,8 @@ public final class AntarchyNeoForgeClient { registerGeoItemExtensionSizeRay(event, AntarchyNeoforgeItems.GROWTH_RAY.get()); registerGeoItemExtension(event, AntarchyNeoforgeItems.GRAVITY_GUN.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); registerGeoItemExtension(event, AntarchyNeoforgeItems.PORTAL_GUN.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); + registerGeoItemExtension(event, AntarchyNeoforgeItems.PORTAL_GUN_ATLAS.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); + registerGeoItemExtension(event, AntarchyNeoforgeItems.PORTAL_GUN_P_BODY.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); registerGeoItemExtension(event, AntarchyNeoforgeItems.SQUIDZOOKA.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); registerGeoItemExtension(event, AntarchyNeoforgeItems.RPO_LAUNCHER.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); registerGeoItemExtension(event, AntarchyNeoforgeItems.WATER_CANNON.get(), HumanoidModel.ArmPose.CROSSBOW_HOLD); diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/DuctTapeClientHandler.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/DuctTapeClientHandler.java deleted file mode 100644 index 950c7ed9..00000000 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/DuctTapeClientHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.craisinlord.antarchy.neoforge.client; - -import com.craisinlord.antarchy.Antarchy; -import com.craisinlord.antarchy.content.block.DuctTapeBlock; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.client.event.MovementInputUpdateEvent; - -@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT) -public final class DuctTapeClientHandler { - private DuctTapeClientHandler() { - } - - @SubscribeEvent - public static void onMovementInputUpdate(MovementInputUpdateEvent event) { - if (!(event.getEntity() instanceof LocalPlayer player)) { - return; - } - - Minecraft mc = Minecraft.getInstance(); - if (mc.level == null || (!player.isNoGravity() && !DuctTapeBlock.isTouchingTape(mc.level, player))) { - return; - } - - var input = event.getInput(); - input.left = false; - input.right = false; - input.up = false; - input.down = false; - input.leftImpulse = 0.0F; - input.forwardImpulse = 0.0F; - input.jumping = false; - input.shiftKeyDown = false; - } -} diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunClientHandler.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunClientHandler.java index 3bc0efee..28c27a4f 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunClientHandler.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunClientHandler.java @@ -4,7 +4,6 @@ import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.content.item.PortalGunItem; import com.craisinlord.antarchy.content.client.PortalGunZoomClientState; import com.craisinlord.antarchy.content.network.PortalGunPrimaryPayload; -import com.craisinlord.antarchy.content.network.PortalGunGrabPayload; import net.minecraft.client.Minecraft; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; @@ -23,7 +22,6 @@ public final class PortalGunClientHandler { public static void onClientTick(ClientTickEvent.Post event) { Minecraft mc = Minecraft.getInstance(); if (mc.player == null) { - com.craisinlord.antarchy.content.client.PortalGunGrabClientState.clear(); com.craisinlord.antarchy.content.client.PortalGunResetClientState.clear(); } com.craisinlord.antarchy.content.client.PortalGunIndicatorClientState.setRequestSender(net.neoforged.neoforge.network.PacketDistributor::sendToServer); @@ -38,9 +36,6 @@ public final class PortalGunClientHandler { AntarchyKeyBindings.isPortalGunResetDown(), net.neoforged.neoforge.network.PacketDistributor::sendToServer ); - if (held && AntarchyKeyBindings.consumePortalGunGrabPressed()) { - PacketDistributor.sendToServer(new PortalGunGrabPayload()); - } if (mc.player == null || mc.level == null || mc.screen != null) { lastAttackDown = false; return; diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunPortalViewRenderHandler.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunPortalViewRenderHandler.java index 79a90c1f..6403e189 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunPortalViewRenderHandler.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/PortalGunPortalViewRenderHandler.java @@ -14,9 +14,6 @@ public final class PortalGunPortalViewRenderHandler { @SubscribeEvent public static void onRenderLevelStage(RenderLevelStageEvent event) { - if (!PortalGunPortalViewRenderer.isEnabled()) { - return; - } if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_LEVEL) { return; } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/WaspSoundHandler.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/WaspSoundHandler.java index fef0c034..7f31bb56 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/WaspSoundHandler.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/WaspSoundHandler.java @@ -29,7 +29,6 @@ public final class WaspSoundHandler { @SubscribeEvent public static void onClientTick(ClientTickEvent.Post event) { - // Ambient buzzing now comes from the wasp entity itself. } private static void refreshNearbyWasps(Minecraft mc) { diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/AntarchyGravityNetworking.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/AntarchyGravityNetworking.java index 1b165d81..64e80ce6 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/AntarchyGravityNetworking.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/AntarchyGravityNetworking.java @@ -31,7 +31,6 @@ public final class AntarchyGravityNetworking { public static void register(PayloadRegistrar registrar) { com.craisinlord.antarchy.content.portalgun.PortalGunIndicatorSync.setSender(PacketDistributor::sendToPlayer); - com.craisinlord.antarchy.content.portalgun.PortalGunGrabManager.setStateSender(PacketDistributor::sendToPlayer); registrar.playToClient( com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload.TYPE, com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload.STREAM_CODEC, @@ -40,10 +39,6 @@ public final class AntarchyGravityNetworking { com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload.TYPE, com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload.STREAM_CODEC, AntarchyGravityNetworking::handlePortalGunIndicatorRequest - ).playToClient( - com.craisinlord.antarchy.content.network.PortalGunGrabStatePayload.TYPE, - com.craisinlord.antarchy.content.network.PortalGunGrabStatePayload.STREAM_CODEC, - (payload, context) -> context.enqueueWork(() -> com.craisinlord.antarchy.content.client.PortalGunGrabClientState.update(payload.active())) ).playToClient( GravityStatePayload.TYPE, GravityStatePayload.STREAM_CODEC, @@ -61,9 +56,19 @@ public final class AntarchyGravityNetworking { PortalGunPrimaryPayload.STREAM_CODEC, AntarchyGravityNetworking::handlePortalGunPrimary ).playToServer( - com.craisinlord.antarchy.content.network.PortalGunGrabPayload.TYPE, - com.craisinlord.antarchy.content.network.PortalGunGrabPayload.STREAM_CODEC, - AntarchyGravityNetworking::handlePortalGunGrab + com.craisinlord.antarchy.content.network.PortalGunTransitPayload.TYPE, + com.craisinlord.antarchy.content.network.PortalGunTransitPayload.STREAM_CODEC, + (payload, context) -> { + if (context.player() instanceof ServerPlayer serverPlayer && serverPlayer.getServer() != null && serverPlayer.getServer().isSameThread()) { + com.craisinlord.antarchy.content.portalgun.PortalGunTransitHandler.handle(serverPlayer, payload); + return; + } + context.enqueueWork(() -> { + if (context.player() instanceof ServerPlayer serverPlayer) { + com.craisinlord.antarchy.content.portalgun.PortalGunTransitHandler.handle(serverPlayer, payload); + } + }); + } ).playToServer( com.craisinlord.antarchy.content.network.PortalGunResetPayload.TYPE, com.craisinlord.antarchy.content.network.PortalGunResetPayload.STREAM_CODEC, @@ -239,13 +244,6 @@ public final class AntarchyGravityNetworking { }); } - private static void handlePortalGunGrab(com.craisinlord.antarchy.content.network.PortalGunGrabPayload payload, IPayloadContext context) { - context.enqueueWork(() -> { - if (context.player() instanceof ServerPlayer serverPlayer) { - com.craisinlord.antarchy.content.portalgun.PortalGunGrabManager.toggle(serverPlayer); - } - }); - } private static void handlePortalGunIndicatorRequest(com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload payload, IPayloadContext context) { context.enqueueWork(() -> { diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java index 2fdcba3f..1a839e04 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java @@ -5,7 +5,6 @@ import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.recipe.CustomBrewingRecipes; -import com.craisinlord.antarchy.content.block.DuctTapeBlock; import com.craisinlord.antarchy.content.dispenser.RpoLauncherDispenseBehavior; import com.craisinlord.antarchy.content.dispenser.SizeRayDispenseBehavior; import com.craisinlord.antarchy.content.dispenser.BugSprayDispenseBehavior; @@ -152,7 +151,6 @@ public final class AntarchyNeoForgeEvents { NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::tickThoraxisUnderside); modEventBus.addListener(AntarchyNeoForgeEvents::modifyEntityAttributes); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::tickOverheadInversion); - NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::tickDuctTapeStickiness); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleDreadDeath); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleFallenKingCrownKill); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleDreadBedSleep); @@ -248,6 +246,7 @@ public final class AntarchyNeoForgeEvents { for (ServerLevel level : event.getServer().getAllLevels()) { CavarynHordeManager.tick(level); com.craisinlord.antarchy.content.horde.CavarynCreatureSpawner.tick(level); + com.craisinlord.antarchy.content.worldgen.elythia.KingsTreeGridFeature.tickPendingSpawns(level); } } @@ -448,12 +447,6 @@ public final class AntarchyNeoForgeEvents { event.setResult(MobSpawnEvent.PositionCheck.Result.FAIL); } - static void tickDuctTapeStickiness(EntityTickEvent.Post event) { - if (DuctTapeBlock.shouldTickStuckEntity(event.getEntity())) { - DuctTapeBlock.tickStuckEntity(event.getEntity()); - } - } - static void handleDreadDeath(LivingDeathEvent event) { LivingEntity entity = event.getEntity(); if (!entity.hasEffect(AntarchyNeoforgeMisc.DREAD)) { diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java index 4fb518b1..707f6417 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java @@ -1039,7 +1039,28 @@ public final class AntarchyNeoforgeItems { AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE, AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, - AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE + AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, + com.craisinlord.antarchy.content.portalgun.PortalGunVariant.DEFAULT + )); + public static final DeferredItem PORTAL_GUN_ATLAS = ITEMS.register("portal_gun_atlas", + () -> new PortalGunItem( + new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), + AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, + AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE, + AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, + AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, + AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, + com.craisinlord.antarchy.content.portalgun.PortalGunVariant.ATLAS + )); + public static final DeferredItem PORTAL_GUN_P_BODY = ITEMS.register("portal_gun_p_body", + () -> new PortalGunItem( + new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), + AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, + AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE, + AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, + AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, + AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, + com.craisinlord.antarchy.content.portalgun.PortalGunVariant.P_BODY )); public static final DeferredItem EYE_OF_THE_STORM = ITEMS.register("eye_of_the_storm", () -> new EyeOfTheStormItem(new Item.Properties().stacksTo(1).durability(384).rarity(Rarity.EPIC))); diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/PortalGunGrabEvents.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/PortalGunServerEvents.java similarity index 55% rename from neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/PortalGunGrabEvents.java rename to neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/PortalGunServerEvents.java index c9cd49f4..8e9fe421 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/PortalGunGrabEvents.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/PortalGunServerEvents.java @@ -1,25 +1,17 @@ package com.craisinlord.antarchy.neoforge.registry; import com.craisinlord.antarchy.Antarchy; -import com.craisinlord.antarchy.content.portalgun.PortalGunGrabManager; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.event.server.ServerStoppingEvent; -import net.neoforged.neoforge.event.tick.ServerTickEvent; @EventBusSubscriber(modid = Antarchy.MODID) -public final class PortalGunGrabEvents { - private PortalGunGrabEvents() { - } - - @SubscribeEvent - public static void onServerTick(ServerTickEvent.Post event) { - PortalGunGrabManager.tick(event.getServer()); +public final class PortalGunServerEvents { + private PortalGunServerEvents() { } @SubscribeEvent public static void onServerStopping(ServerStoppingEvent event) { - PortalGunGrabManager.clear(event.getServer()); com.craisinlord.antarchy.content.portalgun.PortalGunResetManager.clear(event.getServer()); } } diff --git a/neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json b/neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json new file mode 100644 index 00000000..43e29acb --- /dev/null +++ b/neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_atlas.json @@ -0,0 +1,18 @@ +{ + "loader": "neoforge:separate_transforms", + "gui_light": "front", + "base": { + "parent": "antarchy:item/portal_gun_held_geo" + }, + "perspectives": { + "gui": { + "parent": "antarchy:item/portal_gun_atlas_gui" + }, + "ground": { + "parent": "antarchy:item/portal_gun_atlas_gui" + }, + "fixed": { + "parent": "antarchy:item/portal_gun_atlas_gui" + } + } +} diff --git a/neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json b/neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json new file mode 100644 index 00000000..cce6378f --- /dev/null +++ b/neoforge-1.21.1/src/main/resources/assets/antarchy/models/item/portal_gun_p_body.json @@ -0,0 +1,18 @@ +{ + "loader": "neoforge:separate_transforms", + "gui_light": "front", + "base": { + "parent": "antarchy:item/portal_gun_held_geo" + }, + "perspectives": { + "gui": { + "parent": "antarchy:item/portal_gun_p_body_gui" + }, + "ground": { + "parent": "antarchy:item/portal_gun_p_body_gui" + }, + "fixed": { + "parent": "antarchy:item/portal_gun_p_body_gui" + } + } +}