diff --git a/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java b/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java index c00650c..d69a16a 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java @@ -75,6 +75,7 @@ public class FinderConfig { MONUMENT(OceanMonumentFinder::create, Category.STRUCTURES), SWAMP_HUT(SwampHutFinder::create, Category.STRUCTURES), MANSION(MansionFinder::create, Category.STRUCTURES), + SHIPWRECK(ShipwreckFinder::create, Category.STRUCTURES), END_PILLARS(EndPillarsFinder::create, Category.OTHERS), END_GATEWAY(EndGatewayFinder::create, Category.OTHERS), diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/ShipwreckFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/ShipwreckFinder.java new file mode 100644 index 0000000..9cda143 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/ShipwreckFinder.java @@ -0,0 +1,209 @@ +package kaptainwutax.seedcracker.finder.structure; + +import kaptainwutax.seedcracker.SeedCracker; +import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.BlockFinder; +import kaptainwutax.seedcracker.finder.Finder; +import kaptainwutax.seedcracker.render.Cube; +import kaptainwutax.seedcracker.render.Cuboid; +import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.ChestBlockEntity; +import net.minecraft.client.util.math.Vector4f; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.feature.Feature; + +import java.util.ArrayList; +import java.util.List; + +public class ShipwreckFinder extends BlockFinder { + + protected static List SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> { + return false; + }); + + public ShipwreckFinder(World world, ChunkPos chunkPos) { + super(world, chunkPos, Blocks.CHEST); + this.searchPositions = SEARCH_POSITIONS; + } + + @Override + public List findInChunk() { + Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9)); + + if(!biome.hasStructureFeature(Feature.SHIPWRECK)) { + return new ArrayList<>(); + } + + List result = super.findInChunk(); + + result.removeIf(pos -> { + BlockState state = this.world.getBlockState(pos); + if(!state.get(ChestBlock.WATERLOGGED))return true; + + BlockEntity blockEntity = this.world.getBlockEntity(pos); + if(!(blockEntity instanceof ChestBlockEntity))return true; + + return !this.onChestFound(pos); + }); + + return result; + } + + /** + * Source: https://github.com/skyrising/casual-mod/blob/master/src/main/java/de/skyrising/casual/ShipwreckFinder.java + * */ + private boolean onChestFound(BlockPos pos) { + BlockPos.Mutable mutablePos = new BlockPos.Mutable(pos); + Direction chestFacing = world.getBlockState(pos).get(ChestBlock.FACING); + + int[] stairs = new int[4]; + int totalStairs = 0; + int[] trapdoors = new int[4]; + int totalTrapdoors = 0; + for(int y = -1; y <= 2; y++) { + for(int x = -1; x <= 1; x++) { + for(int z = -1; z <= 1; z++) { + if (x == 0 && y == 0 && z == 0)continue; + mutablePos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z); + BlockState neighborState = world.getBlockState(mutablePos); + Block neighborBlock = neighborState.getBlock(); + if(neighborBlock == Blocks.VOID_AIR)return false; + + if(neighborBlock instanceof StairsBlock) { + stairs[y + 1]++; + totalStairs++; + } else if(neighborBlock instanceof TrapdoorBlock) { + trapdoors[y + 1]++; + totalTrapdoors++; + } + } + } + } + //System.out.printf("%s: chest facing %s\n", pos, chestFacing); + int chestX = 4; + int chestY = 2; + int chestZ = 0; + int length = 16; + int height = 9; + Direction direction = chestFacing; + + if(trapdoors[3] > 4) { // with_mast[_degraded] + chestZ = 9; + height = 21; + length = 28; + } else if(totalTrapdoors == 0 && stairs[3] == 3) { // upsidedown_backhalf[_degraded] + if(stairs[0] == 0) { + chestX = 2; + chestZ = 12; + direction = chestFacing.getOpposite(); + } else { // redundant + chestX = 3; + chestY = 5; + chestZ = 5; + direction = chestFacing.rotateYClockwise(); + } + } else if(totalTrapdoors == 0) { // rightsideup that have backhalf + if(stairs[0] == 4) { + if(totalStairs > 4) { + chestX = 6; + chestY = 4; + chestZ = 12; + direction = chestFacing.getOpposite(); + } else { // sideways backhalf + chestX = 6; + chestY = 3; + chestZ = 8; + length = 17; + direction = chestFacing.getOpposite(); + } + } else if(stairs[0] == 3 && totalStairs > 5) { + chestX = 5; + chestZ = 6; + direction = chestFacing.rotateYCounterclockwise(); + } + + mutablePos.set(pos); + mutablePos.setOffset(0, -chestY, 0); + mutablePos.setOffset(direction.rotateYClockwise(), chestX - 4); + mutablePos.setOffset(direction, -chestZ - 1); + + if(this.world.getBlockState(mutablePos).getMaterial() == Material.WOOD) { + if(length == 17) { // sideways + chestZ += 11; + length += 11; + } else { + chestZ += 12; + length += 12; + } + mutablePos.setOffset(0, 10, 0); + + if(this.world.getBlockState(mutablePos).getBlock() instanceof LogBlock) { + height = 21; + } + } + } else if(totalTrapdoors == 2 && trapdoors[3] == 2 && stairs[3] == 3) { // rightsideup_fronthalf[_degraded] + chestZ = 8; + length = 24; + } + + if(chestZ != 0) { + mutablePos.set(pos); + mutablePos.setOffset(direction, 15 - chestZ); + mutablePos.setOffset(direction.rotateYClockwise(), chestX - 4); + BlockPos.Mutable pos2 = new BlockPos.Mutable(mutablePos); + pos2.setOffset(0, -chestY, 0); + pos2.setOffset(direction, -15); + pos2.setOffset(direction.rotateYClockwise(), 4); + BlockPos.Mutable pos3 = new BlockPos.Mutable(pos2); + pos3.setOffset(direction, length - 1); + pos3.setOffset(direction.rotateYClockwise(), -8); + pos3.setOffset(0, height - 1, 0); + + BlockBox box = new BlockBox( + Math.min(pos2.getX(), pos3.getX()), pos2.getY(), Math.min(pos2.getZ(), pos3.getZ()), + Math.max(pos2.getX(), pos3.getX()), pos3.getY(), Math.max(pos2.getZ(), pos3.getZ())); + + mutablePos.setOffset(-4, -chestY, -15); + + if((mutablePos.getX() & 0xf) == 0 && (mutablePos.getZ() & 0xf) == 0) { + if(SeedCracker.get().onStructureData(new StructureData(new ChunkPos(mutablePos), StructureData.SHIPWRECK))) { + this.renderers.add(new Cuboid(box, new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); + this.renderers.add(new Cube(new ChunkPos(mutablePos).getCenterBlockPos().offset(Direction.UP, mutablePos.getY()), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); + return true; + } + } + } + + return false; + } + + @Override + public boolean isValidDimension(DimensionType dimension) { + return dimension == DimensionType.OVERWORLD; + } + + public static List create(World world, ChunkPos chunkPos) { + List finders = new ArrayList<>(); + finders.add(new ShipwreckFinder(world, chunkPos)); + + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z))); + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1))); + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); + + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z))); + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1))); + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1))); + + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); + finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z + 1))); + return finders; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java b/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java index d0e7ffb..56db6f1 100644 --- a/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java +++ b/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java @@ -1,6 +1,7 @@ package kaptainwutax.seedcracker.render; import net.minecraft.client.util.math.Vector4f; +import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3i; @@ -24,6 +25,10 @@ public class Cuboid extends Renderer { this(start, new Vec3i(end.getX() - start.getX(), end.getY() - start.getY(), end.getZ() - start.getZ()), color); } + public Cuboid(BlockBox box, Vector4f color) { + this(new BlockPos(box.minX, box.minY, box.minZ), new BlockPos(box.maxX, box.maxY, box.maxZ), color); + } + public Cuboid(BlockPos start, Vec3i size, Vector4f color) { this.start = start; this.size = size;