diff --git a/gradle.properties b/gradle.properties index 4a78c15..7ed2046 100644 --- a/gradle.properties +++ b/gradle.properties @@ -36,7 +36,7 @@ mod_name=Cog Works Engineering # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=PolyFormPerimeter-1.0 # The mod version. See https://semver.org/ -mod_version=0.4.2 +mod_version=0.4.3 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/org/darkar/cog_works/block/events/BlockEvents.java b/src/main/java/org/darkar/cog_works/block/events/BlockEvents.java new file mode 100644 index 0000000..101f74b --- /dev/null +++ b/src/main/java/org/darkar/cog_works/block/events/BlockEvents.java @@ -0,0 +1,73 @@ +package org.darkar.cog_works.block.events; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.level.BlockEvent; +import net.neoforged.neoforge.network.PacketDistributor; +import org.darkar.cog_works.level.chunk.attachment.ChunkSampleSiteMap; +import org.darkar.cog_works.net.payload.client.ClientSampleSiteMapUpdatePayload; +import org.darkar.cog_works.utils.Data.AttachmentUtils.ChunkSampleSiteMapUtil; + +import java.util.Optional; + +import static org.darkar.cog_works.CogWorks.MOD_ID; +import static org.darkar.cog_works.Registry.DataAttachments.CHUNK_SAMPLE_SITE_MAP; + +@EventBusSubscriber(modid = MOD_ID) +public class BlockEvents { + + /** + * Handles the logic to update the {@link ChunkSampleSiteMap} when a block is broken and is a sample site. + * + * @param levelAccessor level where the block is broken + * @param pos position of the block that was broken + * @param player player that broke the block + */ + private static void handleChunkSampleSiteMap(LevelAccessor levelAccessor, BlockPos pos, Player player) { + ChunkAccess chunk = levelAccessor.getChunk(pos); + Level level = player.level(); + if (level.isClientSide()) return; + Optional payload = Optional.empty(); + if (!chunk.hasAttachments() || !chunk.hasData(CHUNK_SAMPLE_SITE_MAP)) return; + ChunkSampleSiteMap chunkSampleSiteMap = chunk.getData(CHUNK_SAMPLE_SITE_MAP); + if (!ChunkSampleSiteMapUtil.isDirty(chunkSampleSiteMap)) return; + + if (ChunkSampleSiteMapUtil.isSurface(chunkSampleSiteMap, pos)) { + ChunkSampleSiteMap newChunkSampleSiteMap = ChunkSampleSiteMapUtil.resetDefaultSurface(chunkSampleSiteMap); + chunk.setData(CHUNK_SAMPLE_SITE_MAP, newChunkSampleSiteMap); + payload = Optional.of(new ClientSampleSiteMapUpdatePayload(chunk.getPos(), + newChunkSampleSiteMap)); + + } + + if (ChunkSampleSiteMapUtil.isDeep(chunkSampleSiteMap, pos)) { + ChunkSampleSiteMap newChunkSampleSiteMap = ChunkSampleSiteMapUtil.resetDefaultDeep(chunkSampleSiteMap); + chunk.setData(CHUNK_SAMPLE_SITE_MAP, newChunkSampleSiteMap); + payload = Optional.of(new ClientSampleSiteMapUpdatePayload(chunk.getPos(), + newChunkSampleSiteMap)); + } + + + payload.ifPresent(updatePayload -> { + PacketDistributor.sendToPlayersTrackingChunk((ServerLevel) level, chunk.getPos(), updatePayload); + }); + + } + + @SubscribeEvent + public static void onBlockBreak(final BlockEvent.BreakEvent event) { + Player player = event.getPlayer(); + LevelAccessor level = event.getLevel(); + BlockPos breakPos = event.getPos(); + + if (!level.isClientSide()) { + handleChunkSampleSiteMap(level, breakPos, player); + } + } +} diff --git a/src/main/java/org/darkar/cog_works/item/ProspectingPickItem.java b/src/main/java/org/darkar/cog_works/item/ProspectingPickItem.java index ef4f5c6..b26edfc 100644 --- a/src/main/java/org/darkar/cog_works/item/ProspectingPickItem.java +++ b/src/main/java/org/darkar/cog_works/item/ProspectingPickItem.java @@ -5,7 +5,6 @@ import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; import net.minecraft.tags.TagKey; import net.minecraft.world.InteractionHand; @@ -144,10 +143,9 @@ public void handleLeftClickBlock(Player player, Level level, BlockPos pos, Direc player.getCooldowns().addCooldown(this, COOLDOWN_TICKS); if (needsCollection) { String message = String.format( - "This chunk already has a surface sampling site. Please collect the surface sample at" + - " %s" + - " before placing a new one", - chunkSampleSiteMap.surfacePos()); + "This chunk already has a surface sampling site. Please collect the surface sample " + + "at" + + " %s" + " before placing a new one", chunkSampleSiteMap.surfacePos()); player.sendSystemMessage(Component.literal(message)); return; } @@ -159,28 +157,26 @@ public void handleLeftClickBlock(Player player, Level level, BlockPos pos, Direc chunkSampleSiteMap = new ChunkSampleSiteMap(pos, chunkSampleSiteMap.deepPos(), surfaceSiteState, - chunkSampleSiteMap.deepState(), - face, chunkSampleSiteMap.deepFace()); + chunkSampleSiteMap.deepState(), face, + chunkSampleSiteMap.deepFace()); chunk.setData(CHUNK_SAMPLE_SITE_MAP, chunkSampleSiteMap); - PacketDistributor.sendToPlayer((ServerPlayer) player, new ClientSampleSiteMapUpdatePayload( - chunkSampleSiteMap.surfacePos(), chunkSampleSiteMap.deepPos(), - chunkSampleSiteMap.surfaceState(), chunkSampleSiteMap.deepState(), - chunkSampleSiteMap.surfaceFace(), chunkSampleSiteMap.deepFace())); + ClientSampleSiteMapUpdatePayload payload = new ClientSampleSiteMapUpdatePayload(chunk.getPos(), + chunkSampleSiteMap); + PacketDistributor.sendToPlayersTrackingChunk(serverLevel, chunk.getPos(), payload); } case DEEP -> { boolean needsCollection = !chunkSampleSiteMap.deepPos().equals(BlockPos.ZERO) && - (!chunkSampleSiteMap.deepState().isAir() && - serverLevel.getBlockState(chunkSampleSiteMap.deepPos()).is( - tagsPerRegion.get(SampleSiteRegion.DEEP))); + (!chunkSampleSiteMap.deepState().isAir() && serverLevel.getBlockState( + chunkSampleSiteMap.deepPos()).is( + tagsPerRegion.get(SampleSiteRegion.DEEP))); itemStack.set(IS_DIGGING_SAMPLE, isDiggingSample); player.getCooldowns().addCooldown(this, COOLDOWN_TICKS); if (needsCollection) { String message = String.format( "This chunk already has a deep sampling site. Please collect the deep sample at %s " + - "before placing a new one", - chunkSampleSiteMap.deepPos()); + "before placing a new one", chunkSampleSiteMap.deepPos()); player.sendSystemMessage(Component.literal(message)); return; } @@ -192,11 +188,9 @@ public void handleLeftClickBlock(Player player, Level level, BlockPos pos, Direc chunkSampleSiteMap.surfaceState(), deepSiteState, chunkSampleSiteMap.surfaceFace(), face); chunk.setData(CHUNK_SAMPLE_SITE_MAP, chunkSampleSiteMap); - PacketDistributor.sendToPlayer((ServerPlayer) player, new ClientSampleSiteMapUpdatePayload( - chunkSampleSiteMap.surfacePos(), chunkSampleSiteMap.deepPos(), - chunkSampleSiteMap.surfaceState(), chunkSampleSiteMap.deepState(), - chunkSampleSiteMap.surfaceFace(), chunkSampleSiteMap.deepFace())); - + ClientSampleSiteMapUpdatePayload payload = new ClientSampleSiteMapUpdatePayload(chunk.getPos(), + chunkSampleSiteMap); + PacketDistributor.sendToPlayersTrackingChunk(serverLevel, chunk.getPos(), payload); } } diff --git a/src/main/java/org/darkar/cog_works/level/events/LevelEvents.java b/src/main/java/org/darkar/cog_works/level/events/LevelEvents.java index e7a9bf2..b8e3b52 100644 --- a/src/main/java/org/darkar/cog_works/level/events/LevelEvents.java +++ b/src/main/java/org/darkar/cog_works/level/events/LevelEvents.java @@ -23,10 +23,7 @@ public static void onChunkSent(final ChunkWatchEvent.Sent event) { ChunkPos pos = chunk.getPos(); if (chunk.hasAttachments() && chunk.hasData(CHUNK_SAMPLE_SITE_MAP)) { ChunkSampleSiteMap chunkSampleSiteMap = chunk.getData(CHUNK_SAMPLE_SITE_MAP); - ClientSampleSiteMapUpdatePayload payload = new ClientSampleSiteMapUpdatePayload( - chunkSampleSiteMap.surfacePos(), chunkSampleSiteMap.deepPos(), chunkSampleSiteMap.surfaceState(), - chunkSampleSiteMap.deepState(), chunkSampleSiteMap.surfaceFace(), chunkSampleSiteMap.deepFace() - ); + ClientSampleSiteMapUpdatePayload payload = new ClientSampleSiteMapUpdatePayload(pos, chunkSampleSiteMap); PacketDistributor.sendToPlayersTrackingChunk(serverLevel, pos, payload); } } diff --git a/src/main/java/org/darkar/cog_works/level/renderer/SampleSiteRenderBehaviour.java b/src/main/java/org/darkar/cog_works/level/renderer/SampleSiteRenderBehaviour.java index bf04a2d..bd62c61 100644 --- a/src/main/java/org/darkar/cog_works/level/renderer/SampleSiteRenderBehaviour.java +++ b/src/main/java/org/darkar/cog_works/level/renderer/SampleSiteRenderBehaviour.java @@ -18,15 +18,18 @@ import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.client.NeoForgeRenderTypes; import org.darkar.cog_works.level.chunk.attachment.ChunkSampleSiteMap; +import org.darkar.cog_works.utils.Data; import org.darkar.cog_works.utils.World; import org.joml.Matrix4f; -import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static org.darkar.cog_works.CogWorks.MOD_ID; import static org.darkar.cog_works.Registry.DataAttachments.CHUNK_SAMPLE_SITE_MAP; @@ -42,62 +45,65 @@ public static void render(Frustum frustum, PoseStack poseStack, Camera cam) { LocalPlayer player = minecraft.player; BlockPos currentPos = player.getOnPos(); - LevelChunk chunk = level.getChunkAt(currentPos); + ChunkAccess chunk = level.getChunk(currentPos); - List nearbyChunks = World.getNearbyChunks(chunk, 2); RenderBuffers buffers = minecraft.renderBuffers(); MultiBufferSource.BufferSource source = buffers.bufferSource(); Vec3 camPos = cam.getPosition(); RenderType bufferType = NeoForgeRenderTypes.TRANSLUCENT_ON_PARTICLES_TARGET.get(); + Map mapsToRender = World.getNearbyChunks(chunk, level, 4).filter( + nearbyChunk -> nearbyChunk.hasAttachments() && nearbyChunk.hasData(CHUNK_SAMPLE_SITE_MAP) && + Data.AttachmentUtils.ChunkSampleSiteMapUtil.isDirty( + nearbyChunk.getData(CHUNK_SAMPLE_SITE_MAP))).collect( + Collectors.toMap(ChunkAccess::getPos, mapChunk -> mapChunk.getData(CHUNK_SAMPLE_SITE_MAP))); - nearbyChunks.stream().filter( - nearbyChunk -> nearbyChunk.hasAttachments() && nearbyChunk.hasData(CHUNK_SAMPLE_SITE_MAP)).forEach( - nearbyChunk -> { - - ChunkSampleSiteMap chunkSampleSiteMap = nearbyChunk.getData(CHUNK_SAMPLE_SITE_MAP); - boolean isSurfaceVisible = frustum.isVisible(new AABB(chunkSampleSiteMap.surfacePos())); - boolean isDeepVisible = frustum.isVisible(new AABB(chunkSampleSiteMap.deepPos())); - if (!isSurfaceVisible && !isDeepVisible) { - return; - } - - BlockPos pos = isSurfaceVisible ? chunkSampleSiteMap.surfacePos() : chunkSampleSiteMap.deepPos(); - Direction face = isSurfaceVisible ? chunkSampleSiteMap.surfaceFace() : chunkSampleSiteMap.deepFace(); - Vec3 offset = Vec3.atLowerCornerOf(pos).subtract(camPos); - - poseStack.pushPose(); - poseStack.translate(offset.x, offset.y, offset.z); - poseStack.translate(.5F, .5F, .5F); - switch (face) { - case UP -> poseStack.mulPose(Axis.XP.rotationDegrees(90F)); - case DOWN -> poseStack.mulPose(Axis.XN.rotationDegrees(90F)); - default -> poseStack.mulPose(Axis.YN.rotationDegrees((face.toYRot() + 180F) % 360F)); - } - poseStack.translate(-.5F, -.5F, -.5F); - VertexConsumer textureConsumer = source.getBuffer(bufferType); - TextureAtlasSprite texture = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply( - SAMPLE_SITE_TEXTURE_KEY); - - Matrix4f quadMatrix = poseStack.last().pose(); - textureConsumer.vertex(quadMatrix, 0, 1, -0.01F).color(255, 255, 255, 255).uv(texture.getU0(), - texture.getV0()) - .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( - poseStack.last(), 0, 0, -1).endVertex(); - textureConsumer.vertex(quadMatrix, 1, 1, -0.01F).color(255, 255, 255, 255).uv(texture.getU0(), - texture.getV1()) - .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( - poseStack.last(), 0, 0, -1).endVertex(); - textureConsumer.vertex(quadMatrix, 1, 0, -0.01F).color(255, 255, 255, 255).uv(texture.getU1(), - texture.getV1()) - .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( - poseStack.last(), 0, 0, -1).endVertex(); - textureConsumer.vertex(quadMatrix, 0, 0, -0.01F).color(255, 255, 255, 255).uv(texture.getU1(), - texture.getV0()) - .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( - poseStack.last(), 0, 0, -1).endVertex(); - source.endBatch(bufferType); - poseStack.popPose(); - }); + for (ChunkSampleSiteMap chunkSampleSiteMap : mapsToRender.values()) { + boolean isSurfaceVisible = frustum.isVisible(new AABB(chunkSampleSiteMap.surfacePos())) && + !chunkSampleSiteMap.surfacePos().equals(BlockPos.ZERO); + boolean isDeepVisible = frustum.isVisible(new AABB(chunkSampleSiteMap.deepPos())) && + !chunkSampleSiteMap.deepPos().equals(BlockPos.ZERO); + + if (!isSurfaceVisible && !isDeepVisible) { + return; + } + + BlockPos pos = isSurfaceVisible ? chunkSampleSiteMap.surfacePos() : chunkSampleSiteMap.deepPos(); + Direction face = isSurfaceVisible ? chunkSampleSiteMap.surfaceFace() : chunkSampleSiteMap.deepFace(); + Vec3 offset = Vec3.atLowerCornerOf(pos).subtract(camPos); + + poseStack.pushPose(); + poseStack.translate(offset.x, offset.y, offset.z); + poseStack.translate(.5F, .5F, .5F); + switch (face) { + case UP -> poseStack.mulPose(Axis.XP.rotationDegrees(90F)); + case DOWN -> poseStack.mulPose(Axis.XN.rotationDegrees(90F)); + default -> poseStack.mulPose(Axis.YN.rotationDegrees((face.toYRot() + 180F) % 360F)); + } + poseStack.translate(-.5F, -.5F, -.5F); + VertexConsumer textureConsumer = source.getBuffer(bufferType); + TextureAtlasSprite texture = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply( + SAMPLE_SITE_TEXTURE_KEY); + + Matrix4f quadMatrix = poseStack.last().pose(); + textureConsumer.vertex(quadMatrix, 0, 1, -0.01F).color(255, 255, 255, 255).uv(texture.getU0(), + texture.getV0()) + .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( + poseStack.last(), 0, 0, -1).endVertex(); + textureConsumer.vertex(quadMatrix, 1, 1, -0.01F).color(255, 255, 255, 255).uv(texture.getU0(), + texture.getV1()) + .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( + poseStack.last(), 0, 0, -1).endVertex(); + textureConsumer.vertex(quadMatrix, 1, 0, -0.01F).color(255, 255, 255, 255).uv(texture.getU1(), + texture.getV1()) + .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( + poseStack.last(), 0, 0, -1).endVertex(); + textureConsumer.vertex(quadMatrix, 0, 0, -0.01F).color(255, 255, 255, 255).uv(texture.getU1(), + texture.getV0()) + .overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal( + poseStack.last(), 0, 0, -1).endVertex(); + source.endBatch(bufferType); + poseStack.popPose(); + } } diff --git a/src/main/java/org/darkar/cog_works/net/payload/client/ClientSampleSiteMapUpdatePayload.java b/src/main/java/org/darkar/cog_works/net/payload/client/ClientSampleSiteMapUpdatePayload.java index 33e7180..f7c61d9 100644 --- a/src/main/java/org/darkar/cog_works/net/payload/client/ClientSampleSiteMapUpdatePayload.java +++ b/src/main/java/org/darkar/cog_works/net/payload/client/ClientSampleSiteMapUpdatePayload.java @@ -1,56 +1,46 @@ package org.darkar.cog_works.net.payload.client; -import io.netty.buffer.ByteBuf; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.network.codec.NeoForgeStreamCodecs; import net.neoforged.neoforge.network.handling.IPayloadContext; import org.darkar.cog_works.level.chunk.attachment.ChunkSampleSiteMap; +import static org.darkar.cog_works.CogWorks.LOGGER; import static org.darkar.cog_works.CogWorks.MOD_ID; import static org.darkar.cog_works.Registry.DataAttachments.CHUNK_SAMPLE_SITE_MAP; -public record ClientSampleSiteMapUpdatePayload(BlockPos surfacePos, BlockPos deepPos, BlockState surfaceState, - BlockState deepState, Direction surfaceFace, - Direction deepFace) implements CustomPacketPayload +public record ClientSampleSiteMapUpdatePayload(ChunkPos targetChunk, ChunkSampleSiteMap sampleSiteMap) implements CustomPacketPayload { public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(new ResourceLocation(MOD_ID, "update_chunk_sample_site_map")); - @SuppressWarnings("deprecation") - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - BlockPos.STREAM_CODEC, ClientSampleSiteMapUpdatePayload::surfacePos, BlockPos.STREAM_CODEC, - ClientSampleSiteMapUpdatePayload::deepPos, ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY), - ClientSampleSiteMapUpdatePayload::surfaceState, ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY), - ClientSampleSiteMapUpdatePayload::deepState, Direction.STREAM_CODEC, - ClientSampleSiteMapUpdatePayload::surfaceFace, Direction.STREAM_CODEC, - ClientSampleSiteMapUpdatePayload::deepFace, ClientSampleSiteMapUpdatePayload::new); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + NeoForgeStreamCodecs.CHUNK_POS, ClientSampleSiteMapUpdatePayload::targetChunk, + ChunkSampleSiteMap.STREAM_CODEC, ClientSampleSiteMapUpdatePayload::sampleSiteMap, + ClientSampleSiteMapUpdatePayload::new + ); + public static void handle(final ClientSampleSiteMapUpdatePayload data, final IPayloadContext ctx) { ctx.enqueueWork(() -> { if (FMLEnvironment.dist.isClient()) { - Player player = ctx.player(); + Player player = ctx.player(); Level level = player.level(); - BlockPos surfacePos = data.surfacePos(); - BlockPos deepPos = data.deepPos(); - BlockState surfaceState = data.surfaceState(); - BlockState deepState = data.deepState(); - Direction surfaceFace = data.surfaceFace(); - Direction deepFace = data.deepFace(); + ChunkAccess chunk = level.getChunk(data.targetChunk().x, data.targetChunk().z); + ChunkSampleSiteMap sampleSiteMap = data.sampleSiteMap(); - level.getChunk(surfacePos).setData(CHUNK_SAMPLE_SITE_MAP, - new ChunkSampleSiteMap(surfacePos, deepPos, surfaceState, deepState, - surfaceFace, deepFace)); + LOGGER.info("Client received Sample Site Map Update Payload: {}", data); + chunk.setData(CHUNK_SAMPLE_SITE_MAP,sampleSiteMap); } }); diff --git a/src/main/java/org/darkar/cog_works/utils/Data.java b/src/main/java/org/darkar/cog_works/utils/Data.java new file mode 100644 index 0000000..3a5082e --- /dev/null +++ b/src/main/java/org/darkar/cog_works/utils/Data.java @@ -0,0 +1,136 @@ +package org.darkar.cog_works.utils; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import org.darkar.cog_works.level.chunk.attachment.ChunkSampleSiteMap; + +public class Data { + + public static class AttachmentUtils { + + public static class ChunkSampleSiteMapUtil { + + /** + * Resets the surface position and state of the given {@link ChunkSampleSiteMap} to the default values. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to reset + * @return a new {@link ChunkSampleSiteMap} with the surface position and state reset to the default values + */ + public static ChunkSampleSiteMap resetDefaultSurface(ChunkSampleSiteMap chunkSampleSiteMap) { + return new ChunkSampleSiteMap(ChunkSampleSiteMap.DEFAULT.surfacePos(), chunkSampleSiteMap.deepPos(), + ChunkSampleSiteMap.DEFAULT.surfaceState(), + chunkSampleSiteMap.deepState(), + ChunkSampleSiteMap.DEFAULT.surfaceFace(), chunkSampleSiteMap.deepFace()); + } + + /** + * Resets the deep position and state of the given {@link ChunkSampleSiteMap} to the default values. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to reset + * @return a new {@link ChunkSampleSiteMap} with the deep position and state reset to the default values + */ + public static ChunkSampleSiteMap resetDefaultDeep(ChunkSampleSiteMap chunkSampleSiteMap) { + return new ChunkSampleSiteMap(chunkSampleSiteMap.surfacePos(), ChunkSampleSiteMap.DEFAULT.deepPos(), + chunkSampleSiteMap.surfaceState(), + ChunkSampleSiteMap.DEFAULT.deepState(), + chunkSampleSiteMap.surfaceFace(), ChunkSampleSiteMap.DEFAULT.deepFace()); + } + + /** + * Determines if the given {@link BlockPos} matches the surface position of the given + * {@link ChunkSampleSiteMap}. But only checks the position, not the state. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @param blockPos the {@link BlockPos} to check + * @return {@code true} if the given {@link BlockPos} matches the surface position of the given + */ + public static boolean isSurface(ChunkSampleSiteMap chunkSampleSiteMap, BlockPos blockPos) { + return chunkSampleSiteMap.surfacePos().equals(blockPos); + } + + /** + * Determines if the given {@link BlockPos} matches the surface position of the given + * {@link ChunkSampleSiteMap}. Checks both the position and the state. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @param blockPos the {@link BlockPos} to check + * @param level the {@link Level} to access the block state + * @return {@code true} if the given {@link BlockPos} matches the surface position of the given {@link ChunkSampleSiteMap} + * and the block state at the given {@link BlockPos} matches the surface state of the given {@link ChunkSampleSiteMap} + */ + public static boolean isSurface(ChunkSampleSiteMap chunkSampleSiteMap, BlockPos blockPos, + Level level) + { + return chunkSampleSiteMap.surfacePos().equals(blockPos) && chunkSampleSiteMap.surfaceState().equals( + level.getBlockState(blockPos)); + } + + /** + * Determines if the given {@link BlockPos} matches the deep position of the given {@link ChunkSampleSiteMap}. + * But only checks the position, not the state. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @param blockPos the {@link BlockPos} to check + * @return {@code true} if the given {@link BlockPos} matches the deep position of the given {@link ChunkSampleSiteMap} + */ + public static boolean isDeep(ChunkSampleSiteMap chunkSampleSiteMap, BlockPos blockPos) { + return chunkSampleSiteMap.deepPos().equals(blockPos); + } + + /** + * Determines if the given {@link BlockPos} matches the deep position of the given {@link ChunkSampleSiteMap}. + * Checks both the position and the state. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @param blockPos the {@link BlockPos} to check + * @param level the {@link Level} to access the block state + * @return {@code true} if the given {@link BlockPos} matches the deep position of the given {@link ChunkSampleSiteMap} + * and the block state at the given {@link BlockPos} matches the deep state of the given {@link ChunkSampleSiteMap} + */ + public static boolean isDeep(ChunkSampleSiteMap chunkSampleSiteMap, BlockPos blockPos, Level level) { + return chunkSampleSiteMap.deepPos().equals(blockPos) && chunkSampleSiteMap.deepState().equals( + level.getBlockState(blockPos)); + } + + /** + * Determines if the given {@link BlockPos} matches either the surface or deep position of the given + * {@link ChunkSampleSiteMap}. But only checks the position, not the state. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @param blockPos the {@link BlockPos} to check + * @return {@code true} if the given {@link BlockPos} matches either the surface or deep position of the given + */ + public static boolean isSurfaceOrDeep(ChunkSampleSiteMap chunkSampleSiteMap, BlockPos blockPos) { + return isSurface(chunkSampleSiteMap, blockPos) || isDeep(chunkSampleSiteMap, blockPos); + } + + /** + * Determines if the given {@link BlockPos} matches either the surface or deep position of the given + * {@link ChunkSampleSiteMap}. Checks both the position and the state. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @param blockPos the {@link BlockPos} to check + * @param level the {@link Level} to access the block state + * @return {@code true} if the given {@link BlockPos} matches either the surface or deep position of the given + * {@link ChunkSampleSiteMap} and the block state at the given {@link BlockPos} matches either the surface or deep state + * of the given {@link ChunkSampleSiteMap} + */ + public static boolean isSurfaceOrDeep(ChunkSampleSiteMap chunkSampleSiteMap, BlockPos blockPos, + Level level) + { + return isSurface(chunkSampleSiteMap, blockPos, level) || isDeep(chunkSampleSiteMap, blockPos, level); + } + + /** + * Determines if the given {@link ChunkSampleSiteMap} is different from its default in any member. + * + * @param chunkSampleSiteMap the {@link ChunkSampleSiteMap} to check + * @return {@code true} if the given {@link ChunkSampleSiteMap} is dirty + */ + public static boolean isDirty(ChunkSampleSiteMap chunkSampleSiteMap) { + return !chunkSampleSiteMap.equals(ChunkSampleSiteMap.DEFAULT); + } + } + } + +} diff --git a/src/main/java/org/darkar/cog_works/utils/World.java b/src/main/java/org/darkar/cog_works/utils/World.java index a1288f7..64c5cce 100644 --- a/src/main/java/org/darkar/cog_works/utils/World.java +++ b/src/main/java/org/darkar/cog_works/utils/World.java @@ -2,31 +2,34 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.ChunkAccess; -import java.util.ArrayList; -import java.util.List; import java.util.stream.Stream; public class World { - public static List getNearbyChunks(LevelChunk chunk) { - return getNearbyChunks(chunk, 8); + /** + * Gets a list of nearby chunks around the given {@link ChunkAccess} within a default radius of {@code 2} chunks. + * + * @param chunk the {@link ChunkAccess} that is the center to get nearby chunks from + * @param level the {@link Level} to get the chunks from + * @return a list of nearby chunks around the given {@link ChunkAccess} + */ + public static Stream getNearbyChunks(ChunkAccess chunk, Level level) { + return getNearbyChunks(chunk, level,2); } - public static List getNearbyChunks(LevelChunk chunk, int radius) { - List chunks = new ArrayList<>(); - chunks.add(chunk); - Level level = chunk.getLevel(); + /** + * Gets a list of nearby chunks around the given {@link ChunkAccess} within the given radius. + * + * @param chunk the {@link ChunkAccess} that is the center to get nearby chunks from + * @param level the {@link Level} to get the chunks from + * @param radius the radius to search for nearby chunks + * @return a list of nearby chunks around the given {@link ChunkAccess} + */ + public static Stream getNearbyChunks(ChunkAccess chunk, Level level ,int radius) { ChunkPos chunkPos = chunk.getPos(); - Stream chunkPosStream = ChunkPos.rangeClosed(chunkPos, radius); - - chunkPosStream.filter((pos) -> !chunkPos.equals(pos)).forEach(pos -> { - LevelChunk nearbyChunk = level.getChunk(pos.x, pos.z); - chunks.add(nearbyChunk); - }); - - return chunks; + return chunkPosStream.map(pos -> level.getChunk(pos.x, pos.z)); } }