package mcjty.rftools.dimension;
import io.netty.buffer.ByteBuf;
import mcjty.lib.network.NetworkTools;
import mcjty.lib.varia.BlockMeta;
import mcjty.lib.varia.Coordinate;
import mcjty.lib.varia.Logging;
import mcjty.rftools.blocks.RFToolsTools;
import mcjty.rftools.blocks.dimlets.DimletConfiguration;
import mcjty.rftools.dimension.description.*;
import mcjty.rftools.dimension.world.types.*;
import mcjty.rftools.items.dimlets.*;
import mcjty.rftools.items.dimlets.types.IDimletType;
import mcjty.rftools.items.dimlets.types.Patreons;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.util.Constants;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class DimensionInformation {
private final DimensionDescriptor descriptor;
private String name;
private String ownerName;
private UUID owner;
private Coordinate spawnPoint = null;
private int probeCounter = 0;
private long forcedDimensionSeed = 0; // Seed was forced using a seed dimlet.
private long baseSeed = 0; // World seed we start to generate own seed from.
private int worldVersion = VERSION_OLD; // Used for compatilibity checking between generated worlds.
public static final int VERSION_OLD = 0; // Old version of worlds. Seed is incorrect.
public static final int VERSION_CORRECTSEED = 1; // New version of worlds. Seed is correct.
private TerrainType terrainType = TerrainType.TERRAIN_VOID;
private BlockMeta baseBlockForTerrain = null;
private Block fluidForTerrain = null;
private BlockMeta tendrilBlock = null;
private BlockMeta canyonBlock = null;
private BlockMeta[] pyramidBlocks = new BlockMeta[] { BlockMeta.STONE };
private BlockMeta[] sphereBlocks = new BlockMeta[] { BlockMeta.STONE };
private BlockMeta[] hugeSphereBlocks = new BlockMeta[] { BlockMeta.STONE };
private BlockMeta[] liquidSphereBlocks = new BlockMeta[] { BlockMeta.STONE };
private Block[] liquidSphereFluids = new Block[] { Blocks.water };
private BlockMeta[] hugeLiquidSphereBlocks = new BlockMeta[] { BlockMeta.STONE };
private Block[] hugeLiquidSphereFluids = new Block[] { Blocks.water };
private BlockMeta[] extraOregen = new BlockMeta[] {};
private Block[] fluidsForLakes = new Block[] {};
private List<MobDescriptor> extraMobs = new ArrayList<MobDescriptor>();
private boolean peaceful = false;
private boolean noanimals = false;
private boolean shelter = false;
private boolean respawnHere = false;
private Set<FeatureType> featureTypes = new HashSet<FeatureType>();
private Set<StructureType> structureTypes = new HashSet<StructureType>();
private Set<EffectType> effectTypes = new HashSet<EffectType>();
private ControllerType controllerType = null;
private List<BiomeGenBase> biomes = new ArrayList<BiomeGenBase>();
private static final Map<Integer, Integer> biomeMapping = new HashMap<Integer, Integer>();
private String digitString = "";
private Float celestialAngle = null;
private Float timeSpeed = null;
private SkyDescriptor skyDescriptor;
private List<CelestialBodyDescriptor> celestialBodyDescriptors;
// Patreon effects.
private long patreon1 = 0;
private String[] dimensionTypes = new String[0]; // Used for Recurrent Complex if that's present.
private WeatherDescriptor weatherDescriptor;
// The actual RF cost after taking into account the features we got in our world.
private int actualRfCost;
public DimensionInformation(String name, DimensionDescriptor descriptor, World world, String playerName, UUID player) {
this.name = name;
this.descriptor = descriptor;
this.ownerName = playerName;
this.owner = player;
this.forcedDimensionSeed = descriptor.getForcedSeed();
if (DimletConfiguration.randomizeSeed) {
baseSeed = (long) (Math.random() * 10000 + 1);
} else {
baseSeed = world.getSeed();
}
worldVersion = VERSION_CORRECTSEED;
setupFromDescriptor(world.getSeed());
setupBiomeMapping();
dump(null);
}
private void setupFromDescriptor(long seed) {
List<Pair<DimletKey,List<DimletKey>>> dimlets = descriptor.getDimletsWithModifiers();
Random random = new Random(descriptor.calculateSeed(seed));
actualRfCost = 0;
DimletType.DIMLET_PATREON.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_TERRAIN.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_FEATURE.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_STRUCTURE.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_BIOME.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_DIGIT.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_SKY.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_MOBS.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_SPECIAL.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_TIME.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_EFFECT.dimletType.constructDimension(dimlets, random, this);
DimletType.DIMLET_WEATHER.dimletType.constructDimension(dimlets, random, this);
actualRfCost += descriptor.getRfMaintainCost();
}
public String loadFromJson(String filename) {
File file = new File(filename);
String json;
try {
json = FileUtils.readFileToString(file);
} catch (IOException e) {
return "Error reading file!";
}
NBTTagCompound tagCompound;
try {
tagCompound = (NBTTagCompound) JsonToNBT.func_150315_a(json);
} catch (NBTException e) {
return "NBT Error: " + e.getMessage();
}
readFromNBT(tagCompound);
return null;
}
public String buildJson(String filename) {
NBTTagCompound tagCompound = new NBTTagCompound();
writeToNBT(tagCompound);
StringBuffer buffer = new StringBuffer();
buffer.append("{\n");
RFToolsTools.convertNBTtoJson(buffer, tagCompound, 4);
buffer.append("}");
String json = buffer.toString();
// String json = tagCompound.toString();
try {
FileWriter writer = new FileWriter(filename);
writer.write(json);
writer.close();
} catch (IOException e) {
return "Error writing file!";
}
return null;
}
public void injectDimlet(DimletKey key) {
DimletType type = key.getType();
IDimletType itype = type.dimletType;
if (itype.isInjectable()) {
addToCost(key);
itype.inject(key, this);
}
}
public DimensionInformation(DimensionDescriptor descriptor, NBTTagCompound tagCompound) {
this.name = tagCompound.getString("name");
this.ownerName = tagCompound.getString("owner");
if (tagCompound.hasKey("ownerM")) {
this.owner = new UUID(tagCompound.getLong("ownerM"), tagCompound.getLong("ownerL"));
} else {
this.owner = null;
}
this.descriptor = descriptor;
setSpawnPoint(Coordinate.readFromNBT(tagCompound, "spawnPoint"));
setProbeCounter(tagCompound.getInteger("probeCounter"));
int version = tagCompound.getInteger("version");
if (version == 1) {
// This version of the dimension information has the random information persisted.
setupFromNBT(tagCompound);
} else {
// This is an older version. Here we have to calculate the random information again.
setupFromDescriptor(1);
}
setupBiomeMapping();
}
public void readFromNBT(NBTTagCompound tagCompound) {
this.name = tagCompound.getString("name");
this.ownerName = tagCompound.getString("owner");
if (tagCompound.hasKey("ownerM")) {
this.owner = new UUID(tagCompound.getLong("ownerM"), tagCompound.getLong("ownerL"));
} else {
this.owner = null;
}
setSpawnPoint(Coordinate.readFromNBT(tagCompound, "spawnPoint"));
setProbeCounter(tagCompound.getInteger("probeCounter"));
setupFromNBT(tagCompound);
setupBiomeMapping();
}
public static int[] getIntArraySafe(NBTTagCompound tagCompound, String name) {
if (!tagCompound.hasKey(name)) {
return new int[0];
}
NBTBase tag = tagCompound.getTag(name);
if (tag instanceof NBTTagIntArray) {
return tagCompound.getIntArray(name);
} else {
return new int[0];
}
}
private void setupFromNBT(NBTTagCompound tagCompound) {
terrainType = TerrainType.values()[tagCompound.getInteger("terrain")];
featureTypes = toEnumSet(getIntArraySafe(tagCompound, "features"), FeatureType.values());
structureTypes = toEnumSet(getIntArraySafe(tagCompound, "structures"), StructureType.values());
effectTypes = toEnumSet(getIntArraySafe(tagCompound, "effects"), EffectType.values());
biomes.clear();
for (int a : getIntArraySafe(tagCompound, "biomes")) {
BiomeGenBase biome = BiomeGenBase.getBiome(a);
if (biome != null) {
biomes.add(biome);
} else {
// Protect against deleted biomes (i.e. a mod with biomes gets removed and this dimension still uses it).
// We will pick a replacement biome here.
biomes.add(BiomeGenBase.plains);
}
}
if (tagCompound.hasKey("controller")) {
controllerType = ControllerType.values()[tagCompound.getInteger("controller")];
} else {
// Support for old type.
if (biomes.isEmpty()) {
controllerType = ControllerType.CONTROLLER_DEFAULT;
} else {
controllerType = ControllerType.CONTROLLER_SINGLE;
}
}
digitString = tagCompound.getString("digits");
forcedDimensionSeed = tagCompound.getLong("forcedSeed");
baseSeed = tagCompound.getLong("baseSeed");
worldVersion = tagCompound.getInteger("worldVersion");
baseBlockForTerrain = getBlockMeta(tagCompound, "baseBlock");
tendrilBlock = getBlockMeta(tagCompound, "tendrilBlock");
canyonBlock = getBlockMeta(tagCompound, "canyonBlock");
fluidForTerrain = (Block) Block.blockRegistry.getObjectById(tagCompound.getInteger("fluidBlock"));
hugeLiquidSphereFluids = readFluidsFromNBT(tagCompound, "hugeLiquidSphereFluids");
hugeLiquidSphereBlocks = readBlockArrayFromNBT(tagCompound, "hugeLiquidSphereBlocks");
// Support for the old format with only one liquid block.
Block oldLiquidSphereFluid = (Block) Block.blockRegistry.getObjectById(tagCompound.getInteger("liquidSphereFluid"));
liquidSphereFluids = readFluidsFromNBT(tagCompound, "liquidSphereFluids");
if (liquidSphereFluids.length == 0) {
liquidSphereFluids = new Block[] { oldLiquidSphereFluid };
}
// Support for the old format with only one sphere block.
BlockMeta oldLiquidSphereBlock = getBlockMeta(tagCompound, "liquidSphereBlock");
liquidSphereBlocks = readBlockArrayFromNBT(tagCompound, "liquidSphereBlocks");
if (liquidSphereBlocks.length == 0) {
liquidSphereBlocks = new BlockMeta[] { oldLiquidSphereBlock };
}
pyramidBlocks = readBlockArrayFromNBT(tagCompound, "pyramidBlocks");
if (pyramidBlocks.length == 0) {
pyramidBlocks = new BlockMeta[] { BlockMeta.STONE };
}
// Support for the old format with only one sphere block.
BlockMeta oldSphereBlock = getBlockMeta(tagCompound, "sphereBlock");
sphereBlocks = readBlockArrayFromNBT(tagCompound, "sphereBlocks");
if (sphereBlocks.length == 0) {
sphereBlocks = new BlockMeta[] { oldSphereBlock };
}
hugeSphereBlocks = readBlockArrayFromNBT(tagCompound, "hugeSphereBlocks");
extraOregen = readBlockArrayFromNBT(tagCompound, "extraOregen");
fluidsForLakes = readFluidsFromNBT(tagCompound, "lakeFluids");
peaceful = tagCompound.getBoolean("peaceful");
noanimals = tagCompound.getBoolean("noanimals");
shelter = tagCompound.getBoolean("shelter");
respawnHere = tagCompound.getBoolean("respawnHere");
if (tagCompound.hasKey("celestialAngle")) {
celestialAngle = tagCompound.getFloat("celestialAngle");
} else {
celestialAngle = null;
}
if (tagCompound.hasKey("timeSpeed")) {
timeSpeed = tagCompound.getFloat("timeSpeed");
} else {
timeSpeed = null;
}
probeCounter = tagCompound.getInteger("probes");
actualRfCost = tagCompound.getInteger("actualCost");
skyDescriptor = new SkyDescriptor.Builder().fromNBT(tagCompound).build();
calculateCelestialBodyDescriptors();
patreon1 = tagCompound.getLong("patreon1");
weatherDescriptor = new WeatherDescriptor.Builder().fromNBT(tagCompound).build();
extraMobs.clear();
NBTTagList list = tagCompound.getTagList("mobs", Constants.NBT.TAG_COMPOUND);
for (int i = 0 ; i < list.tagCount() ; i++) {
NBTTagCompound tc = list.getCompoundTagAt(i);
String className = tc.getString("class");
int chance = tc.getInteger("chance");
int minGroup = tc.getInteger("minGroup");
int maxGroup = tc.getInteger("maxGroup");
int maxLoaded = tc.getInteger("maxLoaded");
Class<? extends EntityLiving> c = null;
try {
c = (Class<? extends EntityLiving>) Class.forName(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
MobDescriptor mob = new MobDescriptor(null, c, chance, minGroup, maxGroup, maxLoaded);
extraMobs.add(mob);
}
String ds = tagCompound.getString("dimensionTypes");
dimensionTypes = StringUtils.split(ds, ",");
if (dimensionTypes == null) {
dimensionTypes = new String[0];
}
}
private Block[] readFluidsFromNBT(NBTTagCompound tagCompound, String name) {
List<Block> fluids = new ArrayList<Block>();
for (int a : getIntArraySafe(tagCompound, name)) {
fluids.add((Block) Block.blockRegistry.getObjectById(a));
}
return fluids.toArray(new Block[fluids.size()]);
}
private static BlockMeta[] readBlockArrayFromNBT(NBTTagCompound tagCompound, String name) {
List<BlockMeta> blocks = new ArrayList<BlockMeta>();
int[] blockIds = getIntArraySafe(tagCompound, name);
int[] metas = getIntArraySafe(tagCompound, name + "_meta");
for (int i = 0 ; i < blockIds.length ; i++) {
int id = blockIds[i];
Block block = (Block) Block.blockRegistry.getObjectById(id);
int meta = 0;
if (i < metas.length) {
meta = metas[i];
}
blocks.add(new BlockMeta(block, meta));
}
return blocks.toArray(new BlockMeta[blocks.size()]);
}
private BlockMeta getBlockMeta(NBTTagCompound tagCompound, String name) {
Block block = (Block) Block.blockRegistry.getObjectById(tagCompound.getInteger(name));
int meta = tagCompound.getInteger(name + "_meta");
return new BlockMeta(block, meta);
}
public void writeToNBT(NBTTagCompound tagCompound) {
tagCompound.setString("name", getName());
tagCompound.setString("owner", ownerName);
if (owner != null) {
tagCompound.setLong("ownerM", owner.getMostSignificantBits());
tagCompound.setLong("ownerL", owner.getLeastSignificantBits());
}
Coordinate spawnPoint = getSpawnPoint();
if (spawnPoint != null) {
Coordinate.writeToNBT(tagCompound, "spawnPoint", spawnPoint);
}
tagCompound.setInteger("probeCounter", getProbeCounter());
tagCompound.setInteger("version", 1); // Version number so that we can detect incompatible changes in persisted dimension information objects.
tagCompound.setInteger("terrain", terrainType == null ? TerrainType.TERRAIN_VOID.ordinal() : terrainType.ordinal());
tagCompound.setIntArray("features", toIntArray(featureTypes));
tagCompound.setIntArray("structures", toIntArray(structureTypes));
tagCompound.setIntArray("effects", toIntArray(effectTypes));
List<Integer> c = new ArrayList<Integer>(biomes.size());
for (BiomeGenBase t : biomes) {
if (t != null) {
c.add(t.biomeID);
} else {
c.add(BiomeGenBase.plains.biomeID);
}
}
tagCompound.setIntArray("biomes", ArrayUtils.toPrimitive(c.toArray(new Integer[c.size()])));
tagCompound.setInteger("controller", controllerType == null ? ControllerType.CONTROLLER_DEFAULT.ordinal() : controllerType.ordinal());
tagCompound.setString("digits", digitString);
tagCompound.setLong("forcedSeed", forcedDimensionSeed);
tagCompound.setLong("baseSeed", baseSeed);
tagCompound.setInteger("worldVersion", worldVersion);
setBlockMeta(tagCompound, baseBlockForTerrain, "baseBlock");
setBlockMeta(tagCompound, tendrilBlock, "tendrilBlock");
writeBlocksToNBT(tagCompound, pyramidBlocks, "pyramidBlocks");
writeBlocksToNBT(tagCompound, sphereBlocks, "sphereBlocks");
if (sphereBlocks.length > 0) {
// Write out a single sphere block for compatibility with older RFTools.
setBlockMeta(tagCompound, sphereBlocks[0], "sphereBlock");
}
writeBlocksToNBT(tagCompound, hugeSphereBlocks, "hugeSphereBlocks");
writeBlocksToNBT(tagCompound, hugeLiquidSphereBlocks, "hugeLiquidSphereBlocks");
writeFluidsToNBT(tagCompound, hugeLiquidSphereFluids, "hugeLiquidSphereFluids");
writeBlocksToNBT(tagCompound, liquidSphereBlocks, "liquidSphereBlocks");
if (liquidSphereBlocks.length > 0) {
// Write out a single sphere block for compatibility with older RFTools.
setBlockMeta(tagCompound, liquidSphereBlocks[0], "liquidSphereBlock");
}
writeFluidsToNBT(tagCompound, liquidSphereFluids, "liquidSphereFluids");
if (liquidSphereFluids.length > 0) {
tagCompound.setInteger("liquidSphereFluid", Block.blockRegistry.getIDForObject(liquidSphereFluids[0]));
}
setBlockMeta(tagCompound, canyonBlock, "canyonBlock");
tagCompound.setInteger("fluidBlock", Block.blockRegistry.getIDForObject(fluidForTerrain));
writeBlocksToNBT(tagCompound, extraOregen, "extraOregen");
writeFluidsToNBT(tagCompound, fluidsForLakes, "lakeFluids");
tagCompound.setBoolean("peaceful", peaceful);
tagCompound.setBoolean("noanimals", noanimals);
tagCompound.setBoolean("shelter", shelter);
tagCompound.setBoolean("respawnHere", respawnHere);
if (celestialAngle != null) {
tagCompound.setFloat("celestialAngle", celestialAngle);
}
if (timeSpeed != null) {
tagCompound.setFloat("timeSpeed", timeSpeed);
}
tagCompound.setInteger("probes", probeCounter);
tagCompound.setInteger("actualCost", actualRfCost);
skyDescriptor.writeToNBT(tagCompound);
weatherDescriptor.writeToNBT(tagCompound);
tagCompound.setLong("patreon1", patreon1);
NBTTagList list = new NBTTagList();
for (MobDescriptor mob : extraMobs) {
NBTTagCompound tc = new NBTTagCompound();
if (mob != null) {
if (mob.getEntityClass() != null) {
tc.setString("class", mob.getEntityClass().getName());
tc.setInteger("chance", mob.getSpawnChance());
tc.setInteger("minGroup", mob.getMinGroup());
tc.setInteger("maxGroup", mob.getMaxGroup());
tc.setInteger("maxLoaded", mob.getMaxLoaded());
list.appendTag(tc);
}
}
}
tagCompound.setTag("mobs", list);
tagCompound.setString("dimensionTypes", StringUtils.join(dimensionTypes, ","));
}
private void setBlockMeta(NBTTagCompound tagCompound, BlockMeta blockMeta, String name) {
tagCompound.setInteger(name, Block.blockRegistry.getIDForObject(blockMeta.getBlock()));
tagCompound.setInteger(name + "_meta", blockMeta.getMeta());
}
private static void writeFluidsToNBT(NBTTagCompound tagCompound, Block[] fluids, String name) {
List<Integer> c;
c = new ArrayList<Integer>(fluids.length);
for (Block t : fluids) {
c.add(Block.blockRegistry.getIDForObject(t));
}
tagCompound.setIntArray(name, ArrayUtils.toPrimitive(c.toArray(new Integer[c.size()])));
}
private static void writeBlocksToNBT(NBTTagCompound tagCompound, BlockMeta[] blocks, String name) {
List<Integer> ids = new ArrayList<Integer>(blocks.length);
List<Integer> meta = new ArrayList<Integer>(blocks.length);
for (BlockMeta t : blocks) {
ids.add(Block.blockRegistry.getIDForObject(t.getBlock()));
meta.add((int)t.getMeta());
}
tagCompound.setIntArray(name, ArrayUtils.toPrimitive(ids.toArray(new Integer[ids.size()])));
tagCompound.setIntArray(name + "_meta", ArrayUtils.toPrimitive(meta.toArray(new Integer[meta.size()])));
}
private static <T extends Enum> int[] toIntArray(Collection<T> collection) {
List<Integer> c = new ArrayList<Integer>(collection.size());
for (T t : collection) {
c.add(t.ordinal());
}
return ArrayUtils.toPrimitive(c.toArray(new Integer[c.size()]));
}
private static <T extends Enum> Set<T> toEnumSet(int[] arr, T[] values) {
Set<T> list = new HashSet<T>();
for (int a : arr) {
list.add(values[a]);
}
return list;
}
private void logDebug(EntityPlayer player, String message) {
if (player == null) {
Logging.log(message);
} else {
Logging.message(player, EnumChatFormatting.YELLOW + message);
}
}
public void dump(EntityPlayer player) {
String digits = getDigitString();
if (!digits.isEmpty()) {
logDebug(player, " Digits: " + digits);
}
if (forcedDimensionSeed != 0) {
logDebug(player, " Forced seed: " + forcedDimensionSeed);
}
if (baseSeed != 0) {
logDebug(player, " Base seed: " + baseSeed);
}
logDebug(player, " World version: " + worldVersion);
TerrainType terrainType = getTerrainType();
logDebug(player, " Terrain: " + terrainType.toString());
logDebug(player, " Base block: " + new ItemStack(baseBlockForTerrain.getBlock(), 1, baseBlockForTerrain.getMeta()).getDisplayName());
if (featureTypes.contains(FeatureType.FEATURE_TENDRILS)) {
logDebug(player, " Tendril block: " + new ItemStack(tendrilBlock.getBlock(), 1, tendrilBlock.getMeta()).getDisplayName());
}
if (featureTypes.contains(FeatureType.FEATURE_PYRAMIDS)) {
for (BlockMeta block : pyramidBlocks) {
if (block != null) {
logDebug(player, " Pyramid blocks: " + new ItemStack(block.getBlock(), 1, block.getMeta()).getDisplayName());
}
}
}
if (featureTypes.contains(FeatureType.FEATURE_ORBS)) {
for (BlockMeta block : sphereBlocks) {
if (block != null) {
logDebug(player, " Orb blocks: " + new ItemStack(block.getBlock(), 1, block.getMeta()).getDisplayName());
}
}
}
if (featureTypes.contains(FeatureType.FEATURE_HUGEORBS)) {
for (BlockMeta block : hugeSphereBlocks) {
if (block != null) {
logDebug(player, " Huge Orb blocks: " + new ItemStack(block.getBlock(), 1, block.getMeta()).getDisplayName());
}
}
}
if (featureTypes.contains(FeatureType.FEATURE_LIQUIDORBS)) {
for (BlockMeta block : liquidSphereBlocks) {
if (block != null) {
logDebug(player, " Liquid Orb blocks: " + new ItemStack(block.getBlock(), 1, block.getMeta()).getDisplayName());
}
}
}
if (featureTypes.contains(FeatureType.FEATURE_HUGELIQUIDORBS)) {
for (BlockMeta block : hugeLiquidSphereBlocks) {
if (block != null) {
logDebug(player, " Huge Liquid Orb blocks: " + new ItemStack(block.getBlock(), 1, block.getMeta()).getDisplayName());
}
}
}
if (featureTypes.contains(FeatureType.FEATURE_CANYONS)) {
logDebug(player, " Canyon block: " + new ItemStack(canyonBlock.getBlock(), 1, canyonBlock.getMeta()).getDisplayName());
}
logDebug(player, " Base fluid: " + new ItemStack(fluidForTerrain).getDisplayName());
logDebug(player, " Biome controller: " + (controllerType == null ? "<null>" : controllerType.name()));
for (BiomeGenBase biome : getBiomes()) {
if (biome != null) {
logDebug(player, " Biome: " + biome.biomeName);
}
}
for (FeatureType featureType : getFeatureTypes()) {
logDebug(player, " Feature: " + featureType.toString());
}
for (BlockMeta block : extraOregen) {
if (block != null) {
logDebug(player, " Extra ore: " + new ItemStack(block.getBlock(), 1, block.getMeta()).getDisplayName());
}
}
for (Block block : fluidsForLakes) {
logDebug(player, " Lake fluid: " + new ItemStack(block).getDisplayName());
}
if (featureTypes.contains(FeatureType.FEATURE_LIQUIDORBS)) {
for (Block fluid : liquidSphereFluids) {
logDebug(player, " Liquid orb fluids: " + new ItemStack(fluid).getDisplayName());
}
}
if (featureTypes.contains(FeatureType.FEATURE_HUGELIQUIDORBS)) {
for (Block fluid : hugeLiquidSphereFluids) {
logDebug(player, " Huge Liquid orb fluids: " + new ItemStack(fluid).getDisplayName());
}
}
for (StructureType structureType : getStructureTypes()) {
logDebug(player, " Structure: " + structureType.toString());
}
if (structureTypes.contains(StructureType.STRUCTURE_RECURRENTCOMPLEX)) {
for (String type : dimensionTypes) {
logDebug(player, " RR DimensionType: " + type);
}
}
for (EffectType effectType : getEffectTypes()) {
logDebug(player, " Effect: " + effectType.toString());
}
logDebug(player, " Sun brightness: " + skyDescriptor.getSunBrightnessFactor());
logDebug(player, " Star brightness: " + skyDescriptor.getStarBrightnessFactor());
float r = skyDescriptor.getSkyColorFactorR();
float g = skyDescriptor.getSkyColorFactorG();
float b = skyDescriptor.getSkyColorFactorB();
logDebug(player, " Sky color: " + r + ", " + g + ", " + b);
r = skyDescriptor.getFogColorFactorR();
g = skyDescriptor.getFogColorFactorG();
b = skyDescriptor.getFogColorFactorB();
logDebug(player, " Fog color: " + r + ", " + g + ", " + b);
SkyType skyType = skyDescriptor.getSkyType();
if (skyType != SkyType.SKY_NORMAL) {
logDebug(player, " Sky type: " + skyType.toString());
}
for (CelestialBodyType bodyType : skyDescriptor.getCelestialBodies()) {
logDebug(player, " Sky body: " + bodyType.name());
}
if (weatherDescriptor.getRainStrength() > -0.5f) {
logDebug(player, " Weather rain: " + weatherDescriptor.getRainStrength());
}
if (weatherDescriptor.getThunderStrength() > -0.5f) {
logDebug(player, " Weather thunder " + weatherDescriptor.getThunderStrength());
}
for (MobDescriptor mob : extraMobs) {
if (mob != null) {
if (mob.getEntityClass() == null) {
logDebug(player, " Mob: " + mob);
} else {
logDebug(player, " Mob: " + mob.getEntityClass().getName());
}
}
}
if (peaceful) {
logDebug(player, " Peaceful mode");
}
if (noanimals) {
logDebug(player, " No animals mode");
}
if (shelter) {
logDebug(player, " Safe shelter");
}
if (respawnHere) {
logDebug(player, " Respawn local");
}
if (celestialAngle != null) {
logDebug(player, " Celestial angle: " + celestialAngle);
}
if (timeSpeed != null) {
logDebug(player, " Time speed: " + timeSpeed);
}
if (probeCounter > 0) {
logDebug(player, " Probes: " + probeCounter);
}
if (patreon1 != 0) {
logDebug(player, " Patreon: " + patreon1);
}
}
public void toBytes(ByteBuf buf) {
NetworkTools.writeString(buf, ownerName);
if (owner == null) {
buf.writeBoolean(false);
} else {
buf.writeBoolean(true);
buf.writeLong(owner.getMostSignificantBits());
buf.writeLong(owner.getLeastSignificantBits());
}
NetworkTools.writeEnum(buf, terrainType, TerrainType.TERRAIN_VOID);
NetworkTools.writeEnumCollection(buf, featureTypes);
NetworkTools.writeEnumCollection(buf, structureTypes);
NetworkTools.writeEnumCollection(buf, effectTypes);
buf.writeInt(biomes.size());
for (BiomeGenBase entry : biomes) {
if (entry != null) {
buf.writeInt(entry.biomeID);
} else {
buf.writeInt(BiomeGenBase.plains.biomeID);
}
}
NetworkTools.writeEnum(buf, controllerType, ControllerType.CONTROLLER_DEFAULT);
NetworkTools.writeString(buf, digitString);
buf.writeLong(forcedDimensionSeed);
buf.writeLong(baseSeed);
buf.writeInt(worldVersion);
buf.writeInt(Block.blockRegistry.getIDForObject(baseBlockForTerrain.getBlock()));
buf.writeInt(baseBlockForTerrain.getMeta());
buf.writeInt(Block.blockRegistry.getIDForObject(tendrilBlock.getBlock()));
buf.writeInt(tendrilBlock.getMeta());
writeBlockArrayToBuf(buf, pyramidBlocks);
writeBlockArrayToBuf(buf, sphereBlocks);
writeBlockArrayToBuf(buf, hugeSphereBlocks);
writeBlockArrayToBuf(buf, liquidSphereBlocks);
writeFluidArrayToBuf(buf, liquidSphereFluids);
writeBlockArrayToBuf(buf, hugeLiquidSphereBlocks);
writeFluidArrayToBuf(buf, hugeLiquidSphereFluids);
buf.writeInt(Block.blockRegistry.getIDForObject(canyonBlock.getBlock()));
buf.writeInt(canyonBlock.getMeta());
buf.writeInt(Block.blockRegistry.getIDForObject(fluidForTerrain));
writeBlockArrayToBuf(buf, extraOregen);
writeFluidArrayToBuf(buf, fluidsForLakes);
buf.writeBoolean(peaceful);
buf.writeBoolean(noanimals);
buf.writeBoolean(shelter);
buf.writeBoolean(respawnHere);
NetworkTools.writeFloat(buf, celestialAngle);
NetworkTools.writeFloat(buf, timeSpeed);
buf.writeInt(probeCounter);
buf.writeInt(actualRfCost);
skyDescriptor.toBytes(buf);
weatherDescriptor.toBytes(buf);
buf.writeLong(patreon1);
buf.writeInt(extraMobs.size());
for (MobDescriptor mob : extraMobs) {
if (mob != null) {
if (mob.getEntityClass() != null) {
NetworkTools.writeString(buf, mob.getEntityClass().getName());
buf.writeInt(mob.getSpawnChance());
buf.writeInt(mob.getMinGroup());
buf.writeInt(mob.getMaxGroup());
buf.writeInt(mob.getMaxLoaded());
}
}
}
buf.writeInt(dimensionTypes.length);
for (String type : dimensionTypes) {
NetworkTools.writeString(buf, type);
}
}
private static void writeFluidArrayToBuf(ByteBuf buf, Block[] fluids) {
buf.writeInt(fluids.length);
for (Block block : fluids) {
buf.writeInt(Block.blockRegistry.getIDForObject(block));
}
}
private static void writeBlockArrayToBuf(ByteBuf buf, BlockMeta[] array) {
buf.writeInt(array.length);
for (BlockMeta block : array) {
buf.writeInt(Block.blockRegistry.getIDForObject(block.getBlock()));
buf.writeInt(block.getMeta());
}
}
public DimensionInformation(String name, DimensionDescriptor descriptor, ByteBuf buf) {
this.name = name;
this.descriptor = descriptor;
ownerName = NetworkTools.readString(buf);
if (buf.readBoolean()) {
owner = new UUID(buf.readLong(), buf.readLong());
} else {
owner = null;
}
terrainType = NetworkTools.readEnum(buf, TerrainType.values());
NetworkTools.readEnumCollection(buf, featureTypes, FeatureType.values());
NetworkTools.readEnumCollection(buf, structureTypes, StructureType.values());
NetworkTools.readEnumCollection(buf, effectTypes, EffectType.values());
biomes.clear();
int size = buf.readInt();
for (int i = 0 ; i < size ; i++) {
BiomeGenBase biome = BiomeGenBase.getBiome(buf.readInt());
if (biome != null) {
biomes.add(biome);
} else {
biomes.add(BiomeGenBase.plains);
}
}
controllerType = NetworkTools.readEnum(buf, ControllerType.values());
digitString = NetworkTools.readString(buf);
forcedDimensionSeed = buf.readLong();
baseSeed = buf.readLong();
worldVersion = buf.readInt();
Block block = (Block) Block.blockRegistry.getObjectById(buf.readInt());
int meta = buf.readInt();
baseBlockForTerrain = new BlockMeta(block, meta);
block = (Block) Block.blockRegistry.getObjectById(buf.readInt());
meta = buf.readInt();
tendrilBlock = new BlockMeta(block, meta);
pyramidBlocks = readBlockArrayFromBuf(buf);
sphereBlocks = readBlockArrayFromBuf(buf);
hugeSphereBlocks = readBlockArrayFromBuf(buf);
liquidSphereBlocks = readBlockArrayFromBuf(buf);
liquidSphereFluids = readFluidArrayFromBuf(buf);
hugeLiquidSphereBlocks = readBlockArrayFromBuf(buf);
hugeLiquidSphereFluids = readFluidArrayFromBuf(buf);
block = (Block) Block.blockRegistry.getObjectById(buf.readInt());
meta = buf.readInt();
canyonBlock = new BlockMeta(block, meta);
fluidForTerrain = (Block) Block.blockRegistry.getObjectById(buf.readInt());
extraOregen = readBlockArrayFromBuf(buf);
fluidsForLakes = readFluidArrayFromBuf(buf);
peaceful = buf.readBoolean();
noanimals = buf.readBoolean();
shelter = buf.readBoolean();
respawnHere = buf.readBoolean();
celestialAngle = NetworkTools.readFloat(buf);
timeSpeed = NetworkTools.readFloat(buf);
probeCounter = buf.readInt();
actualRfCost = buf.readInt();
skyDescriptor = new SkyDescriptor.Builder().fromBytes(buf).build();
calculateCelestialBodyDescriptors();
weatherDescriptor = new WeatherDescriptor.Builder().fromBytes(buf).build();
patreon1 = buf.readLong();
extraMobs.clear();
size = buf.readInt();
for (int i = 0 ; i < size ; i++) {
String className = NetworkTools.readString(buf);
try {
Class<? extends EntityLiving> c = (Class<? extends EntityLiving>) Class.forName(className);
int chance = buf.readInt();
int minGroup = buf.readInt();
int maxGroup = buf.readInt();
int maxLoaded = buf.readInt();
MobDescriptor mob = new MobDescriptor(null, c, chance, minGroup, maxGroup, maxLoaded);
extraMobs.add(mob);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
size = buf.readInt();
dimensionTypes = new String[size];
for (int i = 0 ; i < size ; i++) {
dimensionTypes[i] = NetworkTools.readString(buf);
}
setupBiomeMapping();
}
private static Block[] readFluidArrayFromBuf(ByteBuf buf) {
List<Block> blocks = new ArrayList<Block>();
int size = buf.readInt();
for (int i = 0 ; i < size ; i++) {
blocks.add((Block) Block.blockRegistry.getObjectById(buf.readInt()));
}
return blocks.toArray(new Block[blocks.size()]);
}
private static BlockMeta[] readBlockArrayFromBuf(ByteBuf buf) {
int size = buf.readInt();
List<BlockMeta> blocksMeta = new ArrayList<BlockMeta>();
for (int i = 0 ; i < size ; i++) {
Block b = (Block) Block.blockRegistry.getObjectById(buf.readInt());
int m = buf.readInt();
blocksMeta.add(new BlockMeta(b, m));
}
return blocksMeta.toArray(new BlockMeta[blocksMeta.size()]);
}
public Coordinate getSpawnPoint() {
return spawnPoint;
}
public void setSpawnPoint(Coordinate spawnPoint) {
this.spawnPoint = spawnPoint;
}
public void setSkyDescriptor(SkyDescriptor sd) {
skyDescriptor = sd;
calculateCelestialBodyDescriptors();
}
private void calculateCelestialBodyDescriptors() {
List<CelestialBodyType> celestialBodies = skyDescriptor.getCelestialBodies();
// Find the most suitable sun and moon. This is typically the largest sun in the list of celestial bodies.
int sunidx = -1;
int bestsun = 0;
int moonidx = -1;
int bestmoon = 0;
for (int i = 0 ; i < celestialBodies.size() ; i++) {
CelestialBodyType type = celestialBodies.get(i);
if (type.getGoodSunFactor() > bestsun) {
bestsun = type.getGoodSunFactor();
sunidx = i;
}
if (type.getGoodMoonFactor() > bestmoon) {
bestmoon = type.getGoodMoonFactor();
moonidx = i;
}
}
// Always the same random series.
Random random = new Random(123);
random.nextFloat();
celestialBodyDescriptors = new ArrayList<CelestialBodyDescriptor>();
for (int i = 0 ; i < celestialBodies.size() ; i++) {
CelestialBodyType type = celestialBodies.get(i);
celestialBodyDescriptors.add(new CelestialBodyDescriptor(type, i == sunidx || i == moonidx));
}
}
public static List<Pair<DimletKey,List<DimletKey>>> extractType(DimletType type, List<Pair<DimletKey,List<DimletKey>>> dimlets) {
List<Pair<DimletKey,List<DimletKey>>> result = new ArrayList<Pair<DimletKey, List<DimletKey>>>();
for (Pair<DimletKey, List<DimletKey>> dimlet : dimlets) {
if (dimlet.getLeft().getType() == type) {
result.add(dimlet);
}
}
return result;
}
public void updateCostFactor(DimletKey key) {
actualRfCost += calculateCostFactor(key);
}
private int calculateCostFactor(DimletKey key) {
DimletEntry dimletEntry = KnownDimletConfiguration.getEntry(key);
if (dimletEntry == null) {
Logging.logError("Something went wrong for key: " + key);
return 0;
}
return (int) (dimletEntry.getRfMaintainCost() * DimletConfiguration.afterCreationCostFactor);
}
private void addToCost(DimletKey key) {
DimletEntry dimletEntry = KnownDimletConfiguration.getEntry(key);
int rfMaintainCost = dimletEntry.getRfMaintainCost();
if (rfMaintainCost < 0) {
int nominalCost = descriptor.calculateNominalCost();
int rfMinimum = Math.max(10, nominalCost * DimletConfiguration.minimumCostPercentage / 100);
actualRfCost = actualRfCost - (actualRfCost * (-rfMaintainCost) / 100);
if (actualRfCost < rfMinimum) {
actualRfCost = rfMinimum; // Never consume less then this
}
} else {
actualRfCost += rfMaintainCost;
}
}
public static void getMaterialAndFluidModifiers(List<DimletKey> modifiers, List<BlockMeta> blocks, List<Block> fluids) {
if (modifiers != null) {
for (DimletKey modifier : modifiers) {
if (modifier.getType() == DimletType.DIMLET_MATERIAL) {
BlockMeta block = DimletObjectMapping.idToBlock.get(modifier);
blocks.add(block);
} else if (modifier.getType() == DimletType.DIMLET_LIQUID) {
Block fluid = DimletObjectMapping.idToFluid.get(modifier);
fluids.add(fluid);
}
}
}
}
public BlockMeta getFeatureBlock(Random random, Map<FeatureType, List<DimletKey>> modifiersForFeature, FeatureType featureType) {
BlockMeta block;
if (featureTypes.contains(featureType)) {
List<BlockMeta> blocks = new ArrayList<BlockMeta>();
List<Block> fluids = new ArrayList<Block>();
getMaterialAndFluidModifiers(modifiersForFeature.get(featureType), blocks, fluids);
if (!blocks.isEmpty()) {
block = blocks.get(random.nextInt(blocks.size()));
if (block == null) {
block = BlockMeta.STONE; // This is the default in case None was specified.
}
} else {
// Nothing was specified. With a relatively big chance we use stone. But there is also a chance that the material will be something else.
if (random.nextFloat() < DimletConfiguration.randomFeatureMaterialChance) {
DimletKey key = DimletRandomizer.getRandomMaterialBlock(random, true);
actualRfCost += calculateCostFactor(key);
block = DimletObjectMapping.idToBlock.get(key);
} else {
block = BlockMeta.STONE;
}
}
} else {
block = BlockMeta.STONE;
}
return block;
}
private void setupBiomeMapping() {
biomeMapping.clear();
if (controllerType == ControllerType.CONTROLLER_FILTERED) {
BiomeGenBase[] biomeGenArray = BiomeGenBase.getBiomeGenArray();
final Set<Integer> ids = new HashSet<Integer>();
for (BiomeGenBase biome : biomes) {
if (biome != null) {
ids.add(biome.biomeID);
} else {
ids.add(BiomeGenBase.plains.biomeID);
}
}
ControllerType.BiomeFilter biomeFilter = new ControllerType.BiomeFilter() {
@Override
public boolean match(BiomeGenBase biome) {
return ids.contains(biome.biomeID);
}
@Override
public double calculateBiomeDistance(BiomeGenBase a, BiomeGenBase b) {
return calculateBiomeDistance(a, b, false, false, false);
}
};
BiomeControllerMapping.makeFilteredBiomeMap(biomeGenArray, biomeMapping, biomeFilter);
}
}
public DimensionDescriptor getDescriptor() {
return descriptor;
}
public String getOwnerName() {
return ownerName;
}
public UUID getOwner() {
return owner;
}
public void setOwner(String name, UUID o) {
ownerName = name;
owner = o;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public TerrainType getTerrainType() {
return terrainType;
}
public void setTerrainType(TerrainType type) {
terrainType = type;
}
public boolean hasFeatureType(FeatureType type) {
return featureTypes.contains(type);
}
public Set<FeatureType> getFeatureTypes() {
return featureTypes;
}
public boolean hasStructureType(StructureType type) {
return structureTypes.contains(type);
}
public Set<StructureType> getStructureTypes() {
return structureTypes;
}
public boolean hasEffectType(EffectType type) {
return effectTypes.contains(type);
}
public Set<EffectType> getEffectTypes() {
return effectTypes;
}
public List<BiomeGenBase> getBiomes() {
return biomes;
}
public Map<Integer, Integer> getBiomeMapping() {
if (biomeMapping.isEmpty()) {
setupBiomeMapping();
}
return biomeMapping;
}
public ControllerType getControllerType() {
return controllerType;
}
public void setControllerType(ControllerType controllerType) {
this.controllerType = controllerType;
}
public String getDigitString() {
return digitString;
}
public void setDigitString(String digitString) {
this.digitString = digitString;
}
public BlockMeta getBaseBlockForTerrain() {
return baseBlockForTerrain;
}
public void setBaseBlockForTerrain(BlockMeta blockMeta) { baseBlockForTerrain = blockMeta; }
public BlockMeta getTendrilBlock() {
return tendrilBlock;
}
public void setTendrilBlock(BlockMeta block) {
tendrilBlock = block;
}
public BlockMeta getCanyonBlock() {
return canyonBlock;
}
public void setCanyonBlock(BlockMeta canyonBlock) {
this.canyonBlock = canyonBlock;
}
public BlockMeta[] getPyramidBlocks() {
return pyramidBlocks;
}
public void setPyramidBlocks(BlockMeta[] pyramidBlocks) {
this.pyramidBlocks = pyramidBlocks;
}
public BlockMeta[] getSphereBlocks() {
return sphereBlocks;
}
public void setSphereBlocks(BlockMeta[] sphereBlocks) {
this.sphereBlocks = sphereBlocks;
}
public BlockMeta[] getHugeSphereBlocks() {
return hugeSphereBlocks;
}
public void setHugeSphereBlocks(BlockMeta[] hugeSphereBlocks) {
this.hugeSphereBlocks = hugeSphereBlocks;
}
public BlockMeta[] getLiquidSphereBlocks() {
return liquidSphereBlocks;
}
public void setLiquidSphereBlocks(BlockMeta[] liquidSphereBlocks) {
this.liquidSphereBlocks = liquidSphereBlocks;
}
public Block[] getLiquidSphereFluids() {
return liquidSphereFluids;
}
public void setLiquidSphereFluids(Block[] liquidSphereFluids) {
this.liquidSphereFluids = liquidSphereFluids;
}
public BlockMeta[] getHugeLiquidSphereBlocks() {
return hugeLiquidSphereBlocks;
}
public void setHugeLiquidSphereBlocks(BlockMeta[] hugeLiquidSphereBlocks) {
this.hugeLiquidSphereBlocks = hugeLiquidSphereBlocks;
}
public Block[] getHugeLiquidSphereFluids() {
return hugeLiquidSphereFluids;
}
public void setHugeLiquidSphereFluids(Block[] hugeLiquidSphereFluids) {
this.hugeLiquidSphereFluids = hugeLiquidSphereFluids;
}
public BlockMeta[] getExtraOregen() {
return extraOregen;
}
public void setExtraOregen(BlockMeta[] blocks) {
extraOregen = blocks;
}
public Block getFluidForTerrain() {
return fluidForTerrain;
}
public void setFluidForTerrain(Block block) { fluidForTerrain = block; }
public Block[] getFluidsForLakes() {
return fluidsForLakes;
}
public void setFluidsForLakes(Block[] blocks) {
fluidsForLakes = blocks;
}
public SkyDescriptor getSkyDescriptor() {
return skyDescriptor;
}
public WeatherDescriptor getWeatherDescriptor() {
return weatherDescriptor;
}
public void setWeatherDescriptor(WeatherDescriptor weatherDescriptor) {
this.weatherDescriptor = weatherDescriptor;
}
public List<CelestialBodyDescriptor> getCelestialBodyDescriptors() {
return celestialBodyDescriptors;
}
public String[] getDimensionTypes() {
return dimensionTypes;
}
public void setDimensionTypes(String[] dimensionTypes) {
this.dimensionTypes = dimensionTypes;
}
public List<MobDescriptor> getExtraMobs() {
return extraMobs;
}
public boolean isPeaceful() {
return peaceful;
}
public void setPeaceful(boolean peaceful) {
this.peaceful = peaceful;
}
public boolean isNoanimals() {
return noanimals;
}
public void setNoanimals(boolean noanimals) {
this.noanimals = noanimals;
}
public long getPatreon1() {
return patreon1;
}
public boolean isPatreonBitSet(Patreons patreon) {
return (patreon1 & (1L << patreon.getBit())) != 0;
}
public void setPatreon1(long patreon1) {
this.patreon1 = patreon1;
}
public void setPatreonBit(Patreons patreon) {
patreon1 |= (1L << patreon.getBit());
}
public boolean isShelter() {
return shelter;
}
public void setShelter(boolean shelter) {
this.shelter = shelter;
}
public boolean isRespawnHere() {
return respawnHere;
}
public void setRespawnHere(boolean respawnHere) {
this.respawnHere = respawnHere;
}
public Float getCelestialAngle() {
return celestialAngle;
}
public Float getTimeSpeed() {
return timeSpeed;
}
public void setCelestialAngle(Float celestialAngle) {
this.celestialAngle = celestialAngle;
}
public void setTimeSpeed(Float timeSpeed) {
this.timeSpeed = timeSpeed;
}
public void addProbe() {
probeCounter++;
}
public void removeProbe() {
probeCounter--;
if (probeCounter < 0) {
probeCounter = 0;
}
}
public int getProbeCounter() {
return probeCounter;
}
public void setProbeCounter(int probeCounter) {
this.probeCounter = probeCounter;
}
public int getActualRfCost() {
return actualRfCost;
}
public long getForcedDimensionSeed() {
return forcedDimensionSeed;
}
public long getBaseSeed() {
return baseSeed;
}
public int getWorldVersion() {
return worldVersion;
}
}