BloodMagic/src/main/java/WayofTime/bloodmagic/structures/Dungeon.java
2016-08-20 17:16:07 -04:00

179 lines
7 KiB
Java

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<EnumFacing, List<BlockPos>> availableDoorMap = new HashMap<EnumFacing, List<BlockPos>>(); //Map of doors. The EnumFacing indicates what way this door faces.
List<AreaDescriptor> descriptorList = new ArrayList<AreaDescriptor>();
Map<BlockPos, Pair<DungeonRoom, PlacementSettings>> roomMap = new HashMap<BlockPos, Pair<DungeonRoom, PlacementSettings>>(); // 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<BlockPos> doorList = availableDoorMap.get(facing);
doorList.addAll(room.getDoorOffsetsForFacing(settings, facing, pos));
} else
{
List<BlockPos> 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<EnumFacing> facingList = new ArrayList<EnumFacing>();
for (Entry<EnumFacing, List<BlockPos>> 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<EnumFacing, BlockPos> removedDoor1 = null;
Pair<EnumFacing, BlockPos> removedDoor2 = null;
BlockPos roomLocation = null;
roomPlacement: for (EnumFacing doorFacing : facingList)
{
EnumFacing oppositeDoorFacing = doorFacing.getOpposite();
List<BlockPos> 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<BlockPos> 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<AreaDescriptor> 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<BlockPos> doorList = availableDoorMap.get(facing);
doorList.addAll(room.getDoorOffsetsForFacing(settings, facing, roomLocation));
} else
{
List<BlockPos> 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<BlockPos, Pair<DungeonRoom, PlacementSettings>> 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);
}
}