Implemented schematic structure generation, and Mining laser fluid pumping
- finalized schematic support in structure generation, including blocks replacement and items insertions note: implementation is functional but not optimized. - added blockstate support for schematic insertions and replacements - added maxRetries to item Insertion to try other slots. - added fluid storage to mining laser pump upgrades, will still evaporate fluid if no tank was found.
This commit is contained in:
parent
474c756442
commit
b691306a71
8 changed files with 491 additions and 83 deletions
|
@ -7,9 +7,11 @@ import cr0s.warpdrive.block.TileEntityAbstractLaser;
|
||||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||||
import cr0s.warpdrive.data.FluidWrapper;
|
import cr0s.warpdrive.data.FluidWrapper;
|
||||||
import cr0s.warpdrive.data.InventoryWrapper;
|
import cr0s.warpdrive.data.InventoryWrapper;
|
||||||
|
import cr0s.warpdrive.data.TankWrapper;
|
||||||
import cr0s.warpdrive.data.Vector3;
|
import cr0s.warpdrive.data.Vector3;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -27,8 +29,9 @@ import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.util.SoundCategory;
|
import net.minecraft.util.SoundCategory;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.WorldServer;
|
import net.minecraft.world.WorldServer;
|
||||||
|
|
||||||
import net.minecraftforge.common.IPlantable;
|
import net.minecraftforge.common.IPlantable;
|
||||||
|
import net.minecraftforge.fluids.Fluid;
|
||||||
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
|
||||||
public abstract class TileEntityAbstractMiner extends TileEntityAbstractLaser {
|
public abstract class TileEntityAbstractMiner extends TileEntityAbstractLaser {
|
||||||
|
|
||||||
|
@ -55,11 +58,30 @@ public abstract class TileEntityAbstractMiner extends TileEntityAbstractLaser {
|
||||||
if (blockState.getBlock().isAir(blockState, world, blockPos)) {
|
if (blockState.getBlock().isAir(blockState, world, blockPos)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (FluidWrapper.isFluid(blockState)) {
|
|
||||||
// Evaporate fluid
|
final Fluid fluid = FluidWrapper.getFluid(blockState);
|
||||||
world.playSound(null, blockPos, net.minecraft.init.SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F,
|
if (fluid != null) {// (this is a fluid block)
|
||||||
2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
|
if ( WarpDriveConfig.MINING_LASER_PUMP_UPGRADE_HARVEST_FLUID
|
||||||
|
&& FluidWrapper.isSourceBlock(world, blockPos, blockState) ) {// (fluid collection is enabled & it's a source block)
|
||||||
|
final Collection<Object> connectedTanks = TankWrapper.getConnectedTanks(world, pos);
|
||||||
|
if (!connectedTanks.isEmpty()) {// (at least 1 tank is connected)
|
||||||
|
final FluidStack fluidStack = new FluidStack(fluid, 1000);
|
||||||
|
|
||||||
|
final boolean fluidOverflowed = TankWrapper.addToTanks(world, pos, connectedTanks, fluidStack);
|
||||||
|
if (fluidOverflowed) {
|
||||||
|
// assume player wants to collect the fluid, hence stop the mining in case of overflow
|
||||||
|
setIsEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect Fluid
|
||||||
|
world.playSound(null, blockPos, fluid.getFillSound(fluidStack), SoundCategory.BLOCKS, 0.5F,
|
||||||
|
2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Evaporate fluid
|
||||||
|
world.playSound(null, blockPos, net.minecraft.init.SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F,
|
||||||
|
2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
|
||||||
|
}
|
||||||
// remove without updating neighbours
|
// remove without updating neighbours
|
||||||
world.setBlockState(blockPos, Blocks.AIR.getDefaultState(), 2);
|
world.setBlockState(blockPos, Blocks.AIR.getDefaultState(), 2);
|
||||||
|
|
||||||
|
@ -78,14 +100,14 @@ public abstract class TileEntityAbstractMiner extends TileEntityAbstractLaser {
|
||||||
|
|
||||||
// try to replant the crop
|
// try to replant the crop
|
||||||
if ( itemStackDrops != null
|
if ( itemStackDrops != null
|
||||||
&& blockState.getBlock() instanceof IGrowable) {
|
&& blockState.getBlock() instanceof IGrowable ) {
|
||||||
for (final ItemStack itemStackPlant : itemStackDrops) {
|
for (final ItemStack itemStackPlant : itemStackDrops) {
|
||||||
if (itemStackPlant.getItem() instanceof IPlantable) {
|
if (itemStackPlant.getItem() instanceof IPlantable) {
|
||||||
final IPlantable plantable = (IPlantable) itemStackPlant.getItem();
|
final IPlantable plantable = (IPlantable) itemStackPlant.getItem();
|
||||||
final IBlockState blockStatePlant = plantable.getPlant(world, blockPos);
|
final IBlockState blockStatePlant = plantable.getPlant(world, blockPos);
|
||||||
if (WarpDriveConfig.LOGGING_COLLECTION) {
|
if (WarpDriveConfig.LOGGING_COLLECTION) {
|
||||||
WarpDrive.logger.info(String.format("Drop includes %s which is plantable %s as block %s",
|
WarpDrive.logger.info(String.format("Drop includes %s which is plantable %s as block %s",
|
||||||
itemStackPlant, plantable, blockStatePlant ));
|
itemStackPlant, plantable, blockStatePlant));
|
||||||
}
|
}
|
||||||
final BlockPos blockPosSoil = blockPos.down();
|
final BlockPos blockPosSoil = blockPos.down();
|
||||||
final IBlockState blockStateSoil = getWorld().getBlockState(blockPosSoil);
|
final IBlockState blockStateSoil = getWorld().getBlockState(blockPosSoil);
|
||||||
|
|
|
@ -430,6 +430,7 @@ public class WarpDriveConfig {
|
||||||
public static double MINING_LASER_MINE_SILKTOUCH_ENERGY_FACTOR = 1.5;
|
public static double MINING_LASER_MINE_SILKTOUCH_ENERGY_FACTOR = 1.5;
|
||||||
public static int MINING_LASER_MINE_SILKTOUCH_DEUTERIUM_MB = 0;
|
public static int MINING_LASER_MINE_SILKTOUCH_DEUTERIUM_MB = 0;
|
||||||
public static double MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR = 1.5;
|
public static double MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR = 1.5;
|
||||||
|
public static boolean MINING_LASER_PUMP_UPGRADE_HARVEST_FLUID = false;
|
||||||
|
|
||||||
// Laser tree farm
|
// Laser tree farm
|
||||||
// oak tree height is 8 to 11 logs + 2 leaves
|
// oak tree height is 8 to 11 logs + 2 leaves
|
||||||
|
@ -1258,6 +1259,7 @@ public class WarpDriveConfig {
|
||||||
MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR = Commons.clamp(0.01D, 1000.0D,
|
MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR = Commons.clamp(0.01D, 1000.0D,
|
||||||
config.get("mining_laser", "fortune_energy_factor", MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR, "Energy cost multiplier per fortune level").getDouble(MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR));
|
config.get("mining_laser", "fortune_energy_factor", MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR, "Energy cost multiplier per fortune level").getDouble(MINING_LASER_MINE_FORTUNE_ENERGY_FACTOR));
|
||||||
}
|
}
|
||||||
|
MINING_LASER_PUMP_UPGRADE_HARVEST_FLUID = config.get("mining_laser", "pump_upgrade_harvest_fluid", MINING_LASER_PUMP_UPGRADE_HARVEST_FLUID, "Pump upgrade will actually pump fluid source if a tank is found, instead of just evaporating it").getBoolean(false);
|
||||||
|
|
||||||
// Tree Farm
|
// Tree Farm
|
||||||
TREE_FARM_MAX_MEDIUMS_COUNT = Commons.clamp(1, 10,
|
TREE_FARM_MAX_MEDIUMS_COUNT = Commons.clamp(1, 10,
|
||||||
|
|
|
@ -7,12 +7,16 @@ import cr0s.warpdrive.config.InvalidXmlException;
|
||||||
import cr0s.warpdrive.config.Loot;
|
import cr0s.warpdrive.config.Loot;
|
||||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||||
import cr0s.warpdrive.config.XmlFileManager;
|
import cr0s.warpdrive.config.XmlFileManager;
|
||||||
|
import cr0s.warpdrive.data.JumpBlock;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.properties.IProperty;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -21,7 +25,7 @@ import org.w3c.dom.Element;
|
||||||
|
|
||||||
public class Schematic extends AbstractStructure {
|
public class Schematic extends AbstractStructure {
|
||||||
|
|
||||||
protected String filename;
|
protected HashMap<String, Integer> filenames;
|
||||||
protected Replacement[] replacements;
|
protected Replacement[] replacements;
|
||||||
protected Insertion[] insertions;
|
protected Insertion[] insertions;
|
||||||
|
|
||||||
|
@ -29,10 +33,57 @@ public class Schematic extends AbstractStructure {
|
||||||
super(group, name);
|
super(group, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRandomFileName(final Random random) {
|
||||||
|
|
||||||
|
// In loadFromXmlElement, it's already checked that there must be at least 1 "schematic" xml node
|
||||||
|
// therefore, this should not be possible
|
||||||
|
assert(!filenames.isEmpty());
|
||||||
|
|
||||||
|
int totalWeight = 0;
|
||||||
|
for (final int weight : filenames.values()) {
|
||||||
|
totalWeight += weight;
|
||||||
|
}
|
||||||
|
int result = random.nextInt(totalWeight);
|
||||||
|
for (final Map.Entry<String, Integer> entry : filenames.entrySet()) {
|
||||||
|
result -= entry.getValue();
|
||||||
|
if (result <= 0) {
|
||||||
|
return entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filenames.keySet().iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean generate(@Nonnull final World world, @Nonnull final Random random, @Nonnull final BlockPos blockPos) {
|
||||||
|
return instantiate(random).generate(world, random, blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractStructureInstance instantiate(final Random random) {
|
||||||
|
return new SchematicInstance(this, random);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
|
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
|
||||||
super.loadFromXmlElement(element);
|
super.loadFromXmlElement(element);
|
||||||
|
|
||||||
|
final List<Element> fileNameList = XmlFileManager.getChildrenElementByTagName(element, "schematic");
|
||||||
|
if (fileNameList.isEmpty()) {
|
||||||
|
throw new InvalidXmlException("Must have one schematic node with file name!");
|
||||||
|
}
|
||||||
|
this.filenames = new HashMap<>(fileNameList.size());
|
||||||
|
for (final Element entry : fileNameList) {
|
||||||
|
final String filename = entry.getAttribute("filename");
|
||||||
|
int weight = 1;
|
||||||
|
try {
|
||||||
|
weight = Integer.parseInt(entry.getAttribute("weight"));
|
||||||
|
} catch (final NumberFormatException numberFormatException) {
|
||||||
|
throw new InvalidXmlException(String.format("Invalid weight in schematic %s of structure %s:%s",
|
||||||
|
filename, group, name));
|
||||||
|
}
|
||||||
|
this.filenames.put(filename, weight);
|
||||||
|
}
|
||||||
|
|
||||||
// load all replacement elements
|
// load all replacement elements
|
||||||
final List<Element> listReplacements = XmlFileManager.getChildrenElementByTagName(element, "replacement");
|
final List<Element> listReplacements = XmlFileManager.getChildrenElementByTagName(element, "replacement");
|
||||||
replacements = new Replacement[listReplacements.size()];
|
replacements = new Replacement[listReplacements.size()];
|
||||||
|
@ -72,21 +123,143 @@ public class Schematic extends AbstractStructure {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
static class BlockMatcher {
|
||||||
public boolean generate(@Nonnull final World world, @Nonnull final Random random, @Nonnull final BlockPos blockPos) {
|
|
||||||
return instantiate(random).generate(world, random, blockPos);
|
IBlockState blockState;
|
||||||
}
|
|
||||||
|
public static BlockMatcher fromXmlElement(final Element element, final GenericSet<?> caller) throws InvalidXmlException{
|
||||||
@Override
|
final String blockStateString = element.getAttribute("blockState");
|
||||||
public AbstractStructureInstance instantiate(final Random random) {
|
final String blockNameString = element.getAttribute("block");
|
||||||
return new SchematicInstance(this, random);
|
final String metaString = element.getAttribute("metadata");
|
||||||
|
|
||||||
|
final BlockMatcher blockMatcher;
|
||||||
|
|
||||||
|
if(blockNameString.isEmpty()){
|
||||||
|
blockMatcher = BlockMatcher.fromBlockStateString(blockStateString);
|
||||||
|
}else {
|
||||||
|
blockMatcher = BlockMatcher.fromBlockAndMeta(blockNameString, metaString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockMatcher == null){
|
||||||
|
WarpDrive.logger.warn(String.format("Invalid matching scheme %s found for %s",
|
||||||
|
blockStateString.isEmpty() ? blockNameString + "@" + metaString : blockStateString,
|
||||||
|
caller.getFullName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockMatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockMatcher fromBlockStateString(final String blockStateString) {
|
||||||
|
// TODO: allow different data input type for meta: range (e.g. 2-13), comma separated list (e.g. 1,2,3..), multiple property (e.g. variant=oak,half=bottom)
|
||||||
|
|
||||||
|
final BlockMatcher result = new BlockMatcher();
|
||||||
|
|
||||||
|
String blockNameString = "";
|
||||||
|
String metaString = "*";
|
||||||
|
if (blockStateString.contains("@")) {// (with metadata)
|
||||||
|
final String[] blockStateParts = blockStateString.split("@");
|
||||||
|
blockNameString = blockStateParts[0].trim();
|
||||||
|
metaString = blockStateParts[1].trim();
|
||||||
|
} else {// (without metadata)
|
||||||
|
blockNameString = blockStateString;
|
||||||
|
}
|
||||||
|
final Block block = Block.getBlockFromName(blockNameString);
|
||||||
|
if (block == null) {
|
||||||
|
WarpDrive.logger.warn(String.format("Ignoring invalid block with name %s.", blockNameString));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (metaString.equals("*")) {// (no metadata or explicit wildcard)
|
||||||
|
result.blockState = block.getDefaultState();
|
||||||
|
} else if (metaString.contains("=")) {// (in string format (e.g. "color=red"))
|
||||||
|
final String[] metaParts = metaString.split("=");
|
||||||
|
final String propertyKey = metaParts[0].trim();
|
||||||
|
final String propertyValue = metaParts[1].trim();
|
||||||
|
final IProperty<? extends Comparable<?>> property = block.getBlockState().getProperty(propertyKey);
|
||||||
|
if (property == null) {
|
||||||
|
WarpDrive.logger.warn(String.format("Found invalid block property %s for block %s", propertyKey, blockNameString));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: the below code was attempted but not succeeded.
|
||||||
|
IBlockState#WithProperty require (T extends Comparable<?> property , V extend T value).
|
||||||
|
It is impossible to ensure V extend T because value returned from parseValue is itself <? extends Comparable<?>>
|
||||||
|
Therefore, T may only be determined at runtime, and V extend T may not be enforced.
|
||||||
|
|
||||||
|
Optional<? extends Comparable<?>> parsedValue = property.parseValue(propertyValue);
|
||||||
|
if (result.isPresent()){
|
||||||
|
result.blockState = block.getDefaultState().withProperty(property, parsedValue.get());
|
||||||
|
}else{
|
||||||
|
WarpDrive.logger.warn(String.format("Value %s is not allowed for property %s for block %s", propertyValue, propertyKey, state));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < 16; i++) {// not efficient, but this would work (and since it's load time, it should not be a problem)
|
||||||
|
final IBlockState tmpState = block.getStateFromMeta(i);
|
||||||
|
if (tmpState.getProperties().get(property).equals(property.parseValue(propertyValue).orNull())) {
|
||||||
|
result.blockState = tmpState;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
WarpDrive.logger.warn(String.format("Failed to find metadata value that represent block property %s for block %s", propertyKey, blockNameString));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {// (metadata)
|
||||||
|
final int metadata;
|
||||||
|
try {
|
||||||
|
metadata = Integer.parseInt(metaString);
|
||||||
|
} catch (final NumberFormatException numberFormatException) {
|
||||||
|
WarpDrive.logger.warn(String.format("%s is not a valid number for metadata of block %s", metaString, blockNameString));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
result.blockState = block.getStateFromMeta(metadata);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockMatcher fromBlockAndMeta(final String blockName, final String metaString) {
|
||||||
|
final BlockMatcher result = new BlockMatcher();
|
||||||
|
|
||||||
|
final Block block = Block.getBlockFromName(blockName);
|
||||||
|
if (block == null) {
|
||||||
|
WarpDrive.logger.warn(String.format("Found invalid block %s", blockName));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!metaString.isEmpty()) {
|
||||||
|
try {
|
||||||
|
final int meta = Integer.parseInt(metaString);
|
||||||
|
result.blockState = block.getStateFromMeta(meta);
|
||||||
|
} catch (final NumberFormatException numberFormatException) {
|
||||||
|
WarpDrive.logger.warn(String.format("%s is not a valid number for meta of block %s", metaString, blockName));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMatching(final IBlockState blockStateIn) {
|
||||||
|
return blockStateIn.equals(blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMatching(final JumpBlock jumpBlockIn) {
|
||||||
|
return blockState != null && jumpBlockIn != null && jumpBlockIn.blockMeta == blockState.getBlock().getMetaFromState(blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BlockMatcher{" + (blockState == null ? "null" : blockState.toString()) + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Replacement extends GenericSet<Filler> {
|
public static class Replacement extends GenericSet<Filler> {
|
||||||
|
|
||||||
private final String parentFullName;
|
private final String parentFullName;
|
||||||
protected Block block;
|
protected BlockMatcher matcher;
|
||||||
protected IBlockState blockState;
|
|
||||||
|
|
||||||
public Replacement(final String parentFullName, final String name) {
|
public Replacement(final String parentFullName, final String name) {
|
||||||
super(null, name, Filler.DEFAULT, "filler");
|
super(null, name, Filler.DEFAULT, "filler");
|
||||||
|
@ -95,13 +268,15 @@ public class Schematic extends AbstractStructure {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
|
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
|
||||||
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
|
||||||
WarpDrive.logger.info(String.format(" + found replacement %s",
|
|
||||||
element.getAttribute("name")));
|
|
||||||
}
|
|
||||||
|
|
||||||
super.loadFromXmlElement(element);
|
super.loadFromXmlElement(element);
|
||||||
|
|
||||||
|
matcher = BlockMatcher.fromXmlElement(element, this);
|
||||||
|
|
||||||
|
if ( WarpDriveConfig.LOGGING_WORLD_GENERATION
|
||||||
|
&& matcher != null ) {
|
||||||
|
WarpDrive.logger.info(String.format(" + found replacement for block %s", matcher));
|
||||||
|
}
|
||||||
|
|
||||||
// resolve static imports
|
// resolve static imports
|
||||||
for (final String importGroupName : getImportGroupNames()) {
|
for (final String importGroupName : getImportGroupNames()) {
|
||||||
final GenericSet<Filler> fillerSet = WarpDriveConfig.FillerManager.getGenericSet(importGroupName);
|
final GenericSet<Filler> fillerSet = WarpDriveConfig.FillerManager.getGenericSet(importGroupName);
|
||||||
|
@ -126,8 +301,7 @@ public class Schematic extends AbstractStructure {
|
||||||
|
|
||||||
public Replacement instantiate(final Random random) {
|
public Replacement instantiate(final Random random) {
|
||||||
final Replacement replacement = new Replacement(parentFullName, name);
|
final Replacement replacement = new Replacement(parentFullName, name);
|
||||||
replacement.block = block;
|
replacement.matcher = this.matcher;
|
||||||
replacement.blockState = blockState;
|
|
||||||
try {
|
try {
|
||||||
replacement.loadFrom(this);
|
replacement.loadFrom(this);
|
||||||
for (final String importGroup : getImportGroups()) {
|
for (final String importGroup : getImportGroups()) {
|
||||||
|
@ -159,18 +333,21 @@ public class Schematic extends AbstractStructure {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMatching(final IBlockState blockStateIn) {
|
public boolean isMatching(final IBlockState blockStateIn) {
|
||||||
return (block != null && block == blockStateIn.getBlock())
|
return matcher != null && matcher.isMatching(blockStateIn);
|
||||||
|| blockState.equals(blockStateIn);
|
}
|
||||||
|
|
||||||
|
public boolean isMatching(final JumpBlock jumpBlockIn) {
|
||||||
|
return matcher != null && matcher.isMatching(jumpBlockIn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Insertion extends GenericSet<Loot> {
|
public static class Insertion extends GenericSet<Loot> {
|
||||||
|
|
||||||
private final String parentFullName;
|
private final String parentFullName;
|
||||||
|
protected BlockMatcher matcher;
|
||||||
private int minQuantity;
|
private int minQuantity;
|
||||||
private int maxQuantity;
|
private int maxQuantity;
|
||||||
protected Block block;
|
private int maxRetries;
|
||||||
protected IBlockState blockState;
|
|
||||||
|
|
||||||
public Insertion(final String parentFullName, final String name) {
|
public Insertion(final String parentFullName, final String name) {
|
||||||
super(null, name, Loot.DEFAULT, "loot");
|
super(null, name, Loot.DEFAULT, "loot");
|
||||||
|
@ -179,13 +356,15 @@ public class Schematic extends AbstractStructure {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
|
public boolean loadFromXmlElement(final Element element) throws InvalidXmlException {
|
||||||
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
|
||||||
WarpDrive.logger.info(String.format(" + found insertion %s",
|
|
||||||
element.getAttribute("name")));
|
|
||||||
}
|
|
||||||
|
|
||||||
super.loadFromXmlElement(element);
|
super.loadFromXmlElement(element);
|
||||||
|
|
||||||
|
matcher = BlockMatcher.fromXmlElement(element, this);
|
||||||
|
|
||||||
|
if ( WarpDriveConfig.LOGGING_WORLD_GENERATION
|
||||||
|
&& matcher != null ) {
|
||||||
|
WarpDrive.logger.info(String.format(" + found insertion for block %s", matcher));
|
||||||
|
}
|
||||||
|
|
||||||
// get optional minQuantity attribute, defaulting to 0
|
// get optional minQuantity attribute, defaulting to 0
|
||||||
minQuantity = 0;
|
minQuantity = 0;
|
||||||
final String stringMinQuantity = element.getAttribute("minQuantity");
|
final String stringMinQuantity = element.getAttribute("minQuantity");
|
||||||
|
@ -200,6 +379,13 @@ public class Schematic extends AbstractStructure {
|
||||||
maxQuantity = Integer.parseInt(stringMaxQuantity);
|
maxQuantity = Integer.parseInt(stringMaxQuantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get optional maxTries attribute, defaulting to 3 according to WorldGenStructure#fillInventoryWithLoot
|
||||||
|
maxRetries = 3;
|
||||||
|
final String stringMaxTries = element.getAttribute("maxRetries");
|
||||||
|
if (!stringMaxTries.isEmpty()) {
|
||||||
|
maxRetries = Integer.parseInt(stringMaxTries);
|
||||||
|
}
|
||||||
|
|
||||||
// resolve static imports
|
// resolve static imports
|
||||||
for (final String importGroupName : getImportGroupNames()) {
|
for (final String importGroupName : getImportGroupNames()) {
|
||||||
final GenericSet<Loot> lootSet = WarpDriveConfig.LootManager.getGenericSet(importGroupName);
|
final GenericSet<Loot> lootSet = WarpDriveConfig.LootManager.getGenericSet(importGroupName);
|
||||||
|
@ -226,8 +412,8 @@ public class Schematic extends AbstractStructure {
|
||||||
final Insertion insertion = new Insertion(parentFullName, name);
|
final Insertion insertion = new Insertion(parentFullName, name);
|
||||||
insertion.minQuantity = minQuantity;
|
insertion.minQuantity = minQuantity;
|
||||||
insertion.maxQuantity = maxQuantity;
|
insertion.maxQuantity = maxQuantity;
|
||||||
insertion.block = block;
|
insertion.maxRetries = maxRetries;
|
||||||
insertion.blockState = blockState;
|
insertion.matcher = matcher;
|
||||||
try {
|
try {
|
||||||
insertion.loadFrom(this);
|
insertion.loadFrom(this);
|
||||||
for (final String importGroup : getImportGroups()) {
|
for (final String importGroup : getImportGroups()) {
|
||||||
|
@ -238,7 +424,7 @@ public class Schematic extends AbstractStructure {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
||||||
WarpDrive.logger.info(String.format("Filling %s:%s with %s:%s",
|
WarpDrive.logger.info(String.format("Inserting %s:%s with %s:%s",
|
||||||
parentFullName, name, importGroup, lootSet.getName()));
|
parentFullName, name, importGroup, lootSet.getName()));
|
||||||
}
|
}
|
||||||
insertion.loadFrom(lootSet);
|
insertion.loadFrom(lootSet);
|
||||||
|
@ -258,9 +444,24 @@ public class Schematic extends AbstractStructure {
|
||||||
return insertion;
|
return insertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMinQuantity() {
|
||||||
|
return minQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxQuantity() {
|
||||||
|
return maxQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxRetries() {
|
||||||
|
return maxRetries;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMatching(final IBlockState blockStateIn) {
|
public boolean isMatching(final IBlockState blockStateIn) {
|
||||||
return (block != null && block == blockStateIn.getBlock())
|
return matcher != null && matcher.isMatching(blockStateIn);
|
||||||
|| blockState.equals(blockStateIn);
|
}
|
||||||
|
|
||||||
|
public boolean isMatching(final JumpBlock jumpBlockIn) {
|
||||||
|
return matcher != null && matcher.isMatching(jumpBlockIn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@ package cr0s.warpdrive.config.structures;
|
||||||
import cr0s.warpdrive.Commons;
|
import cr0s.warpdrive.Commons;
|
||||||
import cr0s.warpdrive.WarpDrive;
|
import cr0s.warpdrive.WarpDrive;
|
||||||
import cr0s.warpdrive.api.WarpDriveText;
|
import cr0s.warpdrive.api.WarpDriveText;
|
||||||
|
import cr0s.warpdrive.config.Filler;
|
||||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||||
import cr0s.warpdrive.config.structures.Schematic.Insertion;
|
import cr0s.warpdrive.config.structures.Schematic.Insertion;
|
||||||
import cr0s.warpdrive.config.structures.Schematic.Replacement;
|
import cr0s.warpdrive.config.structures.Schematic.Replacement;
|
||||||
|
import cr0s.warpdrive.data.JumpBlock;
|
||||||
import cr0s.warpdrive.data.JumpShip;
|
import cr0s.warpdrive.data.JumpShip;
|
||||||
import cr0s.warpdrive.world.WorldGenStructure;
|
import cr0s.warpdrive.world.WorldGenStructure;
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ public class SchematicInstance extends AbstractStructureInstance {
|
||||||
super(schematic, random);
|
super(schematic, random);
|
||||||
|
|
||||||
final WarpDriveText reason = new WarpDriveText();
|
final WarpDriveText reason = new WarpDriveText();
|
||||||
jumpShip = JumpShip.createFromFile(schematic.filename, reason);
|
jumpShip = JumpShip.createFromFile(schematic.getRandomFileName(random), reason);
|
||||||
if (jumpShip == null) {
|
if (jumpShip == null) {
|
||||||
WarpDrive.logger.error(String.format("Failed to instantiate schematic structure %s due to %s",
|
WarpDrive.logger.error(String.format("Failed to instantiate schematic structure %s due to %s",
|
||||||
schematic.getFullName(), reason));
|
schematic.getFullName(), reason));
|
||||||
|
@ -45,7 +47,7 @@ public class SchematicInstance extends AbstractStructureInstance {
|
||||||
|
|
||||||
insertions = new Insertion[schematic.insertions.length];
|
insertions = new Insertion[schematic.insertions.length];
|
||||||
int insertionIndexOut = 0;
|
int insertionIndexOut = 0;
|
||||||
for (int insertionIndexIn = 0; insertionIndexIn < schematic.replacements.length; insertionIndexIn++) {
|
for (int insertionIndexIn = 0; insertionIndexIn < schematic.insertions.length; insertionIndexIn++) {
|
||||||
final Insertion insertion = schematic.insertions[insertionIndexIn].instantiate(random);
|
final Insertion insertion = schematic.insertions[insertionIndexIn].instantiate(random);
|
||||||
if (insertion != null) {
|
if (insertion != null) {
|
||||||
insertions[insertionIndexOut] = insertion;
|
insertions[insertionIndexOut] = insertion;
|
||||||
|
@ -72,11 +74,26 @@ public class SchematicInstance extends AbstractStructureInstance {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (final Replacement replacement : this.replacements) {
|
||||||
|
// Pick a common replacement block to get an homogenous result
|
||||||
|
final Filler filler = replacement.getRandomUnit(random);
|
||||||
|
|
||||||
|
// loop through the structure and see if a block need to be replaced
|
||||||
|
for (int i = 0; i < jumpShip.jumpBlocks.length; i++) {
|
||||||
|
if (replacement.isMatching(jumpShip.jumpBlocks[i])) {
|
||||||
|
jumpShip.jumpBlocks[i] = new JumpBlock(filler,
|
||||||
|
jumpShip.jumpBlocks[i].x,
|
||||||
|
jumpShip.jumpBlocks[i].y,
|
||||||
|
jumpShip.jumpBlocks[i].z );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final int y2 = Commons.clamp(
|
final int y2 = Commons.clamp(
|
||||||
WarpDriveConfig.SPACE_GENERATOR_Y_MIN_BORDER + (jumpShip.core.getY() - jumpShip.minY),
|
WarpDriveConfig.SPACE_GENERATOR_Y_MIN_BORDER + (jumpShip.core.getY() - jumpShip.minY),
|
||||||
WarpDriveConfig.SPACE_GENERATOR_Y_MAX_BORDER - (jumpShip.maxY - jumpShip.core.getY()),
|
WarpDriveConfig.SPACE_GENERATOR_Y_MAX_BORDER - (jumpShip.maxY - jumpShip.core.getY()),
|
||||||
blockPos.getY() );
|
blockPos.getY() );
|
||||||
new WorldGenStructure(random.nextFloat() < 0.2F, random).deployShip(world, jumpShip, blockPos.getX(), y2, blockPos.getZ(), (byte) 0);
|
new WorldGenStructure(random.nextFloat() < 0.2F, random).deployShip(world, jumpShip, blockPos.getX(), y2, blockPos.getZ(), (byte) 0, insertions);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,11 @@ public class InventoryWrapper {
|
||||||
} else if (inventory instanceof IItemHandler) {
|
} else if (inventory instanceof IItemHandler) {
|
||||||
qtyLeft = addToInventory(itemStack, (IItemHandler) inventory);
|
qtyLeft = addToInventory(itemStack, (IItemHandler) inventory);
|
||||||
} else {
|
} else {
|
||||||
WarpDrive.logger.error(String.format("Invalid inventory type %s, please report to mod author: %s",
|
if (Commons.throttleMe("addToInventories")){
|
||||||
Commons.format(world, blockPos), inventory ));
|
WarpDrive.logger.error(String.format("Invalid inventory type %s of class %s at %s, please report to mod author",
|
||||||
|
inventory, inventory.getClass(), Commons.format(world, blockPos) ));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (qtyLeft > 0) {
|
if (qtyLeft > 0) {
|
||||||
if (itemStackLeft == itemStack) {
|
if (itemStackLeft == itemStack) {
|
||||||
|
@ -141,7 +144,7 @@ public class InventoryWrapper {
|
||||||
}
|
}
|
||||||
if (qtyLeft > 0) {
|
if (qtyLeft > 0) {
|
||||||
if (WarpDriveConfig.LOGGING_COLLECTION) {
|
if (WarpDriveConfig.LOGGING_COLLECTION) {
|
||||||
WarpDrive.logger.info(String.format("Overflow detected %s",
|
WarpDrive.logger.info(String.format("Overflow detected at %s",
|
||||||
Commons.format(world, blockPos) ));
|
Commons.format(world, blockPos) ));
|
||||||
}
|
}
|
||||||
overflow = true;
|
overflow = true;
|
||||||
|
|
132
src/main/java/cr0s/warpdrive/data/TankWrapper.java
Normal file
132
src/main/java/cr0s/warpdrive/data/TankWrapper.java
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
package cr0s.warpdrive.data;
|
||||||
|
|
||||||
|
import cr0s.warpdrive.Commons;
|
||||||
|
import cr0s.warpdrive.WarpDrive;
|
||||||
|
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.EnumFacing;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.BlockPos.MutableBlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
import net.minecraftforge.fluids.IFluidTank;
|
||||||
|
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||||
|
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// this is almost a copy of InventoryWrapper, but for fluids.
|
||||||
|
|
||||||
|
public class TankWrapper {
|
||||||
|
|
||||||
|
// WarpDrive methods
|
||||||
|
public static boolean isTank(final TileEntity tileEntity, final EnumFacing facing) {
|
||||||
|
boolean isTank = false;
|
||||||
|
|
||||||
|
if (tileEntity instanceof IFluidTank) {
|
||||||
|
isTank = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTank
|
||||||
|
&& tileEntity.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, facing)) {
|
||||||
|
isTank = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isTank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getTank(final TileEntity tileEntity, final EnumFacing facing) {
|
||||||
|
if (tileEntity instanceof IFluidTank) {
|
||||||
|
return tileEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileEntity != null) {
|
||||||
|
return tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, facing);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nonnull Collection<Object> getConnectedTanks(final World world, final BlockPos blockPos) {
|
||||||
|
final Collection<Object> result = new ArrayList<>(6);
|
||||||
|
final Collection<IFluidHandler> resultCapabilities = new ArrayList<>(6);
|
||||||
|
final MutableBlockPos mutableBlockPos = new MutableBlockPos();
|
||||||
|
|
||||||
|
for (final EnumFacing side : EnumFacing.VALUES) {
|
||||||
|
mutableBlockPos.setPos(blockPos.getX() + side.getXOffset(),
|
||||||
|
blockPos.getY() + side.getYOffset(),
|
||||||
|
blockPos.getZ() + side.getZOffset());
|
||||||
|
final TileEntity tileEntity = world.getTileEntity(mutableBlockPos);
|
||||||
|
|
||||||
|
if (tileEntity instanceof IFluidTank) {
|
||||||
|
result.add(tileEntity);
|
||||||
|
} else if (tileEntity != null) {
|
||||||
|
final IFluidHandler fluidHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side);
|
||||||
|
if (fluidHandler != null) {
|
||||||
|
resultCapabilities.add(fluidHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addAll(resultCapabilities);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean addToConnectedTanks(final World world, final BlockPos blockPos, final FluidStack fluidStack) {
|
||||||
|
final List<FluidStack> fluidStacks = new ArrayList<>(1);
|
||||||
|
fluidStacks.add(fluidStack);
|
||||||
|
return addToConnectedTanks(world, blockPos, fluidStacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean addToConnectedTanks(final World world, final BlockPos blockPos, final List<FluidStack> fluidStacks) {
|
||||||
|
final Collection<Object> inventories = getConnectedTanks(world, blockPos);
|
||||||
|
return addToTanks(world, blockPos, inventories, fluidStacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean addToTanks(final World world, final BlockPos blockPos,
|
||||||
|
final Collection<Object> tanks, final FluidStack fluidStack) {
|
||||||
|
final List<FluidStack> fluidStacks = new ArrayList<>(1);
|
||||||
|
fluidStacks.add(fluidStack);
|
||||||
|
|
||||||
|
return addToTanks(world, blockPos, tanks, fluidStacks);
|
||||||
|
}
|
||||||
|
public static boolean addToTanks(final World world, final BlockPos blockPos,
|
||||||
|
final Collection<Object> tanks, final List<FluidStack> fluidStacks) {
|
||||||
|
boolean overflow = false;
|
||||||
|
if (fluidStacks != null) {
|
||||||
|
for (final FluidStack fluidStack : fluidStacks) {
|
||||||
|
int qtyFilled = 0;
|
||||||
|
for (final Object tank : tanks) {
|
||||||
|
if (tank instanceof IFluidTank) {
|
||||||
|
qtyFilled = ((IFluidTank) tank).fill(fluidStack, true);
|
||||||
|
} else if (tank instanceof IFluidHandler) {
|
||||||
|
qtyFilled = ((IFluidHandler) tank).fill(fluidStack, true);
|
||||||
|
} else {
|
||||||
|
if (Commons.throttleMe("addToTanks")){
|
||||||
|
WarpDrive.logger.error(String.format("Invalid fluid tank type %s of class %s at %s, please report to mod author",
|
||||||
|
tank, tank.getClass(), Commons.format(world, blockPos) ));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fluidStack.amount > qtyFilled) {
|
||||||
|
fluidStack.amount -= qtyFilled;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fluidStack.amount > qtyFilled) {
|
||||||
|
if (WarpDriveConfig.LOGGING_COLLECTION) {
|
||||||
|
WarpDrive.logger.info(String.format("Tank overflow detected at %s",
|
||||||
|
Commons.format(world, blockPos)));
|
||||||
|
}
|
||||||
|
overflow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import cr0s.warpdrive.config.Filler;
|
||||||
import cr0s.warpdrive.config.GenericSet;
|
import cr0s.warpdrive.config.GenericSet;
|
||||||
import cr0s.warpdrive.config.Loot;
|
import cr0s.warpdrive.config.Loot;
|
||||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||||
|
import cr0s.warpdrive.config.structures.Schematic.Insertion;
|
||||||
import cr0s.warpdrive.data.InventoryWrapper;
|
import cr0s.warpdrive.data.InventoryWrapper;
|
||||||
import cr0s.warpdrive.data.JumpBlock;
|
import cr0s.warpdrive.data.JumpBlock;
|
||||||
import cr0s.warpdrive.data.JumpShip;
|
import cr0s.warpdrive.data.JumpShip;
|
||||||
|
@ -18,6 +19,8 @@ import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -200,29 +203,6 @@ public class WorldGenStructure {
|
||||||
public void fillInventoryWithLoot(final World world, final Random rand, final BlockPos blockPos, final String group,
|
public void fillInventoryWithLoot(final World world, final Random rand, final BlockPos blockPos, final String group,
|
||||||
final int quantityMin, final int quantityRandom1, final int quantityRandom2,
|
final int quantityMin, final int quantityRandom1, final int quantityRandom2,
|
||||||
final int maxRetries) {
|
final int maxRetries) {
|
||||||
// validate context
|
|
||||||
final TileEntity tileEntity = world.getTileEntity(blockPos);
|
|
||||||
final Object inventory = InventoryWrapper.getInventory(tileEntity, null);
|
|
||||||
|
|
||||||
if (inventory == null) {
|
|
||||||
WarpDrive.logger.warn(String.format("Unable to fill inventory with LootSet %s %s: %s has no inventory",
|
|
||||||
group,
|
|
||||||
Commons.format(world, blockPos),
|
|
||||||
tileEntity ));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tileEntity.isInvalid()) {
|
|
||||||
WarpDrive.logger.warn(String.format("Unable to fill inventory with LootSet %s %s: %s is Invalid",
|
|
||||||
group,
|
|
||||||
Commons.format(world, blockPos),
|
|
||||||
tileEntity ));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// evaluate parameters: quantity of loot, actual loot set
|
|
||||||
final int size = InventoryWrapper.getSize(inventory);
|
|
||||||
final int countLoots = Math.min(quantityMin + rand.nextInt(quantityRandom1) + rand.nextInt(quantityRandom2), size);
|
|
||||||
|
|
||||||
final GenericSet<Loot> lootSet = WarpDriveConfig.LootManager.getRandomSetFromGroup(rand, group);
|
final GenericSet<Loot> lootSet = WarpDriveConfig.LootManager.getRandomSetFromGroup(rand, group);
|
||||||
if (lootSet == null) {
|
if (lootSet == null) {
|
||||||
|
@ -233,6 +213,36 @@ public class WorldGenStructure {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fillInventoryWithLoot(world, rand, blockPos, lootSet, quantityMin, quantityRandom1, quantityRandom2, maxRetries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fillInventoryWithLoot(final World world, final Random rand, final BlockPos blockPos, final GenericSet<Loot> lootSet,
|
||||||
|
final int quantityMin, final int quantityRandom1, final int quantityRandom2,
|
||||||
|
final int maxRetries) {
|
||||||
|
// validate context
|
||||||
|
final TileEntity tileEntity = world.getTileEntity(blockPos);
|
||||||
|
final Object inventory = InventoryWrapper.getInventory(tileEntity, null);
|
||||||
|
|
||||||
|
if (inventory == null) {
|
||||||
|
WarpDrive.logger.warn(String.format("Unable to fill inventory with LootSet %s %s: %s has no inventory",
|
||||||
|
lootSet.getFullName(),
|
||||||
|
Commons.format(world, blockPos),
|
||||||
|
tileEntity ));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileEntity.isInvalid()) {
|
||||||
|
WarpDrive.logger.warn(String.format("Unable to fill inventory with LootSet %s %s: %s is Invalid",
|
||||||
|
lootSet.getFullName(),
|
||||||
|
Commons.format(world, blockPos),
|
||||||
|
tileEntity ));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate parameters: quantity of loot, actual loot set
|
||||||
|
final int size = InventoryWrapper.getSize(inventory);
|
||||||
|
final int countLoots = Math.min(quantityMin + rand.nextInt(quantityRandom1) + rand.nextInt(quantityRandom2), size);
|
||||||
|
|
||||||
// shuffle slot indexes to reduce random calls and loops later on
|
// shuffle slot indexes to reduce random calls and loops later on
|
||||||
final ArrayList<Integer> indexSlots = new ArrayList<>(size);
|
final ArrayList<Integer> indexSlots = new ArrayList<>(size);
|
||||||
for (int indexSlot = 0; indexSlot < size; indexSlot++) {
|
for (int indexSlot = 0; indexSlot < size; indexSlot++) {
|
||||||
|
@ -243,6 +253,14 @@ public class WorldGenStructure {
|
||||||
}
|
}
|
||||||
Collections.shuffle(indexSlots);
|
Collections.shuffle(indexSlots);
|
||||||
|
|
||||||
|
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
||||||
|
WarpDrive.logger.debug(String.format("About to add %d loots from set %s into inventory %s at %s with max retries %d for each",
|
||||||
|
countLoots,
|
||||||
|
lootSet.getFullName(),
|
||||||
|
inventory,
|
||||||
|
Commons.format(world, blockPos),
|
||||||
|
maxRetries));
|
||||||
|
}
|
||||||
// for all loots to add
|
// for all loots to add
|
||||||
ItemStack itemStackLoot;
|
ItemStack itemStackLoot;
|
||||||
boolean isAdded;
|
boolean isAdded;
|
||||||
|
@ -267,23 +285,15 @@ public class WorldGenStructure {
|
||||||
try {
|
try {
|
||||||
InventoryWrapper.insertItem(inventory, indexSlot, itemStackLoot);
|
InventoryWrapper.insertItem(inventory, indexSlot, itemStackLoot);
|
||||||
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
if (WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
||||||
WarpDrive.logger.debug(String.format("Filling inventory with LootSet %s %s: loot %s from %s in slot %d of inventory %s",
|
WarpDrive.logger.debug(String.format(" + placed %s into slot %d",
|
||||||
group,
|
|
||||||
Commons.format(world, blockPos),
|
|
||||||
Commons.format(itemStackLoot),
|
Commons.format(itemStackLoot),
|
||||||
lootSet.getFullName(),
|
indexSlot));
|
||||||
indexSlot,
|
|
||||||
inventory ));
|
|
||||||
}
|
}
|
||||||
} catch (final Exception exception) {
|
} catch (final Exception exception) {
|
||||||
exception.printStackTrace(WarpDrive.printStreamError);
|
exception.printStackTrace(WarpDrive.printStreamError);
|
||||||
WarpDrive.logger.error(String.format("Exception while filling inventory with LootSet %s %s: loot %s from %s in slot %d of inventory %s reported %s",
|
WarpDrive.logger.error(String.format(" ! Exception while placing %s into slot %d: %s",
|
||||||
group,
|
|
||||||
Commons.format(world, blockPos),
|
|
||||||
Commons.format(itemStackLoot),
|
Commons.format(itemStackLoot),
|
||||||
lootSet.getFullName(),
|
|
||||||
indexSlot,
|
indexSlot,
|
||||||
inventory,
|
|
||||||
exception.getMessage() ));
|
exception.getMessage() ));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -313,6 +323,10 @@ public class WorldGenStructure {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deployShip(final World world, final JumpShip jumpShip, final int targetX, final int targetY, final int targetZ, final byte rotationSteps) {
|
public void deployShip(final World world, final JumpShip jumpShip, final int targetX, final int targetY, final int targetZ, final byte rotationSteps) {
|
||||||
|
deployShip(world, jumpShip, targetX, targetY, targetZ, rotationSteps, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deployShip(final World world, final JumpShip jumpShip, final int targetX, final int targetY, final int targetZ, final byte rotationSteps, @Nullable final Insertion[] insertions) {
|
||||||
|
|
||||||
final Transformation transformation = new Transformation(jumpShip, world,
|
final Transformation transformation = new Transformation(jumpShip, world,
|
||||||
targetX - jumpShip.core.getX(),
|
targetX - jumpShip.core.getX(),
|
||||||
|
@ -336,7 +350,6 @@ public class WorldGenStructure {
|
||||||
WarpDrive.logger.info(String.format("At index %d, skipping anchor block %s", index, jumpBlock.block));
|
WarpDrive.logger.info(String.format("At index %d, skipping anchor block %s", index, jumpBlock.block));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
index++;
|
|
||||||
if (WarpDrive.isDev && WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
if (WarpDrive.isDev && WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
||||||
WarpDrive.logger.info(String.format("At index %d, deploying %s ",
|
WarpDrive.logger.info(String.format("At index %d, deploying %s ",
|
||||||
index, jumpBlock));
|
index, jumpBlock));
|
||||||
|
@ -345,6 +358,23 @@ public class WorldGenStructure {
|
||||||
final Block blockAtTarget = world.getBlockState(targetLocation).getBlock();
|
final Block blockAtTarget = world.getBlockState(targetLocation).getBlock();
|
||||||
if (blockAtTarget == Blocks.AIR || Dictionary.BLOCKS_EXPANDABLE.contains(blockAtTarget)) {
|
if (blockAtTarget == Blocks.AIR || Dictionary.BLOCKS_EXPANDABLE.contains(blockAtTarget)) {
|
||||||
jumpBlock.deploy(null, world, transformation);
|
jumpBlock.deploy(null, world, transformation);
|
||||||
|
|
||||||
|
// Apply insertions as defined
|
||||||
|
if (insertions != null) {
|
||||||
|
for(final Insertion insertion : insertions){
|
||||||
|
if (insertion.isMatching(jumpBlock)){
|
||||||
|
final BlockPos deployedLocation = transformation.apply(jumpBlock.x, jumpBlock.y, jumpBlock.z);
|
||||||
|
|
||||||
|
fillInventoryWithLoot(world, rand, deployedLocation,
|
||||||
|
insertion,
|
||||||
|
insertion.getMinQuantity(),
|
||||||
|
insertion.getMaxQuantity(),
|
||||||
|
0,
|
||||||
|
insertion.getMaxRetries() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (WarpDrive.isDev && WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
if (WarpDrive.isDev && WarpDriveConfig.LOGGING_WORLD_GENERATION) {
|
||||||
WarpDrive.logger.info(String.format("Deployment collision detected %s with %s during world generation, skipping this block...",
|
WarpDrive.logger.info(String.format("Deployment collision detected %s with %s during world generation, skipping this block...",
|
||||||
|
|
|
@ -107,6 +107,7 @@
|
||||||
<xs:attribute name="blockState" type="xs:string" use="required" />
|
<xs:attribute name="blockState" type="xs:string" use="required" />
|
||||||
<xs:attribute name="minQuantity" 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="maxQuantity" type="xs:string" use="optional" />
|
||||||
|
<xs:attribute name="maxRetries" type="xs:string" use="optional" />
|
||||||
<xs:attribute name="mods" type="xs:string" use="optional" />
|
<xs:attribute name="mods" type="xs:string" use="optional" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue