diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index fb72a347..d4ec3c7b 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -4,6 +4,10 @@ import java.util.Optional; import java.util.UUID; import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.joml.Vector4f; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; @@ -22,6 +26,7 @@ import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.shape.*; import net.minecraft.block.Block; +import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.nbt.NbtCompound; @@ -31,6 +36,7 @@ import net.minecraft.registry.RegistryWrapper.WrapperLookup; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction.Axis; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.WorldEvents; @@ -139,14 +145,16 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell. }); } } else { + targetPortalPitch.set(targetEntry.getPitch()); + targetPortalYaw.set(targetEntry.getYaw()); + tickActive(source, targetEntry); } } - } - var entry = Ether.get(source.asWorld()).getOrCreate(this, source); - entry.setPitch(pitch.get()); - entry.setYaw(yaw.get()); + ownEntry.setPitch(getPitch()); + ownEntry.setYaw(getYaw()); + } } return !isDead(); @@ -154,6 +162,11 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell. private void tickActive(Caster source, Ether.Entry destination) { destination.entity.getTarget().ifPresent(target -> { + Quaternionf rotationChange = getOrientationChange(); + var matrix = getPositionMatrix(source, source.asEntity().getPos(), rotationChange, new Matrix4f()); + + float yawDifference = getYawDifference(); + source.findAllEntitiesInRange(1).forEach(entity -> { if (!entity.hasPortalCooldown()) { @@ -162,13 +175,16 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell. return; } - Vec3d offset = entity.getPos().subtract(source.asEntity().getPos()) - .add(new Vec3d(0, 0, -0.7F).rotateY(-getTargetYaw() * MathHelper.RADIANS_PER_DEGREE)); - float yawDifference = getYawDifference(); - Vec3d dest = target.pos().add(offset.rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)).add(0, 0.1, 0); + var dest4f = matrix.transform(new Vector4f(entity.getPos().toVector3f(), 1)); + Vec3d dest = new Vec3d(dest4f.x, dest4f.y - 0.5, dest4f.z).add(new Vec3d(0, 0, -0.7F).rotateY(-getTargetYaw() * MathHelper.RADIANS_PER_DEGREE)); - if (entity.getWorld().isTopSolid(BlockPos.ofFloored(dest).up(), entity)) { - dest = dest.add(0, 1, 0); + for (int i = 0; i < 2; i++) { + BlockPos destBlock = BlockPos.ofFloored(dest); + BlockState state = entity.getWorld().getBlockState(destBlock); + if (entity.getWorld().isTopSolid(destBlock, entity)) { + double maxY = state.getCollisionShape(entity.getWorld(), destBlock).getMax(Axis.Y); + dest = new Vec3d(dest.x, destBlock.getY() + maxY, dest.z); + } } entity.resetPortalCooldown(); @@ -193,6 +209,24 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell. }); } + public Matrix4f getPositionMatrix(Caster source, Vec3d pos, Quaternionf orientationChange, Matrix4f matrix) { + getDestinationReference().getTarget().ifPresent(destEntity -> { + Vector3f destPos = destEntity.pos().toVector3f(); + Vector3f sourcePos = pos.toVector3f(); + + matrix.rotateAround(orientationChange.conjugate(), destPos.x, destPos.y, destPos.z); + matrix.translate(destPos.sub(sourcePos)); + }); + return matrix; + } + + public Quaternionf getOrientationChange() { + return new Quaternionf().rotateTo( + Vec3d.fromPolar(getPitch(), getYaw()).toVector3f(), + Vec3d.fromPolar(getTargetPitch(), getTargetYaw()).toVector3f() + ); + } + @Override public void setOrientation(Caster caster, float pitch, float yaw) { this.pitch.set(90 - pitch); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java index 91376625..23a7c9ae 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/entity/CastSpellEntityRenderer.java @@ -9,6 +9,8 @@ import com.minelittlepony.unicopia.client.render.spell.SpellEffectsRenderDispatc import com.minelittlepony.unicopia.client.render.spell.SpellRenderer; import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; @@ -16,6 +18,7 @@ import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.PlayerScreenHandler; +import net.minecraft.util.Colors; import net.minecraft.util.Identifier; import net.minecraft.util.math.ColorHelper.Argb; import net.minecraft.util.math.RotationAxis; @@ -41,6 +44,10 @@ public class CastSpellEntityRenderer extends EntityRenderer { @Override public void render(CastSpellEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.cameraEntity instanceof CastSpellEntity) { + return; + } matrices.push(); matrices.translate(0, 0.001, 0); final float height = entity.getHeight(); @@ -52,7 +59,6 @@ public class CastSpellEntityRenderer extends EntityRenderer { float animationProgress = getAnimationProgress(entity, tickDelta); renderAmbientEffects(matrices, vertices, entity, entity.getSpellSlot().get().orElse(null), light, animationProgress, tickDelta); SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertices, light, entity, entity.getScale(tickDelta), 0, tickDelta, animationProgress, yaw, pitch); - matrices.pop(); } @@ -69,7 +75,7 @@ public class CastSpellEntityRenderer extends EntityRenderer { float angle = (animationProgress / 9F) % 360; - int color = spell == null ? 0 : spell.getTypeAndTraits().type().getColor(); + int color = spell == null ? Colors.WHITE : spell.getTypeAndTraits().type().getColor(); @Nullable SpellRenderer renderer = spell == null ? null : SpellEffectsRenderDispatcher.INSTANCE.getRenderer(spell); @@ -87,7 +93,7 @@ public class CastSpellEntityRenderer extends EntityRenderer { matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angle * ringSpeed)); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angle * ringSpeed * dim)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(angle * ringSpeed * dim)); - PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, Argb.withAlpha(color, (int)(255 * (scale / ((float)(dim * 3) + 1))))); + PlaneModel.INSTANCE.render(matrices, buffer, light, OverlayTexture.DEFAULT_UV, 1, Argb.withAlpha(color, (int)(255 * (scale / ((float)(dim * 3) + 1))))); matrices.pop(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java index 42c515bc..53b17d62 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalFrameBuffer.java @@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.joml.Quaternionf; +import org.joml.Vector4f; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -42,6 +43,7 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.util.Colors; +import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -92,14 +94,10 @@ class PortalFrameBuffer implements AutoCloseable { if (!(closed || framebuffer == null)) { Tessellator tessellator = RenderSystem.renderThreadTesselator(); - float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth; - float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight; RenderSystem.setShader(UShaders.RENDER_TYPE_PORTAL_SURFACE); RenderSystem._setShaderTexture(0, framebuffer.getColorAttachment()); BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); - SphereModel.DISK.scaleUV(uScale, vScale); - RenderSystem.setTextureMatrix(SphereModel.DISK.getTextureMatrix()); SphereModel.DISK.render(matrices, buffer, 1, 2F, Colors.WHITE); BufferRenderer.drawWithGlobalProgram(buffer.end()); @@ -115,6 +113,7 @@ class PortalFrameBuffer implements AutoCloseable { } public void build(PortalSpell spell, Caster caster, EntityReference.EntityValues target) { + closed = false; long refreshRate = Unicopia.getConfig().fancyPortalRefreshRate.get(); if (refreshRate > 0 && framebuffer != null && System.currentTimeMillis() % refreshRate != 0) { @@ -146,6 +145,8 @@ class PortalFrameBuffer implements AutoCloseable { } recursionCount++; + Entity globalCameraEntity = client.cameraEntity; + try { if (closed || client.interactionManager == null) { close(); @@ -155,17 +156,21 @@ class PortalFrameBuffer implements AutoCloseable { Camera camera = client.gameRenderer.getCamera(); Entity cameraEntity = UEntities.CAST_SPELL.create(caster.asWorld()); - Vec3d offset = new Vec3d(0, 1, -0.1F).rotateY(-spell.getTargetYaw() * MathHelper.RADIANS_PER_DEGREE); - float yaw = spell.getTargetYaw() + camera.getYaw() - spell.getYaw(); - float pitch = spell.getTargetPitch();//MathHelper.clamp(spell.getTargetPitch() + (camera.getPitch() - spell.getPitch()) * 0.65F, -90, 90) + 90; + Vec3d pos = target.pos(); - cameraEntity.setPosition(target.pos().add(offset)); - cameraEntity.setPitch(pitch % 180); - cameraEntity.setYaw((yaw + 180) % 360); + Quaternionf orientationChange = spell.getOrientationChange(); + Matrix4f positionMatrix = spell.getPositionMatrix(caster, target.pos(), orientationChange, new Matrix4f()); + Vector4f transformedPos = positionMatrix.transform(new Vector4f(pos.toVector3f(), 1)); + cameraEntity.setPosition(transformedPos.x, transformedPos.y + 0.5F, transformedPos.z); + cameraEntity.setPitch(MathHelper.clamp(camera.getPitch() - spell.getTargetPitch() + spell.getPitch(), -90, 90)); + cameraEntity.setYaw(MathHelper.wrapDegrees(camera.getYaw() + spell.getYawDifference())); + + client.cameraEntity = cameraEntity; drawWorld(cameraEntity, 400, 400); } finally { + client.cameraEntity = globalCameraEntity; recursionCount--; } } @@ -198,44 +203,38 @@ class PortalFrameBuffer implements AutoCloseable { BackgroundRenderer.clearFog(); RenderSystem.enableCull(); - if (renderer == null) { - renderer = new WorldRenderer(client, client.getEntityRenderDispatcher(), client.getBlockEntityRenderDispatcher(), client.getBufferBuilders()); - } if (cameraEntity.getWorld() != world) { world = (ClientWorld)cameraEntity.getWorld(); - renderer.setWorld(world); } - //((MixinMinecraftClient)client).setWorldRenderer(renderer); - var tickCounter = client.getRenderTickCounter(); + if (renderer == null) { + renderer = new WorldRenderer(client, client.getEntityRenderDispatcher(), client.getBlockEntityRenderDispatcher(), client.getBufferBuilders()); + renderer.setWorld(world); + renderer.scheduleBlockRenders( + ChunkSectionPos.getSectionCoord((int)cameraEntity.getX()), + ChunkSectionPos.getSectionCoord((int)cameraEntity.getY()), + ChunkSectionPos.getSectionCoord((int)cameraEntity.getZ()) + ); + } camera.update(world, cameraEntity, false, false, 1); - double fov = 110; + double fov = 120; Matrix4f projectionMatrix = client.gameRenderer.getBasicProjectionMatrix(fov); Matrix4f cameraTransform = new Matrix4f().rotation(camera.getRotation().conjugate(new Quaternionf())); client.gameRenderer.loadProjectionMatrix(projectionMatrix); - /*renderer.scheduleBlockRenders( - ChunkSectionPos.getSectionCoord((int)cameraEntity.getX()), - ChunkSectionPos.getSectionCoord((int)cameraEntity.getY()), - ChunkSectionPos.getSectionCoord((int)cameraEntity.getZ()) - );*/ + renderer.setupFrustum( camera.getPos(), cameraTransform, - client.gameRenderer.getBasicProjectionMatrix(Math.max(fov, this.client.options.getFov().getValue().intValue())) + client.gameRenderer.getBasicProjectionMatrix(Math.max(fov, client.options.getFov().getValue().intValue())) + ); + renderer.render(client.getRenderTickCounter(), false, camera, client.gameRenderer, + client.gameRenderer.getLightmapTextureManager(), + cameraTransform, + projectionMatrix ); - try { - renderer.render(tickCounter, false, camera, client.gameRenderer, - client.gameRenderer.getLightmapTextureManager(), - cameraTransform, - projectionMatrix - ); - } catch (Throwable t) { - close(); - } - // Strip transparency RenderSystem.colorMask(false, false, false, true); RenderSystem.clearColor(1, 1, 1, 1); @@ -246,6 +245,7 @@ class PortalFrameBuffer implements AutoCloseable { } finally { client.getFramebuffer().beginWrite(true); client.gameRenderer.loadProjectionMatrix(proj); + client.getBlockEntityRenderDispatcher().setWorld(client.world); window.setFramebufferWidth(globalFramebufferWidth); window.setFramebufferHeight(globalFramebufferHeight); @@ -264,6 +264,7 @@ class PortalFrameBuffer implements AutoCloseable { if (renderer != null) { renderer.getChunkBuilder().stop(); renderer.close(); + renderer = null; } } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java index 42996391..23ebc8e1 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/PortalSpellRenderer.java @@ -6,6 +6,8 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.PortalSpell; import com.minelittlepony.unicopia.client.render.RenderLayers; import com.minelittlepony.unicopia.client.render.model.SphereModel; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; + import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; @@ -42,11 +44,14 @@ public class PortalSpellRenderer extends SpellRenderer { return; } - if (caster.asEntity().distanceTo(client.cameraEntity) > 50) { - return; // don't bother rendering if too far away - } - if (client.cameraEntity == caster.asEntity()) { - return; + if (client.cameraEntity instanceof CastSpellEntity) { + double distance = caster.asEntity().distanceTo(client.cameraEntity); + if (distance > 50) { + return; // don't bother rendering if too far away + } + if (distance < 2) { + return; // don't render ourselves + } } matrices.push(); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 4f33a55c..8c8abb5a 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -788,8 +788,8 @@ public class PlayerPhysics extends EntityPhysics implements Tickab Vec3d airflow = WeatherConditions.getAirflow(entity.getBlockPos(), entity.getWorld()) .multiply(0.04F * effectStrength) .add(Vec3d.fromPolar( - (entity.getPitch() + (float)gust.getY()) * MathHelper.RADIANS_PER_DEGREE, - (entity.getYaw() + (float)gust.getZ()) * MathHelper.RADIANS_PER_DEGREE + (entity.getPitch() + (float)gust.getY()), + (entity.getYaw() + (float)gust.getZ()) ).multiply(effectStrength * (float)gust.getX() / weight)); windStrength.update((float)airflow.length(), airflow.length() > windStrength.getValue() ? 1000 : 500); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinMinecraftClient.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinMinecraftClient.java index 848ef7d0..f210faea 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinMinecraftClient.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinMinecraftClient.java @@ -3,18 +3,12 @@ package com.minelittlepony.unicopia.mixin.client; import java.util.Queue; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.WorldRenderer; @Mixin(MinecraftClient.class) public interface MixinMinecraftClient { @Accessor("renderTaskQueue") Queue getRenderTaskQueue(); - - @Mutable - @Accessor("worldRenderer") - void setWorldRenderer(WorldRenderer worldRenderer); } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinChunkDataSender.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinChunkDataSender.java new file mode 100644 index 00000000..d7a0ef0a --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinChunkDataSender.java @@ -0,0 +1,40 @@ +package com.minelittlepony.unicopia.mixin.server; + +import java.util.stream.LongStream; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minelittlepony.unicopia.ability.magic.spell.effect.PortalSpell; +import com.minelittlepony.unicopia.server.world.Ether; + +import it.unimi.dsi.fastutil.longs.LongSet; +import net.minecraft.server.network.ChunkDataSender; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.WorldChunk; + +@Mixin(ChunkDataSender.class) +abstract class MixinChunkDataSender { + @Shadow + private @Final LongSet chunks; + + @Inject(method = "add", at = @At("RETURN")) + private void onAdd(WorldChunk chunk, CallbackInfo info) { + var etherChunk = Ether.get(chunk.getWorld()).getChunk(chunk.getPos()); + if (etherChunk != null) { + etherChunk.getStates().stream().flatMapToLong(state -> { + if (state.getSpell() instanceof PortalSpell portal && portal.getDestinationReference().isSet()) { + return portal.getDestinationReference() + .getTarget() + .stream() + .mapToLong(target -> ChunkPos.toLong(BlockPos.ofFloored(target.pos()))); + } + return LongStream.empty(); + }).distinct().forEach(chunks::add); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java index 8f30bdb3..7efe8d22 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java @@ -13,6 +13,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.server.world.chunk.Chunk; import com.minelittlepony.unicopia.server.world.chunk.PositionalDataMap; import com.minelittlepony.unicopia.util.Tickable; import com.minelittlepony.unicopia.util.serialization.NbtSerialisable; @@ -20,6 +21,7 @@ import net.minecraft.nbt.*; import net.minecraft.registry.RegistryWrapper.WrapperLookup; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.PersistentState; import net.minecraft.world.World; @@ -172,6 +174,10 @@ public class Ether extends PersistentState implements Tickable { return world.isClient() ? Set.of() : positionData.getState(pos); } + public Chunk> getChunk(ChunkPos pos) { + return world.isClient() ? null : positionData.getChunk(pos); + } + private void pruneNodes() { this.endpoints.values().removeIf(entities -> { entities.values().removeIf(spells -> { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java index d59919db..028329c0 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java @@ -22,6 +22,10 @@ public class Chunk { return section == null ? Set.of() : section.getState(pos); } + public synchronized Set getStates() { + return new HashSet<>(entryToSections.keySet()); + } + public synchronized boolean remove(T entry) { Set> sections = entryToSections.remove(entry); if (sections != null) { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java index eb2ee335..bcb41d5e 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java @@ -5,6 +5,8 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import org.jetbrains.annotations.Nullable; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.util.math.BlockPos; @@ -22,6 +24,11 @@ public class PositionalDataMap { return chunk == null ? Set.of() : chunk.getState(pos); } + @Nullable + public Chunk getChunk(ChunkPos pos) { + return chunks.get(pos.toLong()); + } + public void remove(T entry) { Set> chunks = entryToChunks.remove(entry); if (chunks != null) { diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 20215020..9a63d0c6 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -60,6 +60,7 @@ "datafix.MixinSchemas", "datafix.MixinItemStackComponentizationFix", "datafix.DataFixerBuilderAccessor", + "server.MixinChunkDataSender", "server.MixinEntityTrackerEntry", "server.MixinPathNodeMaker", "server.MixinPlayerManager",