Added configurable loot tables

Added NBT support to fillers
Fixed automatic detection of WarpDrive provided dimensions
Fixed Celestial object render attributes not read properly
Refactored FillerSet and FillerManager into GenericSet and
GenericSetManager
This commit is contained in:
LemADEC 2017-05-23 13:56:35 +02:00
parent 70692f4dbe
commit 6e7aafabcd
34 changed files with 785 additions and 543 deletions

View file

@ -1,9 +1,10 @@
package cr0s.warpdrive.config;
package cr0s.warpdrive.api;
import cr0s.warpdrive.api.IStringSerializable;
import cr0s.warpdrive.config.InvalidXmlException;
import org.w3c.dom.Element;
public interface IXmlRepresentable extends IStringSerializable {
// Load the XML element, return true if successful
boolean loadFromXmlElement(Element element) throws InvalidXmlException;
}

View file

@ -0,0 +1,6 @@
package cr0s.warpdrive.api;
public interface IXmlRepresentableUnit extends IXmlRepresentable {
IXmlRepresentableUnit constructor();
}

View file

@ -62,6 +62,7 @@ public class CelestialObjectManager extends XmlFileManager {
// check overlapping regions
for (CelestialObject celestialObject1 : celestialObjects) {
celestialObject1.lateUpdate();
for (CelestialObject celestialObject2 : celestialObjects) {
if (celestialObject1 == celestialObject2) {
continue;

View file

@ -0,0 +1,120 @@
package cr0s.warpdrive.config;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IXmlRepresentableUnit;
import cr0s.warpdrive.data.JumpBlock;
import org.w3c.dom.Element;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTException;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
/**
* Represents a single filler block.
**/
public class Filler implements IXmlRepresentableUnit {
public static final Filler DEFAULT;
static {
DEFAULT = new Filler();
DEFAULT.name = "-default-";
DEFAULT.block = Blocks.air;
DEFAULT.metadata = 0;
DEFAULT.nbtTagCompound = null;
}
private String name;
public Block block;
public int metadata;
public NBTTagCompound nbtTagCompound = null;
@Override
public String getName() {
return name;
}
public Filler() {
}
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
// Check there is a block name
if (!element.hasAttribute("block")) {
throw new InvalidXmlException("Filler " + element + " is missing a block attribute!");
}
String nameBlock = element.getAttribute("block");
block = Block.getBlockFromName(nameBlock);
if (block == null) {
WarpDrive.logger.warn("Skipping missing block " + nameBlock);
return false;
}
// Get metadata attribute, defaults to 0
metadata = 0;
String stringMetadata = element.getAttribute("metadata");
if (!stringMetadata.isEmpty()) {
try {
metadata = Integer.parseInt(stringMetadata);
} catch (NumberFormatException exception) {
throw new InvalidXmlException("Invalid metadata for block " + nameBlock);
}
}
// Get nbt attribute, default to null/none
nbtTagCompound = null;
String stringNBT = element.getAttribute("nbt");
if (!stringNBT.isEmpty()) {
try {
nbtTagCompound = (NBTTagCompound) JsonToNBT.func_150315_a(stringNBT);
} catch (NBTException exception) {
throw new InvalidXmlException("Invalid nbt for block " + nameBlock);
}
}
name = nameBlock + "@" + metadata + "{" + nbtTagCompound + "}";
return true;
}
public void setBlock(World world, int x, int y, int z) {
JumpBlock.setBlockNoLight(world, x, y, z, block, metadata, 2);
if (nbtTagCompound != null) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity == null) {
WarpDrive.logger.error("No TileEntity found for Filler %s at (%d %d %d)", getName(), x, y, z);
return;
}
tileEntity.readFromNBT(nbtTagCompound);
tileEntity.markDirty();
}
}
@Override
public IXmlRepresentableUnit constructor() {
return new Filler();
}
@Override
public boolean equals(Object object) {
return object instanceof Filler
&& (block == null || block.equals(((Filler)object).block))
&& metadata == ((Filler)object).metadata
&& (nbtTagCompound == null || nbtTagCompound.equals(((Filler)object).nbtTagCompound));
}
@Override
public String toString() {
return "Filler(" + block.getUnlocalizedName() + "@" + metadata + ")";
}
@Override
public int hashCode() {
return Block.getIdFromBlock(block) * 16 + metadata + (nbtTagCompound == null ? 0 : nbtTagCompound.hashCode() * 4096 * 16);
}
}

View file

@ -0,0 +1,125 @@
package cr0s.warpdrive.config;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IXmlRepresentable;
import cr0s.warpdrive.api.IXmlRepresentableUnit;
import org.w3c.dom.Element;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
/**
* Represents a set of 'units' that will be chosen randomly during world generation.
**/
public class GenericSet<E extends IXmlRepresentableUnit> implements IXmlRepresentable, Comparable {
protected String group;
protected String name;
private E unitDefault;
private String nameElementUnit;
private XmlRandomCollection<E> units;
private ArrayList<String> importGroupNames;
private ArrayList<String> importGroups;
public String getFullName() {
return group + ":" + name;
}
@Override
public String getName() {
return name;
}
public GenericSet(final String group, final String name, final E unitDefault, final String nameElementUnit) {
this.group = group;
this.name = name;
this.unitDefault = unitDefault;
this.nameElementUnit = nameElementUnit;
units = new XmlRandomCollection<>();
importGroupNames = new ArrayList<>();
importGroups = new ArrayList<>();
}
public boolean isEmpty() {
return units.isEmpty();
}
public E getRandomUnit(final Random random) {
E unit = units.getRandomEntry(random);
if (unit == null) {
WarpDrive.logger.error(String.format("null %s encountered in set %s", nameElementUnit, getFullName()));
unit = unitDefault;
}
return unit;
}
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
final List<Element> listChildren = XmlFileManager.getChildrenElementByTagName(element, nameElementUnit);
for (Element elementChild : listChildren) {
@SuppressWarnings("unchecked")
final E unit = (E) unitDefault.constructor();
units.loadFromXML(unit, elementChild);
}
final List<Element> listImports = XmlFileManager.getChildrenElementByTagName(element, "import");
if (!listImports.isEmpty()) {
for (Element elementImport : listImports) {
final String importGroup = elementImport.getAttribute("group");
final String importName = elementImport.getAttribute("name");
if (!importGroup.isEmpty()) {
if (!importName.isEmpty()) {
importGroupNames.add(importGroup + ":" + importName);
} else {
importGroups.add(importGroup);
}
} else {
WarpDrive.logger.warn("Ignoring import with no group definition in import element from " + getFullName());
}
}
}
return true;
}
@Override
public int compareTo(@Nonnull Object object) {
return name.compareTo(((GenericSet) object).name);
}
@Override
public String toString() {
return getFullName() + "(" + (units == null ? "-empty-" : units.elements().size()) + ")";
}
/**
* Adds the units from the given genericSet into this one. Must be pre-finishConstruction()
*
* @param genericSet
* The genericSet to add from
*/
public void loadFrom(GenericSet<E> genericSet) throws InvalidXmlException {
units.loadFrom(genericSet.units);
}
/**
* Return static import dependencies
*
* @return null or a list of group:names to be imported
**/
public Collection<String> getImportGroupNames() {
return importGroupNames;
}
/**
* Return dynamic import dependencies
*
* @return null or a list of groups to be imported
**/
public Collection<String> getImportGroups() {
return importGroups;
}
}

View file

@ -0,0 +1,152 @@
package cr0s.warpdrive.config;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IXmlRepresentableUnit;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Random;
/**
* Manage 'unit' sets that will be chosen randomly during world generation.
**/
public class GenericSetManager<E extends IXmlRepresentableUnit> extends XmlFileManager {
private final String prefixFilename;
private final String nameElementUnit;
private final String nameElementSet;
private final E unitDefault;
// all GenericSets
private HashMap<String, XmlRandomCollection<GenericSet<E>>> genericSetsByGroup;
public GenericSetManager(final String prefixFilename, final String nameElementUnit, final String nameElementSet, final E unitDefault) {
super();
this.prefixFilename = prefixFilename;
this.nameElementUnit = nameElementUnit;
this.nameElementSet = nameElementSet;
this.unitDefault = unitDefault;
}
public void load(final File dir) {
genericSetsByGroup = new HashMap<>();
load(dir, prefixFilename, nameElementSet);
propagateGenericSets();
}
@Override
protected void parseRootElement(final String location, final Element elementGenericSet) throws InvalidXmlException, SAXException, IOException {
final String group = elementGenericSet.getAttribute("group");
if (group.isEmpty()) {
throw new InvalidXmlException(location + " is missing a group attribute!");
}
final String name = elementGenericSet.getAttribute("name");
if (name.isEmpty()) {
throw new InvalidXmlException(location + " is missing a name attribute!");
}
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
WarpDrive.logger.info(String.format("- found %s %s:%s", nameElementSet, group, name));
}
final XmlRandomCollection<GenericSet<E>> xmlRandomCollection = genericSetsByGroup.computeIfAbsent(group, k -> new XmlRandomCollection<>());
GenericSet<E> genericSet = xmlRandomCollection.getNamedEntry(name);
if (genericSet == null) {
genericSet = new GenericSet<>(group, name, unitDefault, nameElementUnit);
}
xmlRandomCollection.loadFromXML(genericSet, elementGenericSet);
}
@SuppressWarnings("Convert2Diamond")
private void propagateGenericSets() {
HashMap<GenericSet<E>, ArrayList<String>> genericSetsDependencies = new HashMap<>();
// scan for static import dependencies
for (XmlRandomCollection<GenericSet<E>> genericSets : genericSetsByGroup.values()) {
for (GenericSet<E> genericSet : genericSets.elements()) {
final ArrayList<String> dependencies = genericSetsDependencies.computeIfAbsent(genericSet, k -> new ArrayList<>());
dependencies.addAll(genericSet.getImportGroupNames());
}
}
// resolve
int iterationCount = 0;
while (!genericSetsDependencies.isEmpty() && iterationCount++ < 10) {
final HashMap<GenericSet<E>, ArrayList<String>> genericSetsLeftToImport = new HashMap<>();
for (Entry<GenericSet<E>, ArrayList<String>> entry : genericSetsDependencies.entrySet()) {
final ArrayList<String> newDependencies = new ArrayList<>();
for (String dependency : entry.getValue()) {
final GenericSet<E> genericSet = getGenericSet(dependency);
if (genericSet == null) {
WarpDrive.logger.error(String.format("Ignoring missing %s %s dependency in %s %s", nameElementSet, dependency, nameElementSet, entry.getKey()));
} else if (genericSetsDependencies.containsKey(genericSet)) {
// skip until it is loaded
newDependencies.add(dependency);
} else {
try {
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
WarpDrive.logger.info(String.format("Importing %s %s in %s ", nameElementSet, genericSet.getFullName(), entry.getKey().getFullName()));
}
entry.getKey().loadFrom(genericSet);
} catch (InvalidXmlException exception) {
exception.printStackTrace();
WarpDrive.logger.error(String.format("While importing %s into %s %s", dependency, nameElementSet, entry.getKey().getFullName()));
}
}
}
if (!newDependencies.isEmpty()) {
genericSetsLeftToImport.put(entry.getKey(), newDependencies);
}
}
genericSetsDependencies = genericSetsLeftToImport;
}
// recursion has reach the limit?
if (!genericSetsDependencies.isEmpty()) {
WarpDrive.logger.error("Too many import recursions, ignoring the remaining ones:");
for (Entry<GenericSet<E>, ArrayList<String>> entry : genericSetsDependencies.entrySet()) {
WarpDrive.logger.warn(String.format("- %s %s is pending:", nameElementSet, entry.getKey()));
for (String dependency : entry.getValue()) {
WarpDrive.logger.warn(" + " + dependency);
}
}
}
}
public boolean doesGroupExist(final String groupName) {
return genericSetsByGroup.get(groupName) != null;
}
public GenericSet<E> getRandomSetFromGroup(final Random random, final String groupName) {
final XmlRandomCollection<GenericSet<E>> group = genericSetsByGroup.get(groupName);
if (group == null) {
return null;
}
return group.getRandomEntry(random);
}
public GenericSet<E> getGenericSet(final String groupAndName) {
final String[] parts = groupAndName.split(":");
if (parts.length != 2) {
WarpDrive.logger.error(String.format("Invalid %s '%s'. Expecting '{group}:{name}'", nameElementSet, groupAndName));
return null;
}
final XmlRandomCollection<GenericSet<E>> group = genericSetsByGroup.get(parts[0]);
if (group == null) {
return null;
}
return group.getNamedEntry(parts[1]);
}
}

View file

@ -0,0 +1,143 @@
package cr0s.warpdrive.config;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IXmlRepresentableUnit;
import org.w3c.dom.Element;
import java.util.Random;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTException;
import net.minecraft.nbt.NBTTagCompound;
/**
* Represents a single loot item.
**/
public class Loot implements IXmlRepresentableUnit {
public static final Loot DEFAULT;
static {
DEFAULT = new Loot();
DEFAULT.name = "-default-";
DEFAULT.item = Items.stick;
DEFAULT.damage = 0;
DEFAULT.nbtTagCompound = null;
DEFAULT.quantityMin = 0;
DEFAULT.quantityMax = 0;
}
private String name;
public Item item;
public int damage;
public NBTTagCompound nbtTagCompound = null;
public int quantityMin;
public int quantityMax;
@Override
public String getName() {
return name;
}
public Loot() {
}
@Override
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
// Check there is a block name
if (!element.hasAttribute("item")) {
throw new InvalidXmlException("Loot " + element + " is missing an item attribute!");
}
final String nameItem = element.getAttribute("item");
item = (Item) Item.itemRegistry.getObject(nameItem);
if (item == null) {
WarpDrive.logger.warn("Skipping missing item " + nameItem);
return false;
}
// Get metadata attribute, defaults to 0
damage = 0;
final String stringDamage = element.getAttribute("damage");
if (!stringDamage.isEmpty()) {
try {
damage = Integer.parseInt(stringDamage);
} catch (NumberFormatException exception) {
throw new InvalidXmlException("Invalid damage for item " + nameItem);
}
}
// Get nbt attribute, default to null/none
nbtTagCompound = null;
final String stringNBT = element.getAttribute("nbt");
if (!stringNBT.isEmpty()) {
try {
nbtTagCompound = (NBTTagCompound) JsonToNBT.func_150315_a(stringNBT);
} catch (NBTException exception) {
throw new InvalidXmlException("Invalid nbt for item " + nameItem);
}
}
// Get quantityMin attribute, defaults to 1
quantityMin = 1;
final String stringQuantityMin = element.getAttribute("minQuantity");
if (!stringQuantityMin.isEmpty()) {
try {
quantityMin = Integer.parseInt(stringQuantityMin);
} catch (NumberFormatException exception) {
throw new InvalidXmlException("Invalid minQuantity for item " + nameItem);
}
}
// Get quantityMin attribute, defaults to 1
quantityMax = 1;
final String stringQuantityMax = element.getAttribute("maxQuantity");
if (!stringQuantityMax.isEmpty()) {
try {
quantityMax = Integer.parseInt(stringQuantityMax);
} catch (NumberFormatException exception) {
throw new InvalidXmlException("Invalid maxQuantity for item " + nameItem);
}
}
name = nameItem + "@" + damage + "{" + nbtTagCompound + "}";
return true;
}
public ItemStack getItemStack(final Random rand) {
final int quantity = quantityMin + (quantityMax > quantityMin ? rand.nextInt(quantityMax - quantityMin) : 0);
final ItemStack itemStack = new ItemStack(item, quantity, damage);
if (nbtTagCompound != null) {
NBTTagCompound nbtTagCompoundNew = (NBTTagCompound) nbtTagCompound.copy();
itemStack.setTagCompound(nbtTagCompoundNew);
}
return itemStack;
}
@Override
public IXmlRepresentableUnit constructor() {
return new Loot();
}
@Override
public boolean equals(Object object) {
return object instanceof Loot
&& (item == null || item.equals(((Loot) object).item))
&& damage == ((Loot) object).damage
&& (nbtTagCompound == null || nbtTagCompound.equals(((Loot) object).nbtTagCompound));
}
@Override
public String toString() {
return "Loot(" + item.getUnlocalizedName() + "@" + damage + ")";
}
@Override
public int hashCode() {
return Item.getIdFromItem(item) * 16 + damage + (nbtTagCompound == null ? 0 : nbtTagCompound.hashCode() * 32768 * 16);
}
}

View file

@ -29,7 +29,6 @@ import cr0s.warpdrive.compat.CompatThaumcraft;
import cr0s.warpdrive.compat.CompatThermalDynamics;
import cr0s.warpdrive.compat.CompatThermalExpansion;
import cr0s.warpdrive.compat.CompatWarpDrive;
import cr0s.warpdrive.config.filler.FillerManager;
import cr0s.warpdrive.config.structures.StructureManager;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
@ -68,6 +67,9 @@ public class WarpDriveConfig {
"filler-netherores.xml",
"filler-undergroundbiomes.xml",
};
private static final String[] defaultXML_loots = {
"loot-default.xml",
};
private static final String[] defaultXML_structures = {
"structures-default.xml",
"structures-netherores.xml",
@ -76,6 +78,9 @@ public class WarpDriveConfig {
"celestialObjects-default.xml"
};
public static GenericSetManager<Filler> FillerManager = new GenericSetManager<>("filler", "filler", "fillerSet", Filler.DEFAULT);
public static GenericSetManager<Loot> LootManager = new GenericSetManager<>("loot", "loot", "lootSet", Loot.DEFAULT);
/*
* The variables which store whether or not individual mods are loaded
*/
@ -391,6 +396,7 @@ public class WarpDriveConfig {
// unpack default XML files if none are defined
unpackResourcesToFolder("filler", ".xml", defaultXML_fillers, "config", configDirectory);
unpackResourcesToFolder("loot", ".xml", defaultXML_loots, "config", configDirectory);
unpackResourcesToFolder("structures", ".xml", defaultXML_structures, "config", configDirectory);
unpackResourcesToFolder("celestialObjects", ".xml", defaultXML_celestialObjects, "config", configDirectory);
@ -964,6 +970,7 @@ public class WarpDriveConfig {
public static void onFMLPostInitialization() {
// load XML files
FillerManager.load(configDirectory);
LootManager.load(configDirectory);
StructureManager.load(configDirectory);
Dictionary.apply();

View file

@ -13,7 +13,7 @@ import java.util.List;
public abstract class XmlFileManager {
protected void load(final File dir, final String prefixFilename, final String elementName) {
protected void load(final File dir, final String prefixFilename, final String nameElement) {
// (directory is created by caller, so it can copy default files if any)
@ -42,10 +42,10 @@ public abstract class XmlFileManager {
XmlPreprocessor.doLogicPreprocessing(document);
// only add selected root elements
final List<Element> listElements = getChildrenElementByTagName(document.getDocumentElement(), elementName);
final List<Element> listElements = getChildrenElementByTagName(document.getDocumentElement(), nameElement);
for (int indexElement = 0; indexElement < listElements.size(); indexElement++) {
final Element element = listElements.get(indexElement);
final String location = String.format("%d/%d", indexElement + 1, listElements.size());
final String location = String.format("%s %d/%d", nameElement, indexElement + 1, listElements.size());
parseRootElement(location, element);
}
} catch (Exception exception) {
@ -62,7 +62,7 @@ public abstract class XmlFileManager {
for (Node nodeChild = parent.getFirstChild(); nodeChild != null; nodeChild = nodeChild.getNextSibling()) {
if ( nodeChild.getNodeType() == Node.ELEMENT_NODE
&& name.equals(nodeChild.getNodeName()) ) {
&& name.equals(nodeChild.getNodeName()) ) {
listElements.add((Element) nodeChild);
}
}

View file

@ -39,7 +39,7 @@ public class XmlPreprocessor {
for (String mod : element.getAttribute("mods").split(",")) {
//TODO: add version check
// @TODO add version check
if (mod.isEmpty()) {
continue;

View file

@ -1,5 +1,6 @@
package cr0s.warpdrive.config;
import cr0s.warpdrive.api.IXmlRepresentable;
import org.w3c.dom.Element;
/**
@ -19,6 +20,7 @@ public class XmlRandomCollection<E extends IXmlRepresentable> extends RandomColl
* @param element
* Element of an XML file
* @throws InvalidXmlException
* Exception encountered
**/
public void loadFromXML(E object, Element element) throws InvalidXmlException {
if (!object.loadFromXmlElement(element)) {// skip invalid entries

View file

@ -1,84 +0,0 @@
package cr0s.warpdrive.config.filler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.IXmlRepresentable;
import cr0s.warpdrive.config.InvalidXmlException;
import cr0s.warpdrive.data.JumpBlock;
import org.w3c.dom.Element;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
/**
* Represents a single filler block.
**/
public class Filler implements IXmlRepresentable {
private String name;
public Block block;
public int metadata;
public NBTTagCompound tag = null; // TODO
@Override
public String getName() {
return name;
}
public Filler() {
}
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
// Check there is a block name
if (!element.hasAttribute("block")) {
throw new InvalidXmlException("Filler " + element + " is missing a block tag!");
}
String blockName = element.getAttribute("block");
block = Block.getBlockFromName(blockName);
if (block == null) {
WarpDrive.logger.warn("Skipping missing block " + blockName);
return false;
}
// Get metadata attribute, defaults to 0
metadata = 0;
String stringMetadata = element.getAttribute("metadata");
if (!stringMetadata.isEmpty()) {
try {
metadata = Integer.parseInt(stringMetadata);
} catch (NumberFormatException exception) {
throw new InvalidXmlException("Invalid metadata for block " + blockName);
}
}
name = blockName + "@" + metadata + "{" + tag + "}";
return true;
}
public void setBlock(World world, int x, int y, int z) {
JumpBlock.setBlockNoLight(world, x, y, z, block, metadata, 2);
// world.setBlock(x, y, z, block, metadata, 2);
// TODO set NBT data
}
@Override
public boolean equals(Object object) {
return object instanceof Filler
&& (block == null || block.equals(((Filler)object).block))
&& metadata == ((Filler)object).metadata
&& (tag == null || tag.equals(((Filler)object).tag));
}
@Override
public String toString() {
return "Filler(" + block.getUnlocalizedName() + "@" + metadata + ")";
}
@Override
public int hashCode() {
return Block.getIdFromBlock(block) * 16 + metadata + (tag == null ? 0 : tag.hashCode() * 4096 * 16);
}
}

View file

@ -1,141 +0,0 @@
package cr0s.warpdrive.config.filler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.InvalidXmlException;
import cr0s.warpdrive.config.XmlRandomCollection;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.XmlFileManager;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Random;
public class FillerManager extends XmlFileManager {
private static FillerManager INSTANCE = new FillerManager();
// all fillerSets
private static HashMap<String, XmlRandomCollection<FillerSet>> fillerSetsByGroup;
public static void load(File dir) {
fillerSetsByGroup = new HashMap<>();
INSTANCE.load(dir, "filler", "fillerSet");
propagateFillerSets();
}
@Override
protected void parseRootElement(final String location, Element elementFillerSet) throws InvalidXmlException, SAXException, IOException {
String group = elementFillerSet.getAttribute("group");
if (group.isEmpty()) {
throw new InvalidXmlException("FillerSet " + location + " is missing a group attribute!");
}
String name = elementFillerSet.getAttribute("name");
if (name.isEmpty()) {
throw new InvalidXmlException("FillerSet " + location + " is missing a name attribute!");
}
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
WarpDrive.logger.info("- found FillerSet " + group + ":" + name);
}
XmlRandomCollection<FillerSet> xmlRandomCollection = fillerSetsByGroup.computeIfAbsent(group, k -> new XmlRandomCollection<>());
FillerSet fillerSet = xmlRandomCollection.getNamedEntry(name);
if (fillerSet == null) {
fillerSet = new FillerSet(group, name);
}
xmlRandomCollection.loadFromXML(fillerSet, elementFillerSet);
}
@SuppressWarnings("Convert2Diamond")
private static void propagateFillerSets() {
HashMap<FillerSet, ArrayList<String>> fillerSetsDependencies = new HashMap<>();
// scan for static import dependencies
for (XmlRandomCollection<FillerSet> fillerSets : fillerSetsByGroup.values()) {
for (FillerSet fillerSet : fillerSets.elements()) {
ArrayList<String> dependencies = fillerSetsDependencies.computeIfAbsent(fillerSet, k -> new ArrayList<>());
dependencies.addAll(fillerSet.getImportGroupNames());
}
}
// resolve
int iterationCount = 0;
while (!fillerSetsDependencies.isEmpty() && iterationCount++ < 10) {
HashMap<FillerSet, ArrayList<String>> fillerSetsLeftToImport = new HashMap<>();
for (Entry<FillerSet, ArrayList<String>> entry : fillerSetsDependencies.entrySet()) {
ArrayList<String> newDependencies = new ArrayList<>();
for (String dependency : entry.getValue()) {
FillerSet fillerSet = getFillerSet(dependency);
if (fillerSet == null) {
WarpDrive.logger.error("Ignoring missing FillerSet " + dependency + " dependency in FillerSet " + entry.getKey());
} else if (fillerSetsDependencies.containsKey(fillerSet)) {
// skip until it is loaded
newDependencies.add(dependency);
} else {
try {
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
WarpDrive.logger.info("Importing FillerSet " + fillerSet.getFullName() + " in " + entry.getKey().getFullName());
}
entry.getKey().loadFrom(fillerSet);
} catch (InvalidXmlException exception) {
exception.printStackTrace();
WarpDrive.logger.error("While importing " + dependency + " into FillerSet " + entry.getKey().getFullName());
}
}
}
if (!newDependencies.isEmpty()) {
fillerSetsLeftToImport.put(entry.getKey(), newDependencies);
}
}
fillerSetsDependencies = fillerSetsLeftToImport;
}
// recursion has reach the limit?
if (!fillerSetsDependencies.isEmpty()) {
WarpDrive.logger.error("Too many import recursions, ignoring the remaining ones:");
for (Entry<FillerSet, ArrayList<String>> entry : fillerSetsDependencies.entrySet()) {
WarpDrive.logger.warn("- FillerSet " + entry.getKey() + " is pending:");
for (String dependency : entry.getValue()) {
WarpDrive.logger.warn(" + " + dependency);
}
}
}
}
public static boolean doesGroupExist(final String groupName) {
return fillerSetsByGroup.get(groupName) != null;
}
public static FillerSet getRandomFillerSetFromGroup(Random random, final String groupName) {
XmlRandomCollection<FillerSet> group = fillerSetsByGroup.get(groupName);
if (group == null) {
return null;
}
return group.getRandomEntry(random);
}
public static FillerSet getFillerSet(final String groupAndName) {
String[] parts = groupAndName.split(":");
if (parts.length != 2) {
WarpDrive.logger.error("Invalid FillerSet '" + groupAndName + "'. Expecting '{group}:{name}'");
return null;
}
XmlRandomCollection<FillerSet> group = fillerSetsByGroup.get(parts[0]);
if (group == null) {
return null;
}
return group.getNamedEntry(parts[1]);
}
}

View file

@ -1,124 +0,0 @@
package cr0s.warpdrive.config.filler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.IXmlRepresentable;
import cr0s.warpdrive.config.InvalidXmlException;
import cr0s.warpdrive.config.XmlFileManager;
import cr0s.warpdrive.config.XmlRandomCollection;
import org.w3c.dom.Element;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import net.minecraft.init.Blocks;
/**
* Represents a set of fillers.
**/
public class FillerSet implements IXmlRepresentable, Comparable {
protected String group;
protected String name;
private XmlRandomCollection<Filler> fillers;
private ArrayList<String> importGroupNames;
private ArrayList<String> importGroups;
public String getFullName() {
return group + ":" + name;
}
@Override
public String getName() {
return name;
}
public FillerSet(final String group, final String name) {
this.group = group;
this.name = name;
fillers = new XmlRandomCollection<>();
importGroupNames = new ArrayList<>();
importGroups = new ArrayList<>();
}
public boolean isEmpty() {
return fillers.isEmpty();
}
public Filler getRandomBlock(Random random) {
Filler filler = fillers.getRandomEntry(random);
if (filler == null) {
WarpDrive.logger.error("null filler encountered in FillerSet " + getFullName());
filler = new Filler();
filler.block = Blocks.glass;
}
return filler;
}
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
List<Element> listFillers = XmlFileManager.getChildrenElementByTagName(element, "filler");
for (Element elementFiller : listFillers) {
Filler filler = new Filler();
fillers.loadFromXML(filler, elementFiller);
}
List<Element> listImports = XmlFileManager.getChildrenElementByTagName(element, "import");
if (!listImports.isEmpty()) {
for (Element elementImport : listImports) {
String importGroup = elementImport.getAttribute("group");
String importName = elementImport.getAttribute("name");
if (!importGroup.isEmpty()) {
if (!importName.isEmpty()) {
importGroupNames.add(importGroup + ":" + importName);
} else {
importGroups.add(importGroup);
}
} else {
WarpDrive.logger.warn("Ignoring import with no group definition in import element from " + getFullName());
}
}
}
return true;
}
@Override
public int compareTo(@Nonnull Object object) {
return name.compareTo(((FillerSet) object).name);
}
@Override
public String toString() {
return getFullName() + "(" + (fillers == null ? "-empty-" : fillers.elements().size()) + ")";
}
/**
* Adds the blocks from the given fillerSet into this one. Must be pre-finishConstruction()
*
* @param fillerSet
* The fillerSet to add from
*/
public void loadFrom(FillerSet fillerSet) throws InvalidXmlException {
fillers.loadFrom(fillerSet.fillers);
}
/**
* Return static import dependencies
*
* @return null or a list of group:names to be imported
**/
public Collection<String> getImportGroupNames() {
return importGroupNames;
}
/**
* Return dynamic import dependencies
*
* @return null or a list of groups to be imported
**/
public Collection<String> getImportGroups() {
return importGroups;
}
}

View file

@ -1,6 +1,6 @@
package cr0s.warpdrive.config.structures;
import cr0s.warpdrive.config.IXmlRepresentable;
import cr0s.warpdrive.api.IXmlRepresentable;
import cr0s.warpdrive.config.InvalidXmlException;
import cr0s.warpdrive.config.XmlFileManager;
import org.w3c.dom.Element;
@ -38,12 +38,12 @@ public abstract class AbstractStructure extends WorldGenerator implements IXmlRe
abstract public AbstractStructureInstance instantiate(Random random);
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
List<Element> listVariables = XmlFileManager.getChildrenElementByTagName(element, "variable");
final List<Element> listVariables = XmlFileManager.getChildrenElementByTagName(element, "variable");
for (Element elementVariable : listVariables) {
String variableName = elementVariable.getAttribute("name");
String variableExpression = elementVariable.getTextContent();
final String variableName = elementVariable.getAttribute("name");
final String variableExpression = elementVariable.getTextContent();
variables.put(variableName, variableExpression);
}

View file

@ -1,7 +1,7 @@
package cr0s.warpdrive.config.structures;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.IXmlRepresentable;
import cr0s.warpdrive.api.IXmlRepresentable;
import cr0s.warpdrive.config.InvalidXmlException;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.XmlFileManager;
@ -21,10 +21,10 @@ public class MetaOrb extends Orb {
}
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
super.loadFromXmlElement(element);
List<Element> listMetaShells = XmlFileManager.getChildrenElementByTagName(element, "metaShell");
final List<Element> listMetaShells = XmlFileManager.getChildrenElementByTagName(element, "metaShell");
if (listMetaShells.size() > 1) {
throw new InvalidXmlException("Too many metaShell defined in structure " + getFullName() + ". Maximum is 1.");
}
@ -65,7 +65,7 @@ public class MetaOrb extends Orb {
}
@Override
public boolean loadFromXmlElement(Element element) throws InvalidXmlException {
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
WarpDrive.logger.info(" + found metashell");
}

View file

@ -4,7 +4,7 @@ import cr0s.warpdrive.Commons;
import cr0s.warpdrive.LocalProfiler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.filler.Filler;
import cr0s.warpdrive.config.Filler;
import cr0s.warpdrive.config.structures.Orb.OrbShell;
import cr0s.warpdrive.data.VectorI;
@ -16,24 +16,25 @@ import net.minecraft.init.Blocks;
import net.minecraft.world.World;
public class MetaOrbInstance extends OrbInstance {
private static final int CORE_MAX_TRIES = 10;
protected final MetaShell metaShell;
public MetaOrbInstance(MetaOrb asteroid, Random random) {
public MetaOrbInstance(final MetaOrb asteroid, final Random random) {
super(asteroid, random);
metaShell = new MetaShell(asteroid, random);
// FIXME setRadius(Math.round(totalThickness + metaShell.radius));
}
@Override
public boolean generate(World world, Random random, int x, int y, int z) {
public boolean generate(final World world, final Random random, final int x, final int y, final int z) {
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
WarpDrive.logger.info("Generating MetaOrb " + structure.name + " of " + metaShell.count + " cores with radius of " + totalThickness);
}
LocalProfiler.start("[AsteroidInstance] Generating MetaOrb " + structure.name + " of " + metaShell.count + " cores with radius of " + totalThickness);
int y2 = Math.min(WarpDriveConfig.SPACE_GENERATOR_Y_MAX_BORDER - totalThickness - (int) metaShell.radius,
Math.max(y, WarpDriveConfig.SPACE_GENERATOR_Y_MIN_BORDER + totalThickness + (int) metaShell.radius));
final int y2 = Math.min(WarpDriveConfig.SPACE_GENERATOR_Y_MAX_BORDER - totalThickness - (int) metaShell.radius,
Math.max(y, WarpDriveConfig.SPACE_GENERATOR_Y_MIN_BORDER + totalThickness + (int) metaShell.radius));
if (((MetaOrb)structure).metaShell == null) {
return super.generate(world, random, x, y2, z);
}
@ -46,9 +47,9 @@ public class MetaOrbInstance extends OrbInstance {
}
// calculate distance to borders of generation area
int maxRadX = totalThickness - Math.abs(location.x);
int maxRadY = totalThickness - Math.abs(location.y);
int maxRadZ = totalThickness - Math.abs(location.z);
final int maxRadX = totalThickness - Math.abs(location.x);
final int maxRadY = totalThickness - Math.abs(location.y);
final int maxRadZ = totalThickness - Math.abs(location.z);
// keep the biggest one to have a bumpy effect
int maxLocalRadius = Math.max(maxRadX, Math.max(maxRadY, maxRadZ));
// enforce a minimum thickness to prevent lone core blocks
@ -59,8 +60,8 @@ public class MetaOrbInstance extends OrbInstance {
addShell(world, new VectorI(x, y2, z).add(location), maxLocalRadius);
}
int minY_clamped = Math.max(0, y2 - totalThickness);
int maxY_clamped = Math.min(255, y2 + totalThickness);
final int minY_clamped = Math.max(0, y2 - totalThickness);
final int maxY_clamped = Math.min(255, y2 + totalThickness);
for (int xIndex = x - totalThickness; xIndex <= x + totalThickness; xIndex++) {
for (int zIndex = z - totalThickness; zIndex <= z + totalThickness; zIndex++) {
for (int yIndex = minY_clamped; yIndex <= maxY_clamped; yIndex++) {
@ -75,21 +76,21 @@ public class MetaOrbInstance extends OrbInstance {
return false;
}
private void addShell(World world, VectorI location, int radius) {
double sqRadius = radius * radius;
private void addShell(final World world, final VectorI location, final int radius) {
final double sqRadius = radius * radius;
// iterate all blocks within cube with side 2 * radius
for(int x = location.x - radius; x <= location.x + radius; x++) {
int dX2 = (x - location.x) * (x - location.x);
final int dX2 = (x - location.x) * (x - location.x);
for(int y = location.y - radius; y <= location.y + radius; y++) {
int dX2Y2 = dX2 + (y - location.y) * (y - location.y);
final int dX2Y2 = dX2 + (y - location.y) * (y - location.y);
for(int z = location.z - radius; z <= location.z + radius; z++) {
// current radius
int sqRange = dX2Y2 + (location.z - z) * (location.z - z);
final int sqRange = dX2Y2 + (location.z - z) * (location.z - z);
// if inside radius
if (sqRange <= sqRadius && isReplaceableOreGen(world, x, y, z)) {
OrbShell shell = getShellForSqRadius(sqRange);
Filler filler = shell.getRandomBlock(world.rand);
Filler filler = shell.getRandomUnit(world.rand);
filler.setBlock(world, x, y, z);
}
}
@ -97,7 +98,7 @@ public class MetaOrbInstance extends OrbInstance {
}
}
private static boolean isReplaceableOreGen(World world, int x, int y, int z) {
private static boolean isReplaceableOreGen(final World world, final int x, final int y, final int z) {
return world.getBlock(x, y, z).isReplaceableOreGen(world, x, y, z, Blocks.air);
}
@ -108,7 +109,7 @@ public class MetaOrbInstance extends OrbInstance {
protected final Block block;
protected final int metadata;
public MetaShell(MetaOrb asteroid, Random random) {
public MetaShell(final MetaOrb asteroid, final Random random) {
if (asteroid.metaShell == null) {
count = 1;
radius = 0;
@ -123,16 +124,16 @@ public class MetaOrbInstance extends OrbInstance {
// evaluate core positions
locations = new ArrayList<>();
double diameter = Math.max(1D, 2 * radius);
double xMin = -radius;
double yMin = -radius;
double zMin = -radius;
final double diameter = Math.max(1D, 2 * radius);
final double xMin = -radius;
final double yMin = -radius;
final double zMin = -radius;
for (int index = 0; index < count; index++) {
boolean found = false;
for(int step = 0; step < CORE_MAX_TRIES && !found; step++) {
VectorI location = new VectorI(
final VectorI location = new VectorI(
(int)Math.round(xMin + diameter * random.nextDouble()),
(int)Math.round(yMin + diameter * random.nextDouble()),
(int)Math.round(zMin + diameter * random.nextDouble()));

View file

@ -1,11 +1,11 @@
package cr0s.warpdrive.config.structures;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.GenericSet;
import cr0s.warpdrive.config.InvalidXmlException;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.XmlFileManager;
import cr0s.warpdrive.config.filler.FillerManager;
import cr0s.warpdrive.config.filler.FillerSet;
import cr0s.warpdrive.config.Filler;
import org.w3c.dom.Element;
import java.util.List;
@ -64,13 +64,14 @@ public class Orb extends AbstractStructure {
return new OrbInstance(this, random);
}
public class OrbShell extends FillerSet {
public class OrbShell extends GenericSet<Filler> {
private final String parentFullName;
protected int minThickness;
protected int maxThickness;
public OrbShell(final String parentFullName, final String name) {
super(null, name);
super(null, name, Filler.DEFAULT, "filler");
this.parentFullName = parentFullName;
}
@ -84,7 +85,7 @@ public class Orb extends AbstractStructure {
// resolve static imports
for (String importGroupName : getImportGroupNames()) {
FillerSet fillerSet = FillerManager.getFillerSet(importGroupName);
GenericSet<Filler> fillerSet = WarpDriveConfig.FillerManager.getGenericSet(importGroupName);
if (fillerSet == null) {
WarpDrive.logger.warn("Skipping missing FillerSet " + importGroupName + " in shell " + parentFullName + ":" + name);
} else {
@ -94,7 +95,7 @@ public class Orb extends AbstractStructure {
// validate dynamic imports
for (String importGroup : getImportGroups()) {
if (!FillerManager.doesGroupExist(importGroup)) {
if (!WarpDriveConfig.FillerManager.doesGroupExist(importGroup)) {
WarpDrive.logger.warn("An invalid FillerSet group " + importGroup + " is referenced in shell " + parentFullName + ":" + name);
}
}
@ -126,7 +127,7 @@ public class Orb extends AbstractStructure {
try {
orbShell.loadFrom(this);
for (String importGroup : getImportGroups()) {
FillerSet fillerSet = FillerManager.getRandomFillerSetFromGroup(random, importGroup);
GenericSet<Filler> fillerSet = WarpDriveConfig.FillerManager.getRandomSetFromGroup(random, importGroup);
if (fillerSet == null) {
WarpDrive.logger.info("Ignoring invalid group " + importGroup + " in shell " + name + " of structure " + parentFullName);
continue;

View file

@ -42,12 +42,12 @@ public class StructureManager extends XmlFileManager {
protected void parseRootElement(final String location, Element elementStructure) throws InvalidXmlException, SAXException, IOException {
String group = elementStructure.getAttribute("group");
if (group.isEmpty()) {
throw new InvalidXmlException("Structure " + location + " is missing a group attribute!");
throw new InvalidXmlException(String.format("%s is missing a group attribute!", location));
}
String name = elementStructure.getAttribute("name");
if (name.isEmpty()) {
throw new InvalidXmlException("Structure " + location + " is missing a name attribute!");
throw new InvalidXmlException(String.format("%s is missing a name attribute!", location));
}
WarpDrive.logger.info("- found Structure " + group + ":" + name);

View file

@ -45,6 +45,7 @@ public class CelestialObject implements Cloneable, IStringSerializable {
public int parentCenterX, parentCenterZ;
public boolean isProvidedByWarpDrive;
private boolean isProvidedByWarpDrive_defined = false;
public double gravity;
public boolean isBreathable;
@ -169,8 +170,9 @@ public class CelestialObject implements Cloneable, IStringSerializable {
gravity = parseGravity(elementDimension.getAttribute("gravity"));
if (elementDimension.hasAttribute("isProvidedByWarpDrive")) {
isProvidedByWarpDrive = Boolean.parseBoolean(elementDimension.getAttribute("isProvidedByWarpDrive"));
isProvidedByWarpDrive_defined = true;
} else {
isProvidedByWarpDrive = isHyperspace() || isSpace();
isProvidedByWarpDrive_defined = false;
}
// get required center element
@ -315,13 +317,19 @@ public class CelestialObject implements Cloneable, IStringSerializable {
}
}
public void lateUpdate() {
if (!isProvidedByWarpDrive_defined) {
isProvidedByWarpDrive = isHyperspace() || isSpace();
}
}
@SuppressWarnings("CloneDoesntCallSuperClone")
@Override
public CelestialObject clone() {
return new CelestialObject(dimensionId, dimensionCenterX, dimensionCenterZ, borderRadiusX, borderRadiusZ, parentDimensionId, parentCenterX, parentCenterZ);
}
public StructureGroup getRandomStructure(Random random, final int x, final int z) {
public StructureGroup getRandomStructure(final Random random, final int x, final int z) {
return randomStructures.getRandomEntry(random);
}
@ -551,7 +559,7 @@ public class CelestialObject implements Cloneable, IStringSerializable {
alpha = Commons.clamp(0.0F, 1.0F, Float.parseFloat(elementRender.getAttribute("alpha")));
} catch (Exception exception) {
exception.printStackTrace();
WarpDrive.logger.error("Exception while parsing Render element at " + location);
WarpDrive.logger.error(String.format("Exception while parsing Render element RGBA attributes at %s", location));
red = 0.5F;
green = 0.5F;
blue = 0.5F;
@ -561,13 +569,32 @@ public class CelestialObject implements Cloneable, IStringSerializable {
if (texture == null || texture.isEmpty()) {
texture = null;
resourceLocation = null;
periodU = 1.0F;
periodV = 1.0F;
periodU = 1.0D;
periodV = 1.0D;
isAdditive = false;
} else {
resourceLocation = new ResourceLocation(texture);
periodU = Commons.clampMantisse(0.001D, 1000000.0D, Double.parseDouble(elementRender.getAttribute("periodU")));
periodV = Commons.clampMantisse(0.001D, 1000000.0D, Double.parseDouble(elementRender.getAttribute("periodV")));
periodU = 0.001D;
final String stringPeriodU = elementRender.getAttribute("periodU");
if (!stringPeriodU.isEmpty()) {
try {
periodU = Commons.clampMantisse(0.001D, 1000000.0D, Double.parseDouble(stringPeriodU));
} catch (NumberFormatException exception) {
throw new InvalidXmlException(String.format("Invalid periodU attribute '%s' at %s", stringPeriodU, location));
}
}
periodV = 0.001D;
final String stringPeriodV = elementRender.getAttribute("periodV");
if (!stringPeriodV.isEmpty()) {
try {
periodV = Commons.clampMantisse(0.001D, 1000000.0D, Double.parseDouble(stringPeriodV));
} catch (NumberFormatException exception) {
throw new InvalidXmlException(String.format("Invalid periodV attribute '%s' at %s", stringPeriodV, location));
}
}
isAdditive = Boolean.parseBoolean(elementRender.getAttribute("additive"));
}
}

View file

@ -6,7 +6,7 @@ import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.block.detection.BlockMonitor;
import cr0s.warpdrive.compat.CompatForgeMultipart;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.filler.Filler;
import cr0s.warpdrive.config.Filler;
import java.lang.reflect.Method;
import java.util.HashMap;
@ -94,7 +94,7 @@ public class JumpBlock {
}
block = filler.block;
blockMeta = filler.metadata;
blockNBT = (filler.tag != null) ? (NBTTagCompound) filler.tag.copy() : null;
blockNBT = (filler.nbtTagCompound != null) ? (NBTTagCompound) filler.nbtTagCompound.copy() : null;
this.x = x;
this.y = y;
this.z = z;

View file

@ -2,7 +2,6 @@ package cr0s.warpdrive.world;
import cr0s.warpdrive.LocalProfiler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.structures.Orb.OrbShell;
import cr0s.warpdrive.config.structures.OrbInstance;
import cr0s.warpdrive.data.JumpBlock;
@ -185,14 +184,14 @@ public final class EntitySphereGen extends Entity {
// Add blocks to memory
OrbShell orbShell = orbInstance.getShellForSqRadius(sqRange);
// WarpDrive.logger.info("sqRange " + sqRange + " sqRadius " + sqRadius);
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord + x, yCoord + y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord - x, yCoord + y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord + x, yCoord - y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord + x, yCoord + y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord - x, yCoord - y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord + x, yCoord - y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord - x, yCoord + y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomBlock(rand), xCoord - x, yCoord - y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord + x, yCoord + y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord - x, yCoord + y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord + x, yCoord - y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord + x, yCoord + y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord - x, yCoord - y, zCoord + z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord + x, yCoord - y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord - x, yCoord + y, zCoord - z));
addBlock(new JumpBlock(orbShell.getRandomUnit(rand), xCoord - x, yCoord - y, zCoord - z));
}
}
}

View file

@ -1,15 +1,11 @@
package cr0s.warpdrive.world;
import cr0s.warpdrive.LocalProfiler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.filler.Filler;
import cr0s.warpdrive.config.structures.AbstractStructure;
import cr0s.warpdrive.config.Filler;
import cr0s.warpdrive.config.structures.AbstractStructureInstance;
import cr0s.warpdrive.config.structures.Orb.OrbShell;
import cr0s.warpdrive.config.structures.OrbInstance;
import cr0s.warpdrive.config.structures.StructureGroup;
import cr0s.warpdrive.config.structures.StructureManager;
import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.data.StarMapRegistry;
@ -81,7 +77,7 @@ public class SpaceWorldGenerator implements IWorldGenerator {
// cheat by using axial symmetry so we don't create random numbers too frequently
OrbShell orbShell = orbInstance.getShellForSqRadius(dSq);
Filler filler = orbShell.getRandomBlock(world.rand);
Filler filler = orbShell.getRandomUnit(world.rand);
filler.setBlock(world, xCoord + x, yCoord + y, zCoord + z);
filler.setBlock(world, xCoord - x, yCoord + y, zCoord + z);
filler.setBlock(world, xCoord + x, yCoord - y, zCoord + z);

View file

@ -6,12 +6,12 @@ import cr0s.warpdrive.config.WarpDriveConfig;
import java.util.Random;
import net.minecraft.entity.monster.EntityPigZombie;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenerator;
@ -148,15 +148,15 @@ public class WorldGenSmallShip extends WorldGenerator {
genStructure.setHullPlain(world, i + 6, j + 2, k + 11);
genStructure.setHullPlain(world, i + 6, j + 3, k + 2);
world.setBlock(i + 6, j + 3, k + 3, Blocks.chest, 3, 0);
fillChestWithBonuses(world, rand, i + 6, j + 3, k + 3);
genStructure.fillInventoryWithLoot(world, rand, i + 6, j + 3, k + 3, "ship");
world.setBlock(i + 6, j + 3, k + 11, Blocks.chest, 2, 0);
fillChestWithBonuses(world, rand, i + 6, j + 3, k + 11);
genStructure.fillInventoryWithLoot(world, rand, i + 6, j + 3, k + 11, "ship");
genStructure.setHullPlain(world, i + 6, j + 3, k + 12);
genStructure.setHullPlain(world, i + 6, j + 4, k + 2);
world.setBlock(i + 6, j + 4, k + 3, Blocks.chest, 3, 0);
fillChestWithBonuses(world, rand, i + 6, j + 4, k + 3);
genStructure.fillInventoryWithLoot(world, rand, i + 6, j + 4, k + 3, "ship");
world.setBlock(i + 6, j + 4, k + 11, Blocks.chest, 2, 0);
fillChestWithBonuses(world, rand, i + 6, j + 4, k + 11);
genStructure.fillInventoryWithLoot(world, rand, i + 6, j + 4, k + 11, "ship");
genStructure.setHullPlain(world, i + 6, j + 4, k + 12);
genStructure.setHullPlain(world, i + 6, j + 5, k + 2);
genStructure.setHullPlain(world, i + 6, j + 5, k + 12);
@ -557,117 +557,18 @@ public class WorldGenSmallShip extends WorldGenerator {
entityVillager.setCurrentItemOrArmor(4, new ItemStack(WarpDrive.itemWarpArmor[0], 1, 1));
world.spawnEntityInWorld(entityVillager);
}
} else {// Zombies
} else if (world.rand.nextBoolean()) {// Zombies
for (int idx = 0; idx < countMobs; idx++) {
EntityZombie entityZombie = new EntityZombie(world);
entityZombie.setLocationAndAngles(x + 0.5D, y, z + 0.5D, 0.0F, 0.0F);
world.spawnEntityInWorld(entityZombie);
}
}
}
public void fillChestWithBonuses(final World worldObj, final Random rand, final int x, final int y, final int z) {
final TileEntity tileEntity = worldObj.getTileEntity(x, y, z);
if (tileEntity != null) {
final TileEntityChest chest = (TileEntityChest) tileEntity;
final int size = chest.getSizeInventory();
int numBonuses = rand.nextInt(size) / 2;
for (int i = 0; i < size; i++) {
if (rand.nextInt(size) <= numBonuses) {
numBonuses--;
chest.setInventorySlotContents(i, getRandomBonus(rand));
}
} else {// Zombie pigmen
for (int idx = 0; idx < countMobs; idx++) {
EntityPigZombie entityZombie = new EntityPigZombie(world);
entityZombie.setLocationAndAngles(x + 0.5D, y, z + 0.5D, 0.0F, 0.0F);
world.spawnEntityInWorld(entityZombie);
}
}
}
private ItemStack getRandomBonus(final Random rand) {
ItemStack res = null;
boolean isDone = false;
while (!isDone) {
switch (rand.nextInt(14)) {
case 0: // Mass fabricator
if (WarpDriveConfig.isIndustrialCraft2Loaded) {
res = WarpDriveConfig.getModItemStack("IC2", "blockMachine", -1);
res.setItemDamage(14);
res.stackSize = 1; // + rand.nextInt(2);
isDone = true;
}
break;
case 1:
if (WarpDriveConfig.isIndustrialCraft2Loaded) {
res = WarpDriveConfig.getModItemStack("IC2", "blockNuke", -1);
res.stackSize = 1 + rand.nextInt(2);
isDone = true;
}
break;
case 2: // Quantum armor bonuses
case 3:
case 4:
case 5:
isDone = true;
break;// skipped
case 6:// Glass fiber cable item
if (WarpDriveConfig.isIndustrialCraft2Loaded) {
res = WarpDriveConfig.getModItemStack("IC2", "itemCable", -1);
res.setItemDamage(9);
res.stackSize = 2 + rand.nextInt(12);
isDone = true;
}
break;
case 7:// UU matter cell
if (WarpDriveConfig.isIndustrialCraft2Loaded) {
res = WarpDriveConfig.getModItemStack("IC2", "itemCellEmpty", -1);
res.setItemDamage(3);
res.stackSize = 2 + rand.nextInt(14);
isDone = true;
}
break;
case 8:
isDone = true;
break;// skipped
case 9:
case 10:
case 11: // Rocket launcher platform Tier3
if (WarpDriveConfig.isICBMLoaded) {
// TODO: No 1.7 ICBM yet
// res = new ItemStack(WarpDriveConfig.ICBM_Machine, 1 +
// rand.nextInt(1), 2).copy();
isDone = true;
}
break;
case 12: // Missiles from conventional to hypersonic
if (WarpDriveConfig.isICBMLoaded) {
// TODO: No 1.7 ICBM yet
// res = new ItemStack(WarpDriveConfig.ICBM_Missile, 2 +
// rand.nextInt(1), rand.nextInt(10)).copy();
isDone = true;
}
break;
case 13: // Advanced solar panels
if (WarpDriveConfig.isAdvancedSolarPanelLoaded) {
// TODO: res = new ItemStack(solarPanel_block, rand.nextInt(3), solarPanel_metadata);
isDone = true;
}
break;
default:
break;
}
}
return res;
}
}

View file

@ -2,6 +2,8 @@ package cr0s.warpdrive.world;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.GenericSet;
import cr0s.warpdrive.config.Loot;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.JumpBlock;
import cr0s.warpdrive.data.JumpShip;
@ -11,6 +13,9 @@ import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World;
@ -183,6 +188,49 @@ public class WorldGenStructure {
world.setBlock(x, y, z, resource_block, resource_metadata, 2);
}
public void fillInventoryWithLoot(final World worldObj, final Random rand, final int x, final int y, final int z, final String group) {
final TileEntity tileEntity = worldObj.getTileEntity(x, y, z);
if (tileEntity instanceof IInventory) {
final IInventory inventory = (IInventory) tileEntity;
final int size = inventory.getSizeInventory();
final int countLoots = Math.min(3 + rand.nextInt(3), size);
final GenericSet<Loot> lootSet = WarpDriveConfig.LootManager.getRandomSetFromGroup(rand, group);
if (lootSet == null) {
WarpDrive.logger.warn(String.format("No LootSet found with group %s for inventory @ DIM%d (%d %d %d): check your configuration",
group, worldObj.provider.dimensionId, x, y, z));
return;
}
// for all loots to add
int indexSlot;
ItemStack itemStackLoot;
boolean isAdded;
for (int i = 0; i < countLoots; i++) {
isAdded = false;
for (int countLootRetries = 0; countLootRetries < 3 && !isAdded; countLootRetries++) {
// pick a loot
itemStackLoot = lootSet.getRandomUnit(rand).getItemStack(rand);
// find a valid slot for it
for (int countSlotRetries = 0; countSlotRetries < 5 && !isAdded; countSlotRetries++) {
indexSlot = rand.nextInt(size);
if (inventory.isItemValidForSlot(indexSlot, itemStackLoot)) {
inventory.setInventorySlotContents(indexSlot, itemStackLoot);
isAdded = true;
}
}
}
if (!isAdded) {
WarpDrive.logger.info(String.format("Unable to find a valid loot from LootSet %s for inventory %s in @ DIM%d (%d %d %d): check your configuration",
lootSet.getFullName(),
inventory.getInventoryName() == null ? "-null name-" : inventory.getInventoryName(),
worldObj.provider.dimensionId, x, y, z));
}
}
}
}
public void generateFromFile(final World world, final String filename, final int targetX, final int targetY, final int targetZ, final byte rotationSteps) {
StringBuilder reason = new StringBuilder();
final JumpShip jumpShip = JumpShip.createFromFile(filename, reason);

View file

@ -43,6 +43,7 @@
<xs:complexType name="fillerElement">
<xs:attribute name="block" type="xs:string" use="required" />
<xs:attribute name="metadata" type="xs:string" use="optional" />
<xs:attribute name="nbt" type="xs:string" use="optional" />
<xs:attribute name="weight" type="xs:string" use="optional" />
<xs:attribute name="ratio" type="xs:string" use="optional" />
<xs:attribute name="mods" type="xs:string" use="optional" />
@ -100,7 +101,8 @@
<xs:complexType name="lootElement">
<xs:attribute name="item" type="xs:string" use="required" />
<xs:attribute name="metadata" type="xs:string" use="optional" />
<xs:attribute name="damage" type="xs:string" use="optional" />
<xs:attribute name="nbt" type="xs:string" use="optional" />
<xs:attribute name="minQuantity" type="xs:string" use="optional" />
<xs:attribute name="maxQuantity" type="xs:string" use="optional" />
<xs:attribute name="weight" type="xs:string" use="optional" />

View file

@ -2,7 +2,7 @@
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive warpDrive.xsd">
xsi:schemaLocation="WarpDrive WarpDrive.xsd">
<!--
An astronomical object or celestial object is a naturally occurring physical entity, association, or structure in the observable universe.

View file

@ -2,7 +2,7 @@
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive warpDrive.xsd">
xsi:schemaLocation="WarpDrive WarpDrive.xsd">
<celestialBody group="milkyWay" name="sun" isVirtual="true">
<dimension type="space" id="" centerX="" centerZ="" radiusX="" radiusZ="" />

View file

@ -2,7 +2,7 @@
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive warpDrive.xsd">
xsi:schemaLocation="WarpDrive WarpDrive.xsd">
<!-- all possible overworld ores, mostly for reference purpose -->
<fillerSet group="overworld_allOres" name="stone">

View file

@ -2,7 +2,7 @@
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive warpDrive.xsd"
xsi:schemaLocation="WarpDrive WarpDrive.xsd"
mods="netherores">
<!-- reference ratios

View file

@ -2,7 +2,7 @@
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive warpDrive.xsd"
xsi:schemaLocation="WarpDrive WarpDrive.xsd"
mods="UndergroundBiomes">
<for variable="type" in="igneous,metamorphic,sedimentary">

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive WarpDrive.xsd">
<!--
A lootSet is a list of possible loots.
loot.item is the registry name of the item. It's mandatory.
loot.damage is the damage level, also known as metadata. It defaults to 0.
loot.nbt is the NBT data in JSON format converted to XML. Here's a site to do the XML conversion part: http://coderstoolbox.net/string/#!encoding=xml&action=encode&charset=utf_8
loot.minQuantity is self explanatory. It defaults to 1.
loot.maxQuantity needs to be higher than loot.minQuantity to have any effect. It defaults to 1.
Here after is an example with NBT data.
<loot item="WarpDrive:itemCrystalToken" damage="5" nbt="{shipName:&quot;MySchematicName&quot;}" />
When used on machines, we'll give a few trials to find a valid slot for each loot, eventually try another loot, eventually skipping it altogether.
-->
<lootSet group="ship" name="legacy" weight="1">
<loot item="IC2:blockNuke" minQuantity="1" maxQuantity="3" weight="7" /> <!-- Nuke -->
<loot item="IC2:blockReactorChamber" minQuantity="1" maxQuantity="1" weight="5" /> <!-- Reactor chamber -->
<loot item="IC2:blockMachine2" damage="3" minQuantity="1" maxQuantity="1" weight="10" /> <!-- Thermal centrifuge -->
<loot item="IC2:blockMachine2" damage="4" minQuantity="1" maxQuantity="1" weight="10" /> <!-- Metal former -->
<loot item="IC2:blockMachine2" damage="5" minQuantity="1" maxQuantity="1" weight="10" /> <!-- Ore washing -->
<loot item="IC2:blockAlloy" minQuantity="7" maxQuantity="20" weight="10" /> <!-- Reinforced stone -->
<loot item="IC2:blockAlloyGlass" minQuantity="5" maxQuantity="12" weight="10" /> <!-- Reinforced glass -->
<loot item="IC2:blockIronScaffold" minQuantity="8" maxQuantity="35" weight="10" /> <!-- Iron scaffolding -->
<loot item="IC2:blockGenerator" damage="0" minQuantity="1" maxQuantity="3" weight="10" /> <!-- Generator -->
<loot item="IC2:blockGenerator" damage="2" minQuantity="1" maxQuantity="3" weight="10" /> <!-- Water mill -->
<loot item="IC2:blockGenerator" damage="3" minQuantity="1" maxQuantity="2" weight="10" /> <!-- Solar generator -->
<loot item="IC2:blockChargePad" damage="0" minQuantity="1" maxQuantity="2" weight="10" /> <!-- ChargePad (BatBox) -->
<loot item="IC2:blockChargePad" damage="1" minQuantity="1" maxQuantity="2" weight="10" /> <!-- ChargePad (CESU) -->
<loot item="IC2:blockChargePad" damage="2" minQuantity="1" maxQuantity="1" weight="5" /> <!-- ChargePad (MFE) -->
<loot item="IC2:blockChargePad" damage="3" minQuantity="1" maxQuantity="1" weight="1" /> <!-- ChargePad (MFSU) -->
<loot item="IC2:blockMachine" damage="0" minQuantity="1" maxQuantity="8" weight="15" /> <!-- Machine casing -->
<loot item="IC2:blockMachine" damage="5" minQuantity="1" maxQuantity="2" weight="15" /> <!-- Compressor -->
<loot item="IC2:blockMachine" damage="14" minQuantity="1" maxQuantity="1" weight="10" /> <!-- Mass fabricator -->
<loot item="IC2:itemArmorRubBoots" damage="20" minQuantity="1" maxQuantity="1" weight="5" /> <!-- Damaged rubber boots -->
<loot item="IC2:itemArmorRubBoots" damage="0" minQuantity="1" maxQuantity="1" weight="5" /> <!-- Rubber boots -->
<loot item="IC2:itemFuelRod" damage="0" minQuantity="1" maxQuantity="4" weight="10" /> <!-- Fuel rod -->
<loot item="IC2:itemRubber" minQuantity="5" maxQuantity="24" weight="15" /> <!-- Rubber -->
<loot item="IC2:itemPartCircuit" minQuantity="1" maxQuantity="5" weight="10" /> <!-- Basic circuit -->
<loot item="IC2:itemBatCrystal" minQuantity="1" maxQuantity="1" weight="12" /> <!-- Energy crytal -->
<loot item="IC2:itemCellEmpty" damage="0" minQuantity="4" maxQuantity="35" weight="15" /> <!-- Empty cell -->
<loot item="IC2:itemCellEmpty" damage="3" minQuantity="2" maxQuantity="16" weight="12" /> <!-- UU matter cell -->
<loot item="IC2:itemCellEmpty" damage="5" minQuantity="1" maxQuantity="18" weight="12" /> <!-- Compressed air -->
<loot item="IC2:itemCable" damage="0" minQuantity="1" maxQuantity="18" weight="15" /> <!-- Insulated copper cable -->
<loot item="IC2:itemCable" damage="1" minQuantity="1" maxQuantity="18" weight="12" /> <!-- Copper cable -->
<loot item="IC2:itemCable" damage="2" minQuantity="1" maxQuantity="18" weight="12" /> <!-- Gold cable -->
<loot item="IC2:itemCable" damage="3" minQuantity="1" maxQuantity="18" weight="13" /> <!-- Insulated gold cable -->
<loot item="IC2:itemCable" damage="5" minQuantity="1" maxQuantity="18" weight="8" /> <!-- HV cable -->
<loot item="IC2:itemCable" damage="6" minQuantity="1" maxQuantity="18" weight="10" /> <!-- Insulated HV cable -->
<loot item="IC2:itemCable" damage="9" minQuantity="1" maxQuantity="18" weight="8" /> <!-- Glass fiber cable -->
<loot item="IC2:itemCable" damage="10" minQuantity="1" maxQuantity="18" weight="15" /> <!-- Tin cable -->
<loot item="IC2:itemCable" damage="13" minQuantity="1" maxQuantity="18" weight="15" /> <!-- Insulated tin cable -->
<!-- nano armor? -->
<!-- ICBM rocket launcher platform minQuantity="1" maxQuantity="2" -->
<!-- ICBM missile damage=0 to 9 minQuantity="2" maxQuantity="3" -->
<!-- Advanced solar panel -->
</lootSet>
</worldGeneration>

View file

@ -3,7 +3,7 @@
<worldGeneration version="2"
xmlns="WarpDrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="WarpDrive warpDrive.xsd"
xsi:schemaLocation="WarpDrive WarpDrive.xsd"
mods="netherores">
<!-- Not implemented

View file

@ -91,8 +91,4 @@
<structure group="ship" name="legacy" ratio="0.2">
</structure>
<lootSet group="ship" name="default" weight="1">
<loot item="" metadata="" weight="" minQuantity="" maxQuantity="" />
</lootSet>
</worldGeneration>