NBTStructureLib features brought back to NTM, including:

* `/locate` command
* custom spawning rules (eg. make something always spawn at 0,0)
* code structure reorg
* extra logging for misconfigured structures
This commit is contained in:
George Paton 2025-08-08 14:51:45 +10:00
parent a5bdfa87d9
commit 84601f685f
31 changed files with 537 additions and 245 deletions

View File

@ -5,7 +5,7 @@ import com.hbm.handler.ThreeInts;
import com.hbm.interfaces.ICopiable;
import com.hbm.main.MainRegistry;
import com.hbm.tileentity.IPersistentNBT;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import cpw.mods.fml.relauncher.Side;
@ -37,7 +37,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable, INBTTransformable {
public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable, INBTBlockTransformable {
public BlockDummyable(Material mat) {
super(mat);
@ -590,7 +590,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
meta -= extra;
}
meta = INBTTransformable.transformMetaDeco(meta, coordBaseMode);
meta = INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
if(isOffset) {
meta += offset;

View File

@ -4,8 +4,8 @@ import com.hbm.inventory.gui.GUIScreenBobble;
import com.hbm.items.special.ItemPlasticScrap.ScrapType;
import com.hbm.main.MainRegistry;
import com.hbm.tileentity.IGUIProvider;
import com.hbm.world.gen.INBTTileEntityTransformable;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTTileEntityTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import cpw.mods.fml.relauncher.Side;
@ -34,7 +34,7 @@ import net.minecraft.world.World;
import java.util.List;
import java.util.Random;
public class BlockBobble extends BlockContainer implements IGUIProvider, INBTTransformable {
public class BlockBobble extends BlockContainer implements IGUIProvider, INBTBlockTransformable {
public BlockBobble() {
super(Material.iron);

View File

@ -2,7 +2,7 @@ package com.hbm.blocks.generic;
import com.hbm.blocks.BlockMulti;
import com.hbm.lib.RefStrings;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.relauncher.Side;
@ -15,7 +15,7 @@ import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class BlockDecoCRT extends BlockMulti implements INBTTransformable {
public class BlockDecoCRT extends BlockMulti implements INBTBlockTransformable {
protected String[] variants = new String[] {"crt_clean", "crt_broken", "crt_blinking", "crt_bsod"};
@SideOnly(Side.CLIENT) protected IIcon[] icons;
@ -77,7 +77,7 @@ public class BlockDecoCRT extends BlockMulti implements INBTTransformable {
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDecoModel(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDecoModel(meta, coordBaseMode);
}
}

View File

@ -1,7 +1,7 @@
package com.hbm.blocks.generic;
import com.hbm.blocks.BlockEnumMulti;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.client.registry.RenderingRegistry;
import net.minecraft.block.material.Material;
@ -12,7 +12,7 @@ import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockDecoModel extends BlockEnumMulti implements INBTTransformable {
public class BlockDecoModel extends BlockEnumMulti implements INBTBlockTransformable {
public BlockDecoModel(Material mat, Class<? extends Enum> theEnum, boolean multiName, boolean multiTexture) {
super(mat, theEnum, multiName, multiTexture);

View File

@ -2,7 +2,7 @@ package com.hbm.blocks.generic;
import com.hbm.blocks.BlockMulti;
import com.hbm.lib.RefStrings;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.relauncher.Side;
@ -17,7 +17,7 @@ import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockDecoToaster extends BlockMulti implements INBTTransformable {
public class BlockDecoToaster extends BlockMulti implements INBTBlockTransformable {
protected String[] variants = new String[] {"toaster_iron", "toaster_steel", "toaster_wood"};
@SideOnly(Side.CLIENT) protected IIcon[] icons;
@ -94,7 +94,7 @@ public class BlockDecoToaster extends BlockMulti implements INBTTransformable {
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDecoModel(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDecoModel(meta, coordBaseMode);
}
}

View File

@ -4,7 +4,7 @@ import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.items.ModItems;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@ -21,7 +21,7 @@ import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockModDoor extends Block implements INBTTransformable {
public class BlockModDoor extends Block implements INBTBlockTransformable {
@SideOnly(Side.CLIENT)
private IIcon[] field_150017_a;
@SideOnly(Side.CLIENT)
@ -400,6 +400,6 @@ public class BlockModDoor extends Block implements INBTTransformable {
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDoor(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDoor(meta, coordBaseMode);
}
}

View File

@ -4,7 +4,7 @@ import java.util.List;
import com.hbm.blocks.ITooltipProvider;
import com.hbm.lib.RefStrings;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.relauncher.Side;
@ -17,7 +17,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
public class BlockPipe extends Block implements ITooltipProvider, INBTTransformable {
public class BlockPipe extends Block implements ITooltipProvider, INBTBlockTransformable {
@SideOnly(Side.CLIENT)
private IIcon sideIcon;
@ -96,7 +96,7 @@ public class BlockPipe extends Block implements ITooltipProvider, INBTTransforma
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaPillar(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaPillar(meta, coordBaseMode);
}
}

View File

@ -5,8 +5,8 @@ import java.util.Random;
import com.hbm.blocks.IBlockMulti;
import com.hbm.blocks.ITooltipProvider;
import com.hbm.world.gen.INBTTileEntityTransformable;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTTileEntityTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@ -29,7 +29,7 @@ import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
public class BlockPlushie extends BlockContainer implements IBlockMulti, ITooltipProvider, INBTTransformable {
public class BlockPlushie extends BlockContainer implements IBlockMulti, ITooltipProvider, INBTBlockTransformable {
public BlockPlushie() {
super(Material.cloth);

View File

@ -18,7 +18,7 @@ import com.hbm.tileentity.IGUIProvider;
import com.hbm.tileentity.TileEntityLoadedBase;
import com.hbm.util.BufferUtil;
import com.hbm.util.i18n.I18nUtil;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import cpw.mods.fml.common.registry.GameRegistry;
@ -47,7 +47,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre;
public class BlockWandJigsaw extends BlockContainer implements IBlockSideRotation, INBTTransformable, IGUIProvider, ILookOverlay {
public class BlockWandJigsaw extends BlockContainer implements IBlockSideRotation, INBTBlockTransformable, IGUIProvider, ILookOverlay {
private IIcon iconTop;
private IIcon iconSide;
@ -123,7 +123,7 @@ public class BlockWandJigsaw extends BlockContainer implements IBlockSideRotatio
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDeco(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
}
@Override

View File

@ -13,8 +13,8 @@ import com.hbm.main.MainRegistry;
import com.hbm.tileentity.TileEntityLoadedBase;
import com.hbm.util.BufferUtil;
import com.hbm.util.i18n.I18nUtil;
import com.hbm.world.gen.nbt.INBTTileEntityTransformable;
import com.hbm.world.gen.util.LogicBlockActions;
import com.hbm.world.gen.INBTTileEntityTransformable;
import com.hbm.world.gen.util.LogicBlockConditions;
import com.hbm.world.gen.util.LogicBlockInteractions;
import cpw.mods.fml.common.registry.GameRegistry;

View File

@ -17,7 +17,7 @@ import com.hbm.tileentity.TileEntityLoadedBase;
import com.hbm.util.BufferUtil;
import com.hbm.util.LootGenerator;
import com.hbm.util.i18n.I18nUtil;
import com.hbm.world.gen.INBTTileEntityTransformable;
import com.hbm.world.gen.nbt.INBTTileEntityTransformable;
import com.mojang.authlib.GameProfile;
import api.hbm.block.IToolable;

View File

@ -6,7 +6,7 @@ import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.tileentity.deco.TileEntityDecoBlock;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import api.hbm.block.IToolable;
import cpw.mods.fml.client.registry.RenderingRegistry;
@ -25,7 +25,7 @@ import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class DecoBlock extends BlockContainer implements IToolable, INBTTransformable {
public class DecoBlock extends BlockContainer implements IToolable, INBTBlockTransformable {
Random rand = new Random();
@ -185,6 +185,6 @@ public class DecoBlock extends BlockContainer implements IToolable, INBTTransfor
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDeco(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
}
}

View File

@ -1,7 +1,7 @@
package com.hbm.blocks.generic;
import com.hbm.tileentity.deco.TileEntityDecoPoleSatelliteReceiver;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
@ -11,7 +11,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTTransformable {
public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTBlockTransformable {
public DecoPoleSatelliteReceiver(Material p_i45386_1_) {
super(p_i45386_1_);
@ -61,7 +61,7 @@ public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTTra
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDeco(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
}
}

View File

@ -1,6 +1,6 @@
package com.hbm.blocks.generic;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.client.registry.RenderingRegistry;
import net.minecraft.block.BlockContainer;
@ -11,7 +11,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class DecoTapeRecorder extends BlockContainer implements INBTTransformable {
public class DecoTapeRecorder extends BlockContainer implements INBTBlockTransformable {
public DecoTapeRecorder(Material p_i45386_1_) {
super(p_i45386_1_);
@ -63,7 +63,7 @@ public class DecoTapeRecorder extends BlockContainer implements INBTTransformabl
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDeco(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
}
}

View File

@ -1,7 +1,7 @@
package com.hbm.blocks.machine;
import com.hbm.main.MainRegistry;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import net.minecraft.block.Block;
@ -17,7 +17,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public abstract class BlockMachineBase extends BlockContainer implements INBTTransformable {
public abstract class BlockMachineBase extends BlockContainer implements INBTBlockTransformable {
int guiID = -1;
protected boolean rotatable = false;
@ -115,6 +115,6 @@ public abstract class BlockMachineBase extends BlockContainer implements INBTTra
@Override
public int transformMeta(int meta, int coordBaseMode) {
if(!rotatable) return meta;
return INBTTransformable.transformMetaDeco(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
}
}

View File

@ -4,10 +4,10 @@ import com.hbm.blocks.ModBlocks;
import com.hbm.blocks.machine.FloodlightBeam.TileEntityFloodlightBeam;
import com.hbm.util.Compat;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import api.hbm.block.IToolable;
import api.hbm.energymk2.IEnergyReceiverMK2;
import com.hbm.world.gen.INBTTransformable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
@ -28,7 +28,7 @@ import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class Floodlight extends BlockContainer implements IToolable, INBTTransformable {
public class Floodlight extends BlockContainer implements IToolable, INBTBlockTransformable {
public Floodlight(Material mat) {
super(mat);

View File

@ -7,7 +7,7 @@ import java.util.Random;
import com.hbm.blocks.BlockEnums.LightType;
import com.hbm.blocks.ISpotlight;
import com.hbm.main.ResourceManager;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.relauncher.Side;
@ -26,7 +26,7 @@ import net.minecraft.world.World;
import net.minecraftforge.client.model.obj.WavefrontObject;
import net.minecraftforge.common.util.ForgeDirection;
public class Spotlight extends Block implements ISpotlight, INBTTransformable {
public class Spotlight extends Block implements ISpotlight, INBTBlockTransformable {
public static boolean disableOnGeneration = true;
@ -367,7 +367,7 @@ public class Spotlight extends Block implements ISpotlight, INBTTransformable {
public int transformMeta(int meta, int coordBaseMode) {
// +1 to set as broken, won't turn on until broken and replaced
int disabled = disableOnGeneration ? 1 : 0;
return (INBTTransformable.transformMetaDeco(meta >> 1, coordBaseMode) << 1) + disabled;
return (INBTBlockTransformable.transformMetaDeco(meta >> 1, coordBaseMode) << 1) + disabled;
}
@Override

View File

@ -25,7 +25,7 @@ import com.hbm.tileentity.TileEntityLoadedBase;
import com.hbm.util.BobMathUtil;
import com.hbm.util.EnumUtil;
import com.hbm.util.i18n.I18nUtil;
import com.hbm.world.gen.INBTTransformable;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;
import api.hbm.fluidmk2.IFluidStandardTransceiverMK2;
@ -55,7 +55,7 @@ import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre;
import net.minecraftforge.common.util.ForgeDirection;
public class FluidPump extends BlockContainer implements INBTTransformable, ILookOverlay, IGUIProvider {
public class FluidPump extends BlockContainer implements INBTBlockTransformable, ILookOverlay, IGUIProvider {
public FluidPump(Material mat) {
super(mat);
@ -127,7 +127,7 @@ public class FluidPump extends BlockContainer implements INBTTransformable, ILoo
@Override
public int transformMeta(int meta, int coordBaseMode) {
return INBTTransformable.transformMetaDeco(meta, coordBaseMode);
return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
}
@Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")})

View File

@ -0,0 +1,118 @@
package com.hbm.commands;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import com.hbm.lib.HbmWorld;
import com.hbm.world.gen.nbt.NBTStructure;
import com.hbm.world.gen.nbt.SpawnCondition;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.PlayerNotFoundException;
import net.minecraft.command.WrongUsageException;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
public class CommandLocate extends CommandBase {
private static final int MAX_DISTANCE = 256;
@Override
public String getCommandName() {
return "ntmlocate";
}
@Override
public String getCommandUsage(ICommandSender sender) {
return String.format(Locale.US,
"%s/%s structure <name> %s- Locates the nearest structure with a given name.",
EnumChatFormatting.GREEN, getCommandName(), EnumChatFormatting.LIGHT_PURPLE
);
}
@Override
public void processCommand(ICommandSender sender, String[] args) {
if(!(sender instanceof EntityPlayer))
throw new PlayerNotFoundException();
if(args.length == 0)
throw new WrongUsageException(getCommandUsage(sender), new Object[0]);
if(args[0].equals("structure")) {
EntityPlayer player = (EntityPlayer) sender;
SpawnCondition structure = NBTStructure.getStructure(args[1]);
if(structure == null) {
ChatComponentTranslation message = new ChatComponentTranslation("commands.locate.no_match");
message.getChatStyle().setColor(EnumChatFormatting.RED);
sender.addChatMessage(message);
return;
}
int chunkX = MathHelper.floor_double(player.posX) / 16;
int chunkZ = MathHelper.floor_double(player.posZ) / 16;
ChunkCoordIntPair pos = getNearestLocationTo(structure, player.worldObj, chunkX, chunkZ);
if(pos == null) {
ChatComponentTranslation message = new ChatComponentTranslation("commands.locate.none_found");
message.getChatStyle().setColor(EnumChatFormatting.RED);
sender.addChatMessage(message);
return;
}
ChatComponentTranslation message = new ChatComponentTranslation("commands.locate.success.coordinates", structure.name, pos.chunkXPos * 16, pos.chunkZPos * 16);
message.getChatStyle().setColor(EnumChatFormatting.GREEN);
sender.addChatMessage(message);
} else {
throw new WrongUsageException(getCommandUsage(sender), new Object[0]);
}
}
private ChunkCoordIntPair getNearestLocationTo(SpawnCondition spawn, World world, int chunkX, int chunkZ) {
if(HbmWorld.worldGenerator.getStructureAt(world, chunkX, chunkZ) == spawn)
return new ChunkCoordIntPair(chunkX, chunkZ);
for(int radius = 1; radius < MAX_DISTANCE; radius++) {
for(int x = chunkX - radius; x <= chunkX + radius; x++) {
if(HbmWorld.worldGenerator.getStructureAt(world, x, chunkZ - radius) == spawn)
return new ChunkCoordIntPair(x, chunkZ - radius);
if(HbmWorld.worldGenerator.getStructureAt(world, x, chunkZ + radius) == spawn)
return new ChunkCoordIntPair(x, chunkZ + radius);
}
for(int z = chunkZ - radius; z <= chunkZ + radius; z++) {
if(HbmWorld.worldGenerator.getStructureAt(world, chunkX - radius, z) == spawn)
return new ChunkCoordIntPair(chunkX - radius, z);
if(HbmWorld.worldGenerator.getStructureAt(world, chunkX + radius, z) == spawn)
return new ChunkCoordIntPair(chunkX + radius, z);
}
}
return null;
}
@SuppressWarnings("unchecked")
@Override
public List<String> addTabCompletionOptions(ICommandSender sender, String[] args) {
if(args.length < 1)
return Collections.emptyList();
if(args.length == 1)
return getListOfStringsMatchingLastWord(args, "structure");
if(args.length == 2) {
List<String> structures = NBTStructure.listStructures();
return getListOfStringsMatchingLastWord(args, structures.toArray(new String[structures.size()]));
}
return Collections.emptyList();
}
}

View File

@ -10,7 +10,7 @@ import java.text.SimpleDateFormat;
import com.hbm.blocks.ModBlocks;
import com.hbm.util.BobMathUtil;
import com.hbm.util.Tuple.Pair;
import com.hbm.world.gen.NBTStructure;
import com.hbm.world.gen.nbt.NBTStructure;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;

View File

@ -1,10 +1,11 @@
package com.hbm.lib;
import com.hbm.world.gen.MapGenNTMFeatures;
import com.hbm.world.gen.NBTStructure;
import com.hbm.world.gen.NTMWorldGenerator;
import com.hbm.world.gen.component.*;
import com.hbm.world.gen.component.BunkerComponents.BunkerStart;
import com.hbm.world.gen.nbt.NBTStructure;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.world.gen.structure.MapGenStructureIO;

View File

@ -967,6 +967,7 @@ public class MainRegistry {
event.registerServerCommand(new CommandRadiation());
event.registerServerCommand(new CommandPacketInfo());
event.registerServerCommand(new CommandReloadServer());
event.registerServerCommand(new CommandLocate());
}
@EventHandler

View File

@ -1,7 +1,7 @@
package com.hbm.main;
import com.hbm.lib.RefStrings;
import com.hbm.world.gen.NBTStructure;
import com.hbm.world.gen.nbt.NBTStructure;
import net.minecraft.util.ResourceLocation;

View File

@ -9,14 +9,15 @@ import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.config.StructureConfig;
import com.hbm.main.StructureManager;
import com.hbm.world.gen.NBTStructure.JigsawPiece;
import com.hbm.world.gen.NBTStructure.JigsawPool;
import com.hbm.world.gen.NBTStructure.SpawnCondition;
import com.hbm.world.gen.component.BunkerComponents.BunkerStart;
import com.hbm.world.gen.component.Component.CrabSpawners;
import com.hbm.world.gen.component.Component.GreenOoze;
import com.hbm.world.gen.component.Component.MeteorBricks;
import com.hbm.world.gen.component.Component.SupplyCrates;
import com.hbm.world.gen.nbt.JigsawPiece;
import com.hbm.world.gen.nbt.JigsawPool;
import com.hbm.world.gen.nbt.NBTStructure;
import com.hbm.world.gen.nbt.SpawnCondition;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
@ -41,44 +42,44 @@ public class NTMWorldGenerator implements IWorldGenerator {
final List<BiomeGenBase> lighthouseBiomes = Arrays.asList(new BiomeGenBase[] { BiomeGenBase.ocean, BiomeGenBase.deepOcean, BiomeGenBase.beach, BiomeGenBase.stoneBeach, BiomeGenBase.coldBeach });
/// SPIRE ///
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("spire") {{
canSpawn = biome -> biome.heightVariation <= 0.05F && !invalidBiomes.contains(biome);
structure = new JigsawPiece("spire", StructureManager.spire, -1);
spawnWeight = 2;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("features") {{
canSpawn = biome -> !invalidBiomes.contains(biome);
start = d -> new MapGenNTMFeatures.Start(d.getW(), d.getX(), d.getY(), d.getZ());
spawnWeight = 14 * 4;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("bunker") {{
canSpawn = biome -> !invalidBiomes.contains(biome);
start = d -> new BunkerStart(d.getW(), d.getX(), d.getY(), d.getZ());
spawnWeight = 1 * 4;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("vertibird") {{
canSpawn = biome -> !biome.canSpawnLightningBolt() && biome.temperature >= 2F;
structure = new JigsawPiece("vertibird", StructureManager.vertibird, -3);
spawnWeight = 3 * 4;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("crashed_vertibird") {{
canSpawn = biome -> !biome.canSpawnLightningBolt() && biome.temperature >= 2F;
structure = new JigsawPiece("crashed_vertibird", StructureManager.crashed_vertibird, -10);
spawnWeight = 3 * 4;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("aircraft_carrier") {{
canSpawn = oceanBiomes::contains;
structure = new JigsawPiece("aircraft_carrier", StructureManager.aircraft_carrier, -6);
maxHeight = 42;
spawnWeight = 1;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("oil_rig") {{
canSpawn = biome -> biome == BiomeGenBase.deepOcean;
structure = new JigsawPiece("oil_rig", StructureManager.oil_rig, -20);
maxHeight = 12;
@ -86,7 +87,7 @@ public class NTMWorldGenerator implements IWorldGenerator {
spawnWeight = 2;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("lighthouse") {{
canSpawn = lighthouseBiomes::contains;
structure = new JigsawPiece("lighthouse", StructureManager.lighthouse, -40);
maxHeight = 29;
@ -94,7 +95,7 @@ public class NTMWorldGenerator implements IWorldGenerator {
spawnWeight = 2;
}});
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("beached_patrol") {{
canSpawn = beachBiomes::contains;
structure = new JigsawPiece("beached_patrol", StructureManager.beached_patrol, -5);
minHeight = 58;
@ -103,8 +104,8 @@ public class NTMWorldGenerator implements IWorldGenerator {
}});
NBTStructure.registerNullWeight(0, 2, oceanBiomes::contains); //why the fuck did this change
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("dish") {{
canSpawn = biome -> biome == BiomeGenBase.plains;
structure = new JigsawPiece("dish", StructureManager.dish, -10);
minHeight = 53;
@ -128,13 +129,13 @@ public class NTMWorldGenerator implements IWorldGenerator {
put(ModBlocks.concrete_colored, new GreenOoze());
}};
NBTStructure.registerStructure(0, new SpawnCondition() {{
NBTStructure.registerStructure(0, new SpawnCondition("meteor_dungeon") {{
minHeight = 32;
maxHeight = 32;
sizeLimit = 128;
canSpawn = biome -> biome.rootHeight >= 0;
startPool = "start";
pools = new HashMap<String, NBTStructure.JigsawPool>() {{
pools = new HashMap<String, JigsawPool>() {{
put("start", new JigsawPool() {{
add(new JigsawPiece("meteor_core", StructureManager.meteor_core) {{ blockTable = bricks; }}, 1);
}});
@ -255,4 +256,13 @@ public class NTMWorldGenerator implements IWorldGenerator {
nbtGen.generateStructures(world, rand, chunkProvider, chunkX, chunkZ);
}
public SpawnCondition getStructureAt(World world, int chunkX, int chunkZ) {
if(StructureConfig.enableStructures == 0) return null;
if(StructureConfig.enableStructures == 2 && !world.getWorldInfo().isMapFeaturesEnabled()) return null;
setRandomSeed(world, chunkX, chunkZ);
return nbtGen.getStructureAt(world, chunkX, chunkZ);
}
}

View File

@ -1,8 +1,8 @@
package com.hbm.world.gen;
package com.hbm.world.gen.nbt;
import net.minecraft.block.Block;
public interface INBTTransformable {
public interface INBTBlockTransformable {
/**
* Defines this block as something that has a rotation or some other blockstate
@ -80,6 +80,30 @@ public interface INBTTransformable {
return meta;
}
// what in the FUCK mojangles
// same as stairs but 1 & 3 flipped
public static int transformMetaTrapdoor(int meta, int coordBaseMode) {
if(coordBaseMode == 0) return meta;
switch(coordBaseMode) {
case 1: //West
if((meta & 3) < 2)
meta = meta ^ 3;
else
meta = meta ^ 2;
break;
case 2: //North
meta = meta ^ 1; //Flip first bit
break;
case 3: //East
if((meta & 3) < 2)
meta = meta ^ 2;
else
meta = meta ^ 3;
break;
}
return meta;
}
public static int transformMetaPillar(int meta, int coordBaseMode) {
if(coordBaseMode == 0 || coordBaseMode == 2) return meta;
int type = meta & 3;

View File

@ -1,4 +1,4 @@
package com.hbm.world.gen;
package com.hbm.world.gen.nbt;
import net.minecraft.world.World;

View File

@ -0,0 +1,35 @@
package com.hbm.world.gen.nbt;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.world.gen.structure.StructureComponent.BlockSelector;
// Assigned to a Component to build
public class JigsawPiece {
public final String name;
public final NBTStructure structure;
// Block modifiers, for randomization and terrain matching
public Map<Block, BlockSelector> blockTable;
public boolean conformToTerrain = false; // moves every single column to the terrain (digging out trenches, natural formations)
public boolean alignToTerrain = false; // aligns this component y-level individually, without moving individual columns (village houses)
public int heightOffset = 0; // individual offset for the structure
public JigsawPiece(String name, NBTStructure structure) {
this(name, structure, 0);
}
public JigsawPiece(String name, NBTStructure structure, int heightOffset) {
if(name == null) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered without a valid name!");
if(NBTStructure.jigsawMap.containsKey(name)) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered with the same name as another: " + name);
this.name = name;
this.structure = structure;
NBTStructure.jigsawMap.put(name, this);
this.heightOffset = heightOffset;
}
}

View File

@ -0,0 +1,58 @@
package com.hbm.world.gen.nbt;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.hbm.util.Tuple.Pair;
// A set of pieces with weights
public class JigsawPool {
// Weighted list of pieces to pick from
List<Pair<JigsawPiece, Integer>> pieces = new ArrayList<>();
int totalWeight = 0;
public String fallback;
private boolean isClone;
public void add(JigsawPiece piece, int weight) {
if(weight <= 0) throw new IllegalStateException("JigsawPool spawn weight must be positive!");
pieces.add(new Pair<>(piece, weight));
totalWeight += weight;
}
protected JigsawPool clone() {
JigsawPool clone = new JigsawPool();
clone.pieces = new ArrayList<>(this.pieces);
clone.fallback = this.fallback;
clone.totalWeight = this.totalWeight;
clone.isClone = true;
return clone;
}
// If from a clone, will remove from the pool
public JigsawPiece get(Random rand) {
if(totalWeight <= 0) return null;
int weight = rand.nextInt(totalWeight);
for(int i = 0; i < pieces.size(); i++) {
Pair<JigsawPiece, Integer> pair = pieces.get(i);
weight -= pair.getValue();
if(weight < 0) {
if(isClone) {
pieces.remove(i);
totalWeight -= pair.getValue();
}
return pair.getKey();
}
}
return null;
}
}

View File

@ -1,11 +1,10 @@
package com.hbm.world.gen;
package com.hbm.world.gen.nbt;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import com.hbm.blocks.ModBlocks;
@ -17,6 +16,7 @@ import com.hbm.main.MainRegistry;
import com.hbm.util.Tuple.Pair;
import com.hbm.util.Tuple.Quartet;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.world.gen.nbt.SpawnCondition.WorldCoordinate;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.*;
@ -31,6 +31,7 @@ import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.chunk.IChunkProvider;
@ -53,7 +54,10 @@ public class NBTStructure {
* without having to define and register each structure manually
*/
private static Map<String, SpawnCondition> namedMap = new HashMap<>();
protected static Map<Integer, List<SpawnCondition>> weightedMap = new HashMap<>();
protected static Map<Integer, List<SpawnCondition>> customSpawnMap = new HashMap<>();
// serialization data
protected static Map<String, JigsawPiece> jigsawMap = new HashMap<>();
@ -62,7 +66,7 @@ public class NBTStructure {
private boolean isLoaded;
private ThreeInts size;
protected ThreeInts size;
private List<Pair<Short, String>> itemPalette;
private BlockState[][][] blockArray;
@ -89,6 +93,17 @@ public class NBTStructure {
// Register a new structure for a given dimension
public static void registerStructure(int dimensionId, SpawnCondition spawn) {
if(namedMap.containsKey(spawn.name) && namedMap.get(spawn.name) != spawn)
throw new IllegalStateException("A severe error has occurred in NBTStructure! A SpawnCondition has been registered with the same name as another: " + spawn.name);
namedMap.put(spawn.name, spawn);
if(spawn.checkCoordinates != null) {
List<SpawnCondition> spawnList = customSpawnMap.computeIfAbsent(dimensionId, integer -> new ArrayList<SpawnCondition>());
spawnList.add(spawn);
return;
}
List<SpawnCondition> weightedList = weightedMap.computeIfAbsent(dimensionId, integer -> new ArrayList<SpawnCondition>());
for(int i = 0; i < spawn.spawnWeight; i++) {
weightedList.add(spawn);
@ -107,10 +122,7 @@ public class NBTStructure {
}
public static void registerNullWeight(int dimensionId, int weight, Predicate<BiomeGenBase> predicate) {
SpawnCondition spawn = new SpawnCondition() {{
spawnWeight = weight;
canSpawn = predicate;
}};
SpawnCondition spawn = new SpawnCondition(weight, predicate);
List<SpawnCondition> weightedList = weightedMap.computeIfAbsent(dimensionId, integer -> new ArrayList<SpawnCondition>());
for(int i = 0; i < spawn.spawnWeight; i++) {
@ -118,6 +130,19 @@ public class NBTStructure {
}
}
// Presents a list of all structures registered (so far)
public static List<String> listStructures() {
List<String> names = new ArrayList<>(namedMap.keySet());
names.sort((a, b) -> a.compareTo(b));
return names;
}
// Fetches a registered structure by name,
// If one is not found, will simply return null.
public static SpawnCondition getStructure(String name) {
return namedMap.get(name);
}
// Saves a selected area into an NBT structure (+ some of our non-standard stuff to support 1.7.10)
public static void saveArea(String filename, World world, int x1, int y1, int z1, int x2, int y2, int z2, Set<Pair<Block, Integer>> exclude) {
NBTTagCompound structure = new NBTTagCompound();
@ -552,7 +577,7 @@ public class NBTStructure {
return selector.func_151561_a();
}
if(definition.block instanceof INBTTransformable) return ((INBTTransformable) definition.block).transformBlock(definition.block);
if(definition.block instanceof INBTBlockTransformable) return ((INBTBlockTransformable) definition.block).transformBlock(definition.block);
return definition.block;
}
@ -563,22 +588,23 @@ public class NBTStructure {
}
// Our shit
if(definition.block instanceof INBTTransformable) return ((INBTTransformable) definition.block).transformMeta(definition.meta, coordBaseMode);
if(definition.block instanceof INBTBlockTransformable) return ((INBTBlockTransformable) definition.block).transformMeta(definition.meta, coordBaseMode);
if(coordBaseMode == 0) return definition.meta;
// Vanilla shit
if(definition.block instanceof BlockStairs) return INBTTransformable.transformMetaStairs(definition.meta, coordBaseMode);
if(definition.block instanceof BlockRotatedPillar) return INBTTransformable.transformMetaPillar(definition.meta, coordBaseMode);
if(definition.block instanceof BlockDirectional) return INBTTransformable.transformMetaDirectional(definition.meta, coordBaseMode);
if(definition.block instanceof BlockTorch) return INBTTransformable.transformMetaTorch(definition.meta, coordBaseMode);
if(definition.block instanceof BlockButton) return INBTTransformable.transformMetaTorch(definition.meta, coordBaseMode);
if(definition.block instanceof BlockDoor) return INBTTransformable.transformMetaDoor(definition.meta, coordBaseMode);
if(definition.block instanceof BlockLever) return INBTTransformable.transformMetaLever(definition.meta, coordBaseMode);
if(definition.block instanceof BlockSign) return INBTTransformable.transformMetaDeco(definition.meta, coordBaseMode);
if(definition.block instanceof BlockLadder) return INBTTransformable.transformMetaDeco(definition.meta, coordBaseMode);
if(definition.block instanceof BlockTripWireHook) return INBTTransformable.transformMetaDirectional(definition.meta, coordBaseMode);
if(definition.block == Blocks.vine) return INBTTransformable.transformMetaVine(definition.meta, coordBaseMode);
if(definition.block instanceof BlockStairs) return INBTBlockTransformable.transformMetaStairs(definition.meta, coordBaseMode);
if(definition.block instanceof BlockRotatedPillar) return INBTBlockTransformable.transformMetaPillar(definition.meta, coordBaseMode);
if(definition.block instanceof BlockDirectional) return INBTBlockTransformable.transformMetaDirectional(definition.meta, coordBaseMode);
if(definition.block instanceof BlockTorch) return INBTBlockTransformable.transformMetaTorch(definition.meta, coordBaseMode);
if(definition.block instanceof BlockButton) return INBTBlockTransformable.transformMetaTorch(definition.meta, coordBaseMode);
if(definition.block instanceof BlockDoor) return INBTBlockTransformable.transformMetaDoor(definition.meta, coordBaseMode);
if(definition.block instanceof BlockLever) return INBTBlockTransformable.transformMetaLever(definition.meta, coordBaseMode);
if(definition.block instanceof BlockSign) return INBTBlockTransformable.transformMetaDeco(definition.meta, coordBaseMode);
if(definition.block instanceof BlockLadder) return INBTBlockTransformable.transformMetaDeco(definition.meta, coordBaseMode);
if(definition.block instanceof BlockTripWireHook) return INBTBlockTransformable.transformMetaDirectional(definition.meta, coordBaseMode);
if(definition.block instanceof BlockVine) return INBTBlockTransformable.transformMetaVine(definition.meta, coordBaseMode);
if(definition.block instanceof BlockTrapDoor) return INBTBlockTransformable.transformMetaTrapdoor(definition.meta, coordBaseMode);
return definition.meta;
}
@ -649,152 +675,6 @@ public class NBTStructure {
}
public static class SpawnCondition {
// If defined, will spawn a single jigsaw piece, for single nbt structures
public JigsawPiece structure;
// If defined, will spawn in a non-nbt structure component
public Function<Quartet<World, Random, Integer, Integer>, StructureStart> start;
public Predicate<BiomeGenBase> canSpawn;
public int spawnWeight = 1;
// Named jigsaw pools that are referenced within the structure
public Map<String, JigsawPool> pools;
public String startPool;
// Maximum amount of components in this structure
public int sizeLimit = 8;
// How far the structure can extend horizontally from the center, maximum of 128
// This could be increased by changing GenStructure:range from 8, but this is already quite reasonably large
public int rangeLimit = 128;
// Height modifiers, will clamp height that the start generates at, allowing for:
// * Submarines that must spawn under the ocean surface
// * Bunkers that sit underneath the ground
public int minHeight = 1;
public int maxHeight = 128;
// Can this spawn in the current biome
protected boolean isValid(BiomeGenBase biome) {
if(canSpawn == null) return true;
return canSpawn.test(biome);
}
protected JigsawPool getPool(String name) {
return pools.get(name).clone();
}
// Builds all of the pools into neat rows and columns, for editing and debugging!
// Make sure structure debug is enabled, or it will no-op
// Do not use in generation
public void buildAll(World world, int x, int y, int z) {
if(!StructureConfig.debugStructures) return;
int padding = 5;
int oz = 0;
for(JigsawPool pool : pools.values()) {
int highestWidth = 0;
int ox = 0;
for(Pair<JigsawPiece, Integer> entry : pool.pieces) {
NBTStructure structure = entry.key.structure;
structure.build(world, x + ox + (structure.size.x / 2), y, z + oz + (structure.size.z / 2));
ox += structure.size.x + padding;
highestWidth = Math.max(highestWidth, structure.size.z);
}
oz += highestWidth + padding;
}
}
}
// A set of pieces with weights
public static class JigsawPool {
// Weighted list of pieces to pick from
private List<Pair<JigsawPiece, Integer>> pieces = new ArrayList<>();
private int totalWeight = 0;
public String fallback;
private boolean isClone;
public void add(JigsawPiece piece, int weight) {
if(weight <= 0) throw new IllegalStateException("JigsawPool spawn weight must be positive!");
pieces.add(new Pair<>(piece, weight));
totalWeight += weight;
}
protected JigsawPool clone() {
JigsawPool clone = new JigsawPool();
clone.pieces = new ArrayList<>(this.pieces);
clone.fallback = this.fallback;
clone.totalWeight = this.totalWeight;
clone.isClone = true;
return clone;
}
// If from a clone, will remove from the pool
public JigsawPiece get(Random rand) {
if(totalWeight <= 0) return null;
int weight = rand.nextInt(totalWeight);
for(int i = 0; i < pieces.size(); i++) {
Pair<JigsawPiece, Integer> pair = pieces.get(i);
weight -= pair.getValue();
if(weight < 0) {
if(isClone) {
pieces.remove(i);
totalWeight -= pair.getValue();
}
return pair.getKey();
}
}
return null;
}
}
// Assigned to a Component to build
public static class JigsawPiece {
public final String name;
public final NBTStructure structure;
// Block modifiers, for randomization and terrain matching
public Map<Block, BlockSelector> blockTable;
public boolean conformToTerrain = false; // moves every single column to the terrain (digging out trenches, natural formations)
public boolean alignToTerrain = false; // aligns this component y-level individually, without moving individual columns (village houses)
public int heightOffset = 0; // individual offset for the structure
public JigsawPiece(String name, NBTStructure structure) {
this(name, structure, 0);
}
public JigsawPiece(String name, NBTStructure structure, int heightOffset) {
if(name == null) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered without a valid name!");
if(jigsawMap.containsKey(name)) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered with the same name as another: " + name);
this.name = name;
this.structure = structure;
jigsawMap.put(name, this);
this.heightOffset = heightOffset;
}
}
// Each jigsaw block in a structure will instance one of these
private static class JigsawConnection {
@ -872,7 +752,7 @@ public class NBTStructure {
// Save to NBT
@Override
protected void func_143012_a(NBTTagCompound nbt) {
nbt.setString("piece", piece.name);
nbt.setString("piece", piece != null ? piece.name : "NULL");
nbt.setInteger("min", minHeight);
nbt.setInteger("max", maxHeight);
nbt.setBoolean("hasHeight", heightUpdated);
@ -1055,6 +935,10 @@ public class NBTStructure {
}
JigsawPool nextPool = spawn.getPool(fromConnection.poolName);
if(nextPool == null) {
MainRegistry.logger.warn("[Jigsaw] Jigsaw block points to invalid pool: " + fromConnection.poolName);
continue;
}
Component nextComponent = null;
@ -1119,10 +1003,16 @@ public class NBTStructure {
private Component buildNextComponent(Random rand, SpawnCondition spawn, JigsawPool pool, Component fromComponent, JigsawConnection fromConnection) {
JigsawPiece nextPiece = pool.get(rand);
if(nextPiece == null) return null;
if(nextPiece == null) {
MainRegistry.logger.warn("[Jigsaw] Pool returned null piece: " + fromConnection.poolName);
return null;
}
List<JigsawConnection> connectionPool = getConnectionPool(nextPiece, fromConnection);
if(connectionPool == null) return null;
if(connectionPool == null || connectionPool.isEmpty()) {
MainRegistry.logger.warn("[Jigsaw] No valid connections for: " + fromConnection.targetName + " - in piece: " + nextPiece.name);
return null;
}
JigsawConnection toConnection = connectionPool.get(rand.nextInt(connectionPool.size()));
@ -1192,7 +1082,42 @@ public class NBTStructure {
@Override
protected boolean canSpawnStructureAtCoords(int chunkX, int chunkZ) {
if(!weightedMap.containsKey(worldObj.provider.dimensionId)) return false;
nextSpawn = getSpawnAtCoords(chunkX, chunkZ);
return nextSpawn != null;
}
public SpawnCondition getStructureAt(World world, int chunkX, int chunkZ) {
// make sure the random is in the correct state
this.worldObj = world;
this.rand.setSeed(world.getSeed());
long l = this.rand.nextLong();
long i1 = this.rand.nextLong();
long l1 = (long)chunkX * l;
long i2 = (long)chunkZ * i1;
this.rand.setSeed(l1 ^ i2 ^ world.getSeed());
// random nextInt call just before `canSpawnStructureAtCoords`, no, I don't know why Mojang added that
this.rand.nextInt();
return getSpawnAtCoords(chunkX, chunkZ);
}
private SpawnCondition getSpawnAtCoords(int chunkX, int chunkZ) {
// attempt to spawn with custom chunk coordinate rules
if (customSpawnMap.containsKey(worldObj.provider.dimensionId)) {
WorldCoordinate coords = new WorldCoordinate(worldObj, new ChunkCoordIntPair(chunkX, chunkZ), rand);
List<SpawnCondition> spawnList = customSpawnMap.get(worldObj.provider.dimensionId);
for (SpawnCondition spawn : spawnList) {
if ((spawn.pools != null || spawn.structure != null) && spawn.checkCoordinates.test(coords)) {
return spawn;
}
}
}
if (!weightedMap.containsKey(worldObj.provider.dimensionId))
return null;
int x = chunkX;
int z = chunkZ;
@ -1208,15 +1133,16 @@ public class NBTStructure {
x += rand.nextInt(StructureConfig.structureMaxChunks - StructureConfig.structureMinChunks);
z += rand.nextInt(StructureConfig.structureMaxChunks - StructureConfig.structureMinChunks);
if(chunkX == x && chunkZ == z) {
if (chunkX == x && chunkZ == z) {
BiomeGenBase biome = this.worldObj.getWorldChunkManager().getBiomeGenAt(chunkX * 16 + 8, chunkZ * 16 + 8);
nextSpawn = findSpawn(biome);
SpawnCondition spawn = findSpawn(biome);
return nextSpawn != null && (nextSpawn.pools != null || nextSpawn.start != null || nextSpawn.structure != null);
if(spawn != null && (spawn.pools != null || spawn.start != null || spawn.structure != null))
return spawn;
}
return false;
return null;
}
@Override

View File

@ -0,0 +1,115 @@
package com.hbm.world.gen.nbt;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;
import java.util.function.Predicate;
import com.hbm.config.StructureConfig;
import com.hbm.util.Tuple.Pair;
import com.hbm.util.Tuple.Quartet;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.gen.structure.StructureStart;
public class SpawnCondition {
public final String name;
// If defined, will spawn a single jigsaw piece, for single nbt structures
public JigsawPiece structure;
// If defined, will spawn in a non-nbt structure component
public Function<Quartet<World, Random, Integer, Integer>, StructureStart> start;
// If defined, will override regular spawn location checking, for placing at specific coordinates or with special rules
public Predicate<WorldCoordinate> checkCoordinates;
// Our regular spawning mechanics, based on biome, you should generally use these
public Predicate<BiomeGenBase> canSpawn;
public int spawnWeight = 1;
// Named jigsaw pools that are referenced within the structure
public Map<String, JigsawPool> pools;
public String startPool;
// Maximum amount of components in this structure
public int sizeLimit = 8;
// How far the structure can extend horizontally from the center, maximum of 128
// This could be increased by changing GenStructure:range from 8, but this is already quite reasonably large
public int rangeLimit = 128;
// Height modifiers, will clamp height that the start generates at, allowing for:
// * Submarines that must spawn under the ocean surface
// * Bunkers that sit underneath the ground
public int minHeight = 1;
public int maxHeight = 128;
protected SpawnCondition(int weight, Predicate<BiomeGenBase> predicate) {
name = null;
spawnWeight = weight;
canSpawn = predicate;
}
public SpawnCondition(String name) {
this.name = name;
}
// Can this spawn in the current biome
protected boolean isValid(BiomeGenBase biome) {
if(canSpawn == null) return true;
return canSpawn.test(biome);
}
protected JigsawPool getPool(String name) {
JigsawPool pool = pools.get(name);
return pool != null ? pool.clone() : null;
}
// Builds all of the pools into neat rows and columns, for editing and debugging!
// Make sure structure debug is enabled, or it will no-op
// Do not use in generation
public void buildAll(World world, int x, int y, int z) {
if(!StructureConfig.debugStructures) return;
int padding = 5;
int oz = 0;
for(JigsawPool pool : pools.values()) {
int highestWidth = 0;
int ox = 0;
for(Pair<JigsawPiece, Integer> entry : pool.pieces) {
NBTStructure structure = entry.key.structure;
structure.build(world, x + ox + (structure.size.x / 2), y, z + oz + (structure.size.z / 2));
ox += structure.size.x + padding;
highestWidth = Math.max(highestWidth, structure.size.z);
}
oz += highestWidth + padding;
}
}
/**
* Provides information about the current structure gen chunk,
* use the included random for consistent seeding!
*/
public static class WorldCoordinate {
public final World world;
public final ChunkCoordIntPair coords;
public final Random rand;
protected WorldCoordinate(World world, ChunkCoordIntPair coords, Random rand) {
this.world = world;
this.coords = coords;
this.rand = rand;
}
}
}

View File

@ -705,6 +705,10 @@ commands.satellite.satellite_descended=Satellite successfully descended.
commands.satellite.satellite_orbited=Satellite launched.
commands.satellite.should_be_run_as_player=This command should be run by a player!
commands.locate.no_match=No structures with that name!
commands.locate.none_found=No structures found nearby!
commands.locate.success.coordinates=Structure %s found at %d, %d
container.ammoBag=Ammo Bag
container.amsBase=AMS Base (Deco)
container.amsEmitter=AMS Emitter (Deco)