Started implementing our support for dungeon packs. The code is not usable yet and the mod is not functional at this stage. A few additional changes should make it testable. A significant obstacle to implementing dungeon packs easily is that DungeonGenerator doesn't have some necessary information and shouldn't be modified. Even if it is modified, old serialized instances wouldn't have the new fields initialized. I'm having to create workarounds until we implement the new save format. DungeonPack handles all of the logic of selecting a dungeon and verifying whether its type is valid. It relies on DungeonChainRule and OptimizedRule to check which dungeons should be generated next given a list of the dungeons in a chain. DungeonType maps types in packs to ID numbers and provides a reference to the pack that owns the type. DungeonPackConfig will carry config information to be passed to the DungeonPack constructor.
160 lines
5.0 KiB
Java
160 lines
5.0 KiB
Java
package StevenDimDoors.mod_pocketDim;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.util.HashMap;
|
|
import java.util.Random;
|
|
|
|
import net.minecraft.world.World;
|
|
import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic;
|
|
import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper;
|
|
import StevenDimDoors.mod_pocketDim.helpers.dimHelper;
|
|
import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException;
|
|
|
|
public class SchematicLoader
|
|
{
|
|
private SchematicLoader() { }
|
|
|
|
public static boolean generateDungeonPocket(LinkData link, DDProperties properties)
|
|
{
|
|
//TODO: Phase this function out in the next update. ~SenseiKiwi
|
|
|
|
if (link == null || properties == null)
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
String schematicPath;
|
|
int originDimID = link.locDimID;
|
|
int destDimID = link.destDimID;
|
|
HashMap<Integer, DimData> dimList = dimHelper.dimList;
|
|
World world;
|
|
|
|
if (dimList.containsKey(destDimID))
|
|
{
|
|
dimList.get(destDimID).hasBeenFilled = true;
|
|
if (dimHelper.getWorld(destDimID) == null)
|
|
{
|
|
dimHelper.initDimension(destDimID);
|
|
}
|
|
world = dimHelper.getWorld(destDimID);
|
|
|
|
if (dimList.get(destDimID).dungeonGenerator == null)
|
|
{
|
|
//The following initialization code is based on code from ChunkProviderGenerate.
|
|
//It makes our generation depend on the world seed.
|
|
|
|
Random random = new Random(world.getSeed());
|
|
long factorA = random.nextLong() / 2L * 2L + 1L;
|
|
long factorB = random.nextLong() / 2L * 2L + 1L;
|
|
random.setSeed((link.destXCoord >> 4) * factorA + (link.destZCoord >> 4) * factorB ^ world.getSeed());
|
|
|
|
//TODO: FIX THIS LINE OR SADNESS WILL FOLLOW. Add a reference to the dungeon pack.
|
|
//DungeonHelper.instance().generateDungeonLink(link, ???, random);
|
|
}
|
|
schematicPath = dimList.get(destDimID).dungeonGenerator.schematicPath;
|
|
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
DungeonSchematic dungeon = checkSourceAndLoad(schematicPath);
|
|
boolean valid;
|
|
|
|
//Validate the dungeon's dimensions
|
|
if (hasValidDimensions(dungeon))
|
|
{
|
|
dungeon.applyImportFilters(properties);
|
|
|
|
//Check that the dungeon has an entrance or we'll have a crash
|
|
if (dungeon.getEntranceDoorLocation() != null)
|
|
{
|
|
valid = true;
|
|
}
|
|
else
|
|
{
|
|
System.err.println("The following schematic file does not have an entrance: " + schematicPath);
|
|
valid = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
System.err.println("The following schematic file has dimensions that exceed the maximum permitted dimensions for dungeons: " + schematicPath);
|
|
valid = false;
|
|
}
|
|
|
|
if (!valid)
|
|
{
|
|
//TODO: In the future, remove this dungeon from the generation lists altogether.
|
|
//That will have to wait until our code is updated to support that more easily.
|
|
System.err.println("The dungeon will not be loaded.");
|
|
DungeonGenerator defaultError = DungeonHelper.instance().getDefaultErrorDungeon();
|
|
dimList.get(destDimID).dungeonGenerator = defaultError;
|
|
dungeon = checkSourceAndLoad(defaultError.schematicPath);
|
|
dungeon.applyImportFilters(properties);
|
|
}
|
|
|
|
//Adjust the height at which the dungeon is placed to prevent vertical clipping
|
|
int fixedY = adjustDestinationY(world, link.destYCoord, dungeon);
|
|
if (fixedY != link.destYCoord)
|
|
{
|
|
dimHelper helperInstance = dimHelper.instance;
|
|
helperInstance.moveLinkDataDestination(link, link.destXCoord, fixedY, link.destZCoord, link.destDimID, true);
|
|
}
|
|
dungeon.copyToWorld(world, new Point3D(link.destXCoord, link.destYCoord, link.destZCoord), link.linkOrientation, originDimID, destDimID);
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static int adjustDestinationY(World world, int y, DungeonSchematic dungeon)
|
|
{
|
|
//The goal here is to guarantee that the dungeon fits within the vertical bounds
|
|
//of the world while shifting it as little as possible.
|
|
int destY = y;
|
|
|
|
//Is the top of the dungeon going to be at Y < worldHeight?
|
|
int entranceY = dungeon.getEntranceDoorLocation().getY();
|
|
int pocketTop = (dungeon.getHeight() - 1) + destY - entranceY;
|
|
int worldHeight = world.getHeight();
|
|
if (pocketTop >= worldHeight)
|
|
{
|
|
destY = (worldHeight - 1) - (dungeon.getHeight() - 1) + entranceY;
|
|
}
|
|
|
|
//Is the bottom of the dungeon at Y >= 0?
|
|
if (destY < entranceY)
|
|
{
|
|
destY = entranceY;
|
|
}
|
|
return destY;
|
|
}
|
|
|
|
private static boolean hasValidDimensions(DungeonSchematic dungeon)
|
|
{
|
|
return (dungeon.getWidth() <= DungeonHelper.MAX_DUNGEON_WIDTH &&
|
|
dungeon.getHeight() <= DungeonHelper.MAX_DUNGEON_HEIGHT &&
|
|
dungeon.getLength() <= DungeonHelper.MAX_DUNGEON_LENGTH);
|
|
}
|
|
|
|
private static DungeonSchematic checkSourceAndLoad(String schematicPath) throws FileNotFoundException, InvalidSchematicException
|
|
{
|
|
//TODO: Change this code once we introduce an isInternal flag in dungeon data
|
|
DungeonSchematic dungeon;
|
|
if ((new File(schematicPath)).exists())
|
|
{
|
|
dungeon = DungeonSchematic.readFromFile(schematicPath);
|
|
}
|
|
else
|
|
{
|
|
dungeon = DungeonSchematic.readFromResource(schematicPath);
|
|
}
|
|
return dungeon;
|
|
}
|
|
} |