package WayofTime.bloodmagic.structures; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.util.EnumFacing; import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.WorldServer; import net.minecraft.world.gen.structure.template.PlacementSettings; import org.apache.commons.lang3.tuple.Pair; import WayofTime.bloodmagic.api.ritual.AreaDescriptor; public class Dungeon { public static boolean placeStructureAtPosition(Random rand, WorldServer world, BlockPos pos) { Map> availableDoorMap = new HashMap>(); //Map of doors. The EnumFacing indicates what way this door faces. List descriptorList = new ArrayList(); Map> roomMap = new HashMap>(); // Placement positions in terms of actual positions PlacementSettings settings = new PlacementSettings(); Mirror mir = Mirror.NONE; settings.setMirror(mir); Rotation rot = Rotation.NONE; settings.setRotation(rot); settings.setIgnoreEntities(true); settings.setChunk((ChunkPos) null); settings.setReplacedBlock((Block) null); settings.setIgnoreStructureBlock(false); DungeonRoom room = getRandomRoom(rand); roomMap.put(pos, Pair.of(room, settings.copy())); descriptorList.addAll(room.getAreaDescriptors(settings, pos)); for (EnumFacing facing : EnumFacing.VALUES) { if (availableDoorMap.containsKey(facing)) { List doorList = availableDoorMap.get(facing); doorList.addAll(room.getDoorOffsetsForFacing(settings, facing, pos)); } else { List doorList = room.getDoorOffsetsForFacing(settings, facing, pos); availableDoorMap.put(facing, doorList); } } //Initial AreaDescriptors and door positions are initialized. Time for fun! for (int i = 0; i < 100; i++) { List facingList = new ArrayList(); for (Entry> entry : availableDoorMap.entrySet()) { if (entry.getValue() != null && !entry.getValue().isEmpty()) { facingList.add(entry.getKey()); } } Collections.shuffle(facingList); //Shuffle the list so that it is random what is chosen Pair removedDoor1 = null; Pair removedDoor2 = null; BlockPos roomLocation = null; roomPlacement: for (EnumFacing doorFacing : facingList) { EnumFacing oppositeDoorFacing = doorFacing.getOpposite(); List availableDoorList = availableDoorMap.get(doorFacing); //May need to copy here Collections.shuffle(availableDoorList); settings.setRotation(Rotation.values()[rand.nextInt(Rotation.values().length)]); //Same for the Mirror DungeonRoom testingRoom = getRandomRoom(rand); List otherDoorList = testingRoom.getDoorOffsetsForFacing(settings, oppositeDoorFacing, BlockPos.ORIGIN); if (otherDoorList != null && !otherDoorList.isEmpty()) { //See if one of these doors works. Collections.shuffle(otherDoorList); BlockPos testDoor = otherDoorList.get(0); testDoor: for (BlockPos availableDoor : availableDoorList) { //TODO: Test if it fits, then add the doors to the list. roomLocation = availableDoor.subtract(testDoor).add(doorFacing.getDirectionVec()); List descriptors = testingRoom.getAreaDescriptors(settings, roomLocation); for (AreaDescriptor testDesc : descriptors) { for (AreaDescriptor currentDesc : descriptorList) { if (testDesc.intersects(currentDesc)) { break testDoor; } } } roomMap.put(roomLocation, Pair.of(testingRoom, settings.copy())); descriptorList.addAll(descriptors); removedDoor1 = Pair.of(doorFacing, availableDoor); removedDoor2 = Pair.of(oppositeDoorFacing, testDoor.add(roomLocation)); room = testingRoom; break roomPlacement; } } // Collections.shuffle(otherDoorList); } if (removedDoor1 != null) { for (EnumFacing facing : EnumFacing.VALUES) { if (availableDoorMap.containsKey(facing)) { List doorList = availableDoorMap.get(facing); doorList.addAll(room.getDoorOffsetsForFacing(settings, facing, roomLocation)); } else { List doorList = room.getDoorOffsetsForFacing(settings, facing, roomLocation); availableDoorMap.put(facing, doorList); } } EnumFacing face = removedDoor1.getKey(); if (availableDoorMap.containsKey(face)) { availableDoorMap.get(face).remove(removedDoor1); } removedDoor1 = null; } if (removedDoor2 != null) { EnumFacing face = removedDoor2.getKey(); if (availableDoorMap.containsKey(face)) { availableDoorMap.get(face).remove(removedDoor2); } removedDoor2 = null; } } //Building what I've got for (Entry> entry : roomMap.entrySet()) { BlockPos placementPos = entry.getKey(); DungeonRoom placedRoom = entry.getValue().getKey(); PlacementSettings placementSettings = entry.getValue().getValue(); placedRoom.placeStructureAtPosition(rand, placementSettings, world, placementPos); } return false; } public static DungeonRoom getRandomRoom(Random rand) { return DungeonRoomRegistry.getRandomDungeonRoom(rand); } }