mirror of
https://github.com/GTNewHorizons/StructureLib.git
synced 2026-10-26 14:23:56 +00:00
[ci skip] spotlessApply with the new settings
This commit is contained in:
1 parent
392d2ace8a
commit
464e44de85
76 files changed
+1717
-1863
No files matched your search
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
dependencies {
|
||||
compile("com.github.GTNewHorizons:GTNHLib:0.0.1:dev")
|
||||
runtime("com.github.GTNewHorizons:NotEnoughItems:2.2.20-GTNH:dev")
|
||||
runtimeOnly("com.github.GTNewHorizons:NotEnoughItems:2.2.20-GTNH:dev")
|
||||
|
||||
testImplementation(platform('org.junit:junit-bom:5.8.2'))
|
||||
testImplementation('org.junit.jupiter:junit-jupiter')
|
||||
|
||||
@@ -2,14 +2,8 @@ package com.gtnewhorizon.structurelib;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.RANDOM;
|
||||
|
||||
import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX;
|
||||
import com.gtnewhorizon.structurelib.net.SetChannelDataMessage;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
import java.util.*;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiNewChat;
|
||||
@@ -31,12 +25,22 @@ import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX;
|
||||
import com.gtnewhorizon.structurelib.net.SetChannelDataMessage;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
|
||||
public class ClientProxy extends CommonProxy {
|
||||
|
||||
private static final short[] RGBA_NO_TINT = {255, 255, 255, 255};
|
||||
private static final short[] RGBA_RED_TINT = {255, 128, 128, 0};
|
||||
private static final short[] RGBA_NO_TINT = { 255, 255, 255, 255 };
|
||||
private static final short[] RGBA_RED_TINT = { 255, 128, 128, 0 };
|
||||
private static final Map<HintParticleInfo, HintGroup> allHints = new HashMap<>();
|
||||
/**
|
||||
* All batches of hints.
|
||||
@@ -55,11 +59,10 @@ public class ClientProxy extends CommonProxy {
|
||||
*/
|
||||
private static final List<HintParticleInfo> allHintsForRender = new ArrayList<>(10000);
|
||||
/**
|
||||
* If the diff to current player position is too great sort the allHints.
|
||||
* Initial value is very far off below y=0 but not huge enough to make a NaN.
|
||||
* If the diff to current player position is too great sort the allHints. Initial value is very far off below y=0
|
||||
* but not huge enough to make a NaN.
|
||||
* <p>
|
||||
* We are using this supposedly immutable object as a mutable object here.
|
||||
* So be aware.
|
||||
* We are using this supposedly immutable object as a mutable object here. So be aware.
|
||||
*/
|
||||
private static final Vec3 lastPlayerPos = Vec3.createVectorHelper(0, -1e30, 0);
|
||||
/**
|
||||
@@ -158,11 +161,7 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addThrottledChat(
|
||||
Object throttleKey,
|
||||
EntityPlayer player,
|
||||
IChatComponent text,
|
||||
short intervalRequired,
|
||||
public void addThrottledChat(Object throttleKey, EntityPlayer player, IChatComponent text, short intervalRequired,
|
||||
boolean forceUpdateLastSend) {
|
||||
if (player instanceof EntityPlayerMP)
|
||||
super.addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend);
|
||||
@@ -250,6 +249,7 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
private static class HintGroup {
|
||||
|
||||
private final List<HintParticleInfo> hints = new LinkedList<>();
|
||||
private int creationTime = -1;
|
||||
|
||||
@@ -267,6 +267,7 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
private static class HintParticleInfo {
|
||||
|
||||
private final World w;
|
||||
// these are the block coordinate for e.g. w.getBlock()
|
||||
private final int x, y, z;
|
||||
@@ -418,6 +419,7 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
public static class FMLEventHandler {
|
||||
|
||||
private void resetPlayerLocation() {
|
||||
lastPlayerPos.xCoord = Minecraft.getMinecraft().thePlayer.posX;
|
||||
lastPlayerPos.yCoord = Minecraft.getMinecraft().thePlayer.posY;
|
||||
@@ -466,6 +468,7 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
public static class ForgeEventHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldLoad(WorldEvent.Load e) {
|
||||
if (e.world.isRemote) {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage;
|
||||
import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@@ -15,7 +13,12 @@ import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage;
|
||||
import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
|
||||
public class CommonProxy {
|
||||
|
||||
public void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {}
|
||||
|
||||
public void hintParticleTinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {}
|
||||
@@ -68,11 +71,7 @@ public class CommonProxy {
|
||||
|
||||
private final Map<EntityPlayerMP, Map<Object, Long>> throttleMap = new WeakHashMap<>();
|
||||
|
||||
public void addThrottledChat(
|
||||
Object throttleKey,
|
||||
EntityPlayer player,
|
||||
IChatComponent text,
|
||||
short intervalRequired,
|
||||
public void addThrottledChat(Object throttleKey, EntityPlayer player, IChatComponent text, short intervalRequired,
|
||||
boolean forceUpdateLastSend) {
|
||||
if (player instanceof EntityPlayerMP) {
|
||||
Map<Object, Long> submap = throttleMap.computeIfAbsent((EntityPlayerMP) player, p -> new HashMap<>());
|
||||
@@ -80,13 +79,8 @@ public class CommonProxy {
|
||||
}
|
||||
}
|
||||
|
||||
protected static void addThrottledChat(
|
||||
Object throttleKey,
|
||||
EntityPlayer player,
|
||||
IChatComponent text,
|
||||
short intervalRequired,
|
||||
boolean forceUpdateLastSend,
|
||||
Map<Object, Long> submap) {
|
||||
protected static void addThrottledChat(Object throttleKey, EntityPlayer player, IChatComponent text,
|
||||
short intervalRequired, boolean forceUpdateLastSend, Map<Object, Long> submap) {
|
||||
long now = System.currentTimeMillis();
|
||||
Long old;
|
||||
if (forceUpdateLastSend) {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import cpw.mods.fml.client.event.ConfigChangedEvent;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraftforge.common.config.ConfigCategory;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.common.config.Property;
|
||||
|
||||
import cpw.mods.fml.client.event.ConfigChangedEvent;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
public enum ConfigurationHandler {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private Configuration config;
|
||||
@@ -54,8 +57,8 @@ public enum ConfigurationHandler {
|
||||
"client.hologram",
|
||||
true,
|
||||
"An attempt will be made to remove an existing hologram if it collides with a new hologram.");
|
||||
hintLifespan =
|
||||
config.getInt("hintLifespan", "client.hologram", 400, 1, 20000, "Ticks before a hologram disappears.");
|
||||
hintLifespan = config
|
||||
.getInt("hintLifespan", "client.hologram", 400, 1, 20000, "Ticks before a hologram disappears.");
|
||||
hintTransparency = config.getInt(
|
||||
"hintTransparency",
|
||||
"client.hologram",
|
||||
|
||||
@@ -2,11 +2,15 @@ package com.gtnewhorizon.structurelib;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
enum ConfigurationVersion {
|
||||
|
||||
V1 {
|
||||
|
||||
@Override
|
||||
protected void step(Configuration c) {}
|
||||
};
|
||||
@@ -30,10 +34,8 @@ enum ConfigurationVersion {
|
||||
}
|
||||
|
||||
public static ConfigurationVersion identify(Configuration c) {
|
||||
return Arrays.stream(VALUES)
|
||||
.filter(v -> Objects.equals(c.getLoadedConfigVersion(), v.getVersionMarker()))
|
||||
.findFirst()
|
||||
.orElse(V1);
|
||||
return Arrays.stream(VALUES).filter(v -> Objects.equals(c.getLoadedConfigVersion(), v.getVersionMarker()))
|
||||
.findFirst().orElse(V1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import cpw.mods.fml.client.IModGuiFactory;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
import cpw.mods.fml.client.IModGuiFactory;
|
||||
|
||||
public class GuiFactory implements IModGuiFactory {
|
||||
|
||||
@Override
|
||||
public void initialize(Minecraft minecraftInstance) {}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import com.gtnewhorizon.structurelib.gui.GuiScreenConfigureChannels;
|
||||
import cpw.mods.fml.common.network.IGuiHandler;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.gui.GuiScreenConfigureChannels;
|
||||
import cpw.mods.fml.common.network.IGuiHandler;
|
||||
|
||||
public class GuiHandler implements IGuiHandler {
|
||||
|
||||
@Override
|
||||
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
|
||||
return null;
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import cpw.mods.fml.client.config.GuiConfig;
|
||||
import cpw.mods.fml.client.config.IConfigElement;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraftforge.common.config.ConfigElement;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
import cpw.mods.fml.client.config.GuiConfig;
|
||||
import cpw.mods.fml.client.config.IConfigElement;
|
||||
|
||||
public class GuiModConfig extends GuiConfig {
|
||||
|
||||
public GuiModConfig(GuiScreen guiScreen) {
|
||||
super(
|
||||
guiScreen,
|
||||
@@ -16,16 +19,13 @@ public class GuiModConfig extends GuiConfig {
|
||||
StructureLibAPI.MOD_ID,
|
||||
false,
|
||||
false,
|
||||
GuiConfig.getAbridgedConfigPath(
|
||||
ConfigurationHandler.INSTANCE.getConfig().toString()));
|
||||
GuiConfig.getAbridgedConfigPath(ConfigurationHandler.INSTANCE.getConfig().toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static List<IConfigElement> getConfigElements() {
|
||||
final Configuration config = ConfigurationHandler.INSTANCE.getConfig();
|
||||
return config.getCategoryNames().stream()
|
||||
.filter(name -> name.indexOf('.') == -1)
|
||||
.map(name -> new ConfigElement(config.getCategory(name)))
|
||||
.collect(Collectors.toList());
|
||||
return config.getCategoryNames().stream().filter(name -> name.indexOf('.') == -1)
|
||||
.map(name -> new ConfigElement(config.getCategory(name))).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,6 @@ package com.gtnewhorizon.structurelib;
|
||||
import net.minecraft.util.IIcon;
|
||||
|
||||
public interface IStructureCompat {
|
||||
|
||||
void markTextureUsed(IIcon o);
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import com.gtnewhorizon.structurelib.structure.IStructureElement;
|
||||
import cpw.mods.fml.common.eventhandler.Event;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
/**
|
||||
* Subscribers are <b>required</b> to not keep reference to these events, nor to depend on values of these events after
|
||||
@@ -12,10 +13,11 @@ import net.minecraftforge.common.MinecraftForge;
|
||||
* All of these events will be fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}, if they are
|
||||
* enabled by {@link StructureLibAPI#enableInstrument(Object)}.
|
||||
* <p>
|
||||
* All public stuff in this class and its enclosed classes are considered part of the public API.
|
||||
* Backwards compatibility is maintained to the maximum extend possible.
|
||||
* All public stuff in this class and its enclosed classes are considered part of the public API. Backwards
|
||||
* compatibility is maintained to the maximum extend possible.
|
||||
*/
|
||||
public abstract class StructureEvent extends Event {
|
||||
|
||||
/*
|
||||
* In case the event is passed to another thread for processing.
|
||||
*/
|
||||
@@ -35,20 +37,21 @@ public abstract class StructureEvent extends Event {
|
||||
* Fired <b>just before</b> any structure element is visited.
|
||||
*/
|
||||
public static final class StructureElementVisitedEvent extends StructureEvent {
|
||||
|
||||
private final World world;
|
||||
private final int x, y, z;
|
||||
private final int a, b, c;
|
||||
private final IStructureElement<?> element;
|
||||
|
||||
/**
|
||||
* Fire this event on {@link MinecraftForge#EVENT_BUS} by populating it with given arguments.
|
||||
* Do nothing if instrumenting isn't enabled for current thread.
|
||||
* Fire this event on {@link MinecraftForge#EVENT_BUS} by populating it with given arguments. Do nothing if
|
||||
* instrumenting isn't enabled for current thread.
|
||||
* <p>
|
||||
* Any {@link Exception} thrown by event listeners will be logged and ignored. {@link Error} will be propagated
|
||||
* as is.
|
||||
*/
|
||||
public static void fireEvent(
|
||||
World world, int x, int y, int z, int a, int b, int c, IStructureElement<?> element) {
|
||||
public static void fireEvent(World world, int x, int y, int z, int a, int b, int c,
|
||||
IStructureElement<?> element) {
|
||||
if (StructureLibAPI.isInstrumentEnabled()) {
|
||||
try {
|
||||
MinecraftForge.EVENT_BUS.post(new StructureElementVisitedEvent(world, x, y, z, a, b, c, element));
|
||||
@@ -58,8 +61,8 @@ public abstract class StructureEvent extends Event {
|
||||
}
|
||||
}
|
||||
|
||||
StructureElementVisitedEvent(
|
||||
World world, int x, int y, int z, int a, int b, int c, IStructureElement<?> element) {
|
||||
StructureElementVisitedEvent(World world, int x, int y, int z, int a, int b, int c,
|
||||
IStructureElement<?> element) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
@@ -107,14 +110,22 @@ public abstract class StructureEvent extends Event {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StructureElementVisitedEvent{" + "a="
|
||||
+ a + ", b="
|
||||
+ b + ", c="
|
||||
+ c + ", element="
|
||||
+ element + ", world="
|
||||
+ getWorld() + ", x="
|
||||
+ getX() + ", y="
|
||||
+ getY() + ", z="
|
||||
+ getZ() + '}';
|
||||
+ a
|
||||
+ ", b="
|
||||
+ b
|
||||
+ ", c="
|
||||
+ c
|
||||
+ ", element="
|
||||
+ element
|
||||
+ ", world="
|
||||
+ getWorld()
|
||||
+ ", x="
|
||||
+ getX()
|
||||
+ ", y="
|
||||
+ getY()
|
||||
+ ", z="
|
||||
+ getZ()
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.gtnewhorizon.structurelib.block.BlockHint;
|
||||
import com.gtnewhorizon.structurelib.command.CommandConfigureChannels;
|
||||
import com.gtnewhorizon.structurelib.item.ItemBlockHint;
|
||||
@@ -10,6 +20,7 @@ import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage;
|
||||
import com.gtnewhorizon.structurelib.net.SetChannelDataMessage;
|
||||
import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage;
|
||||
import com.gtnewhorizon.structurelib.util.XSTR;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.SidedProxy;
|
||||
@@ -20,14 +31,6 @@ import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* This class does not contain a stable API. Refrain from using this class.
|
||||
@@ -39,6 +42,7 @@ import org.apache.logging.log4j.Logger;
|
||||
acceptableRemoteVersions = "*",
|
||||
guiFactory = "com.gtnewhorizon.structurelib.GuiFactory")
|
||||
public class StructureLib {
|
||||
|
||||
private static final String STRUCTURECOMPAT_MODID = "structurecompat";
|
||||
public static boolean DEBUG_MODE;
|
||||
public static boolean PANIC_MODE = Boolean.getBoolean("structurelib.panic");
|
||||
@@ -53,7 +57,10 @@ public class StructureLib {
|
||||
|
||||
static {
|
||||
net.registerMessage(
|
||||
AlignmentMessage.ServerHandler.class, AlignmentMessage.AlignmentQuery.class, 0, Side.SERVER);
|
||||
AlignmentMessage.ServerHandler.class,
|
||||
AlignmentMessage.AlignmentQuery.class,
|
||||
0,
|
||||
Side.SERVER);
|
||||
net.registerMessage(AlignmentMessage.ClientHandler.class, AlignmentMessage.AlignmentData.class, 1, Side.CLIENT);
|
||||
net.registerMessage(UpdateHintParticleMessage.Handler.class, UpdateHintParticleMessage.class, 2, Side.CLIENT);
|
||||
net.registerMessage(SetChannelDataMessage.Handler.class, SetChannelDataMessage.class, 3, Side.SERVER);
|
||||
@@ -80,6 +87,7 @@ public class StructureLib {
|
||||
static Item itemFrontRotationTool;
|
||||
static Item itemConstructableTrigger;
|
||||
public static final CreativeTabs creativeTab = new CreativeTabs("structurelib") {
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public Item getTabIconItem() {
|
||||
@@ -93,7 +101,8 @@ public class StructureLib {
|
||||
GameRegistry.registerBlock(blockHint = new BlockHint(), ItemBlockHint.class, "blockhint");
|
||||
itemBlockHint = ItemBlock.getItemFromBlock(StructureLibAPI.getBlockHint());
|
||||
GameRegistry.registerItem(
|
||||
itemFrontRotationTool = new ItemFrontRotationTool(), itemFrontRotationTool.getUnlocalizedName());
|
||||
itemFrontRotationTool = new ItemFrontRotationTool(),
|
||||
itemFrontRotationTool.getUnlocalizedName());
|
||||
GameRegistry.registerItem(
|
||||
itemConstructableTrigger = new ItemConstructableTrigger(),
|
||||
itemConstructableTrigger.getUnlocalizedName());
|
||||
@@ -101,10 +110,7 @@ public class StructureLib {
|
||||
NetworkRegistry.INSTANCE.registerGuiHandler(instance(), new GuiHandler());
|
||||
|
||||
if (Loader.isModLoaded(STRUCTURECOMPAT_MODID)) {
|
||||
COMPAT = Loader.instance()
|
||||
.getIndexedModList()
|
||||
.get(STRUCTURECOMPAT_MODID)
|
||||
.getMod();
|
||||
COMPAT = Loader.instance().getIndexedModList().get(STRUCTURECOMPAT_MODID).getMod();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,6 @@ package com.gtnewhorizon.structurelib;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.proxy;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
|
||||
import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
|
||||
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@@ -18,10 +11,20 @@ import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
|
||||
import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
|
||||
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
|
||||
/**
|
||||
* A stable interface into the structure lib's internals. Backwards compatibility is maintained to the maximum extend possible.
|
||||
* A stable interface into the structure lib's internals. Backwards compatibility is maintained to the maximum extend
|
||||
* possible.
|
||||
*/
|
||||
public class StructureLibAPI {
|
||||
|
||||
public static final String MOD_ID = "structurelib";
|
||||
public static final int HINT_BLOCK_META_GENERIC_0 = 0;
|
||||
public static final int HINT_BLOCK_META_GENERIC_1 = 1;
|
||||
@@ -47,12 +50,13 @@ public class StructureLibAPI {
|
||||
* appropriate. Otherwise, these events will not be sent at all, regardless of whether a listener for these events
|
||||
* are registered.
|
||||
* <p>
|
||||
* Identifiers are required to be value-comparable, i.e. overrides {@link Object#equals(Object)}.
|
||||
* Suggested identifier includes
|
||||
* Identifiers are required to be value-comparable, i.e. overrides {@link Object#equals(Object)}. Suggested
|
||||
* identifier includes
|
||||
* <ul>
|
||||
* <li>Mod Instance or {@link cpw.mods.fml.common.ModContainer}</li>
|
||||
* <li>{@link com.gtnewhorizon.structurelib.alignment.constructable.IConstructable} and its friends, if you are triggering structure check via this interface.</li>
|
||||
* <li>{@link net.minecraft.util.ResourceLocation}</li>
|
||||
* <li>Mod Instance or {@link cpw.mods.fml.common.ModContainer}</li>
|
||||
* <li>{@link com.gtnewhorizon.structurelib.alignment.constructable.IConstructable} and its friends, if you are
|
||||
* triggering structure check via this interface.</li>
|
||||
* <li>{@link net.minecraft.util.ResourceLocation}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* It's an API abuse for normal {@link IStructureDefinition} users to depend on this feature. They have full control
|
||||
@@ -82,6 +86,7 @@ public class StructureLibAPI {
|
||||
|
||||
/**
|
||||
* Check if instrumenting is enabled.
|
||||
*
|
||||
* @return true if enabled, false otherwise
|
||||
*/
|
||||
public static boolean isInstrumentEnabled() {
|
||||
@@ -89,18 +94,22 @@ public class StructureLibAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a batch of hinting. All hints particles generated during one batch will be considered to belong to one hologram.
|
||||
* Start a batch of hinting. All hints particles generated during one batch will be considered to belong to one
|
||||
* hologram.
|
||||
* <p>
|
||||
* You don't need to call this unless your constructable tool didn't call {@link com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility#handle(ItemStack, EntityPlayer, World, int, int, int, int)}
|
||||
* You don't need to call this unless your constructable tool didn't call
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility#handle(ItemStack, EntityPlayer, World, int, int, int, int)}
|
||||
*/
|
||||
public static void startHinting(World w) {
|
||||
proxy.startHinting(w);
|
||||
}
|
||||
|
||||
/**
|
||||
* End current batch of hinting. All hints particles generated during one batch will be considered to belong to one hologram.
|
||||
* End current batch of hinting. All hints particles generated during one batch will be considered to belong to one
|
||||
* hologram.
|
||||
* <p>
|
||||
* You don't need to call this unless your constructable tool didn't call {@link com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility#handle(ItemStack, EntityPlayer, World, int, int, int, int)}
|
||||
* You don't need to call this unless your constructable tool didn't call
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility#handle(ItemStack, EntityPlayer, World, int, int, int, int)}
|
||||
*/
|
||||
public static void endHinting(World w) {
|
||||
proxy.endHinting(w);
|
||||
@@ -114,7 +123,8 @@ public class StructureLibAPI {
|
||||
* @param y y coord
|
||||
* @param z z coord
|
||||
* @param icons 6 texture. in forge direction order.
|
||||
* @param RGBa a 4 short array. tint in rgba form. currently alpha channel is ignored, but we might change this later on.
|
||||
* @param RGBa a 4 short array. tint in rgba form. currently alpha channel is ignored, but we might change this
|
||||
* later on.
|
||||
*/
|
||||
public static void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
|
||||
proxy.hintParticleTinted(w, x, y, z, icons, RGBa);
|
||||
@@ -129,7 +139,8 @@ public class StructureLibAPI {
|
||||
* @param z z coord
|
||||
* @param block block to take texture from
|
||||
* @param meta the meta of block to take texture from
|
||||
* @param RGBa a 4 short array. tint in rgba form. currently alpha channel is ignored, but we might change this later on.
|
||||
* @param RGBa a 4 short array. tint in rgba form. currently alpha channel is ignored, but we might change this
|
||||
* later on.
|
||||
*/
|
||||
public static void hintParticleTinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {
|
||||
proxy.hintParticleTinted(w, x, y, z, block, meta, RGBa);
|
||||
@@ -165,9 +176,8 @@ public class StructureLibAPI {
|
||||
/**
|
||||
* Update the tint of given hint particle. Do nothing if particle not found.
|
||||
* <p>
|
||||
* Can be called on either client side or server side.
|
||||
* Server side will schedule a network message to update it for this player only.
|
||||
* Will do nothing if no hint particle is found at given location.
|
||||
* Can be called on either client side or server side. Server side will schedule a network message to update it for
|
||||
* this player only. Will do nothing if no hint particle is found at given location.
|
||||
*
|
||||
* @return false if nothing updated. true if updated or update instruction sent.
|
||||
*/
|
||||
@@ -185,11 +195,13 @@ public class StructureLibAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the ExtendedFacing of this tile entity from client side. Can be sent only on client side.
|
||||
* The ExtendedFacing will later be set onto given tile entity via {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)}
|
||||
* upon arrival of server reply.
|
||||
* Query the ExtendedFacing of this tile entity from client side. Can be sent only on client side. The
|
||||
* ExtendedFacing will later be set onto given tile entity via
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} upon arrival of
|
||||
* server reply.
|
||||
* <p>
|
||||
* The server side will query the {@link ExtendedFacing} of this provider using {@link IAlignment#getExtendedFacing()}
|
||||
* The server side will query the {@link ExtendedFacing} of this provider using
|
||||
* {@link IAlignment#getExtendedFacing()}
|
||||
*
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
@@ -200,7 +212,8 @@ public class StructureLibAPI {
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to all players. Can be called on server side only.
|
||||
* <p>
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
*
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
@@ -211,7 +224,8 @@ public class StructureLibAPI {
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to given player. Can be called on server side only.
|
||||
* <p>
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
*
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
@@ -220,9 +234,11 @@ public class StructureLibAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to all players around target point. Can be called on server side only.
|
||||
* Send the ExtendedFacing of this Tile Entity to all players around target point. Can be called on server side
|
||||
* only.
|
||||
* <p>
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
*
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
@@ -233,7 +249,8 @@ public class StructureLibAPI {
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to all players in that dimension. Can be called on server side only.
|
||||
* <p>
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
* The receiving tile entity will receive the {@link ExtendedFacing} via its
|
||||
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
|
||||
*
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
@@ -269,10 +286,11 @@ public class StructureLibAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if given block can be replaced without much effort. The exact predicate clauses is not stable and
|
||||
* will be changed, but the general idea will always stay the same.
|
||||
* Determines if given block can be replaced without much effort. The exact predicate clauses is not stable and will
|
||||
* be changed, but the general idea will always stay the same.
|
||||
* <p>
|
||||
* Use this in your {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
* Use this in your
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isBlockTriviallyReplaceable(World w, int x, int y, int z, EntityPlayerMP actor) {
|
||||
@@ -280,10 +298,11 @@ public class StructureLibAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if given block can be replaced without much effort. The exact predicate clauses is not stable and
|
||||
* will be changed, but the general idea will always stay the same.
|
||||
* Determines if given block can be replaced without much effort. The exact predicate clauses is not stable and will
|
||||
* be changed, but the general idea will always stay the same.
|
||||
* <p>
|
||||
* Use this in your {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
* Use this in your
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
*/
|
||||
public static boolean isBlockTriviallyReplaceable(World w, int x, int y, int z, EntityPlayer actor) {
|
||||
// TODO extend this function a bit
|
||||
@@ -294,35 +313,33 @@ public class StructureLibAPI {
|
||||
/**
|
||||
* Send chat to player, but throttled.
|
||||
*
|
||||
* @param throttleKey throttle key. Must properly implement {@link Object#hashCode()} and {@link Object#equals(Object)}
|
||||
* to handle value equality.
|
||||
* @param throttleKey throttle key. Must properly implement {@link Object#hashCode()} and
|
||||
* {@link Object#equals(Object)} to handle value equality.
|
||||
* @param player player to send chat to
|
||||
* @param text chat to send
|
||||
* @param intervalRequired interval required before last recorded time to actually send the message. unit in millisecond.
|
||||
* we purposefully chose to not use a bigger data type to limit how long this interval can be
|
||||
* @param intervalRequired interval required before last recorded time to actually send the message. unit in
|
||||
* millisecond. we purposefully chose to not use a bigger data type to limit how long this
|
||||
* interval can be
|
||||
*/
|
||||
public static void addThrottledChat(
|
||||
Object throttleKey, EntityPlayer player, IChatComponent text, short intervalRequired) {
|
||||
public static void addThrottledChat(Object throttleKey, EntityPlayer player, IChatComponent text,
|
||||
short intervalRequired) {
|
||||
addThrottledChat(throttleKey, player, text, intervalRequired, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send chat to player, but throttled.
|
||||
*
|
||||
* @param throttleKey throttle key. Must properly implement {@link Object#hashCode()} and {@link Object#equals(Object)}
|
||||
* to handle value equality.
|
||||
* @param throttleKey throttle key. Must properly implement {@link Object#hashCode()} and
|
||||
* {@link Object#equals(Object)} to handle value equality.
|
||||
* @param player player to send chat to
|
||||
* @param text chat to send
|
||||
* @param intervalRequired interval required before last recorded time to actually send the message. unit in millisecond.
|
||||
* we purposefully chose to not use a bigger data type to limit how long this interval can be
|
||||
* @param intervalRequired interval required before last recorded time to actually send the message. unit in
|
||||
* millisecond. we purposefully chose to not use a bigger data type to limit how long
|
||||
* this interval can be
|
||||
* @param forceUpdateLastSend if true, always update the last send time, even if the message isn't actually sent.
|
||||
*/
|
||||
public static void addThrottledChat(
|
||||
Object throttleKey,
|
||||
EntityPlayer player,
|
||||
IChatComponent text,
|
||||
short intervalRequired,
|
||||
boolean forceUpdateLastSend) {
|
||||
public static void addThrottledChat(Object throttleKey, EntityPlayer player, IChatComponent text,
|
||||
short intervalRequired, boolean forceUpdateLastSend) {
|
||||
proxy.addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.gtnewhorizon.structurelib.alignment;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
class AlignmentLimits implements IAlignmentLimits {
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
|
||||
public class AlignmentUtility {
|
||||
|
||||
private AlignmentUtility() {}
|
||||
|
||||
public static boolean handle(EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ) {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.gtnewhorizon.structurelib.alignment;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Direction;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public interface IAlignment extends IAlignmentLimits, IAlignmentProvider {
|
||||
|
||||
int DIRECTIONS_COUNT = Direction.VALUES.length;
|
||||
int ROTATIONS_COUNT = Rotation.VALUES.length;
|
||||
int FLIPS_COUNT = Flip.VALUES.length;
|
||||
@@ -15,8 +17,8 @@ public interface IAlignment extends IAlignmentLimits, IAlignmentProvider {
|
||||
ExtendedFacing getExtendedFacing();
|
||||
|
||||
/**
|
||||
* Set the facing without additional checks.
|
||||
* Tools altering facing should use {@link #toolSetExtendedFacing(ExtendedFacing)} instead.
|
||||
* Set the facing without additional checks. Tools altering facing should use
|
||||
* {@link #toolSetExtendedFacing(ExtendedFacing)} instead.
|
||||
*/
|
||||
void setExtendedFacing(ExtendedFacing alignment);
|
||||
|
||||
@@ -57,9 +59,8 @@ public interface IAlignment extends IAlignmentLimits, IAlignmentProvider {
|
||||
|
||||
default boolean toolSetDirection(ForgeDirection direction) {
|
||||
if (direction == null || direction == ForgeDirection.UNKNOWN) {
|
||||
for (int i = 0, j = getDirection().ordinal() + 1, valuesLength = Direction.VALUES.length;
|
||||
i < valuesLength;
|
||||
i++) {
|
||||
for (int i = 0, j = getDirection().ordinal() + 1, valuesLength = Direction.VALUES.length; i
|
||||
< valuesLength; i++) {
|
||||
if (toolSetDirection(Direction.VALUES[(j + i) % valuesLength].getForgeDirection())) {
|
||||
return true;
|
||||
}
|
||||
@@ -97,8 +98,11 @@ public interface IAlignment extends IAlignmentLimits, IAlignmentProvider {
|
||||
int rotations = Rotation.VALUES.length;
|
||||
for (int ii = 0, jj = getFlip().ordinal(); ii < flips; ii++) {
|
||||
for (int i = 1, j = getRotation().ordinal(); i < rotations; i++) {
|
||||
if (checkedSetExtendedFacing(ExtendedFacing.of(
|
||||
getDirection(), Rotation.VALUES[(j + i) % rotations], Flip.VALUES[(jj + ii) % flips]))) {
|
||||
if (checkedSetExtendedFacing(
|
||||
ExtendedFacing.of(
|
||||
getDirection(),
|
||||
Rotation.VALUES[(j + i) % rotations],
|
||||
Flip.VALUES[(jj + ii) % flips]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -140,9 +144,8 @@ public interface IAlignment extends IAlignmentLimits, IAlignmentProvider {
|
||||
|
||||
default boolean toolSetExtendedFacing(ExtendedFacing extendedFacing) {
|
||||
if (extendedFacing == null) {
|
||||
for (int i = 0, j = getExtendedFacing().ordinal() + 1, valuesLength = ExtendedFacing.VALUES.length;
|
||||
i < valuesLength;
|
||||
i++) {
|
||||
for (int i = 0, j = getExtendedFacing().ordinal() + 1, valuesLength = ExtendedFacing.VALUES.length; i
|
||||
< valuesLength; i++) {
|
||||
if (checkedSetExtendedFacing(ExtendedFacing.VALUES[(j + i) % valuesLength])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,16 @@ package com.gtnewhorizon.structurelib.alignment;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.alignment.IAlignment.STATES_COUNT;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
|
||||
|
||||
public interface IAlignmentLimits {
|
||||
|
||||
IAlignmentLimits UNLIMITED = (direction, rotation, flip) -> true;
|
||||
@@ -37,6 +39,7 @@ public interface IAlignmentLimits {
|
||||
}
|
||||
|
||||
class Builder {
|
||||
|
||||
protected final boolean[] validStates = new boolean[STATES_COUNT];
|
||||
|
||||
private Builder() {}
|
||||
@@ -54,15 +57,13 @@ public interface IAlignmentLimits {
|
||||
}
|
||||
|
||||
public Builder deny(ForgeDirection fd) {
|
||||
ExtendedFacing.getAllWith(fd).stream()
|
||||
.mapToInt(ExtendedFacing::getIndex)
|
||||
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
||||
.forEach(v -> validStates[v] = false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder allow(ForgeDirection fd) {
|
||||
ExtendedFacing.getAllWith(fd).stream()
|
||||
.mapToInt(ExtendedFacing::getIndex)
|
||||
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
||||
.forEach(v -> validStates[v] = true);
|
||||
return this;
|
||||
}
|
||||
@@ -78,29 +79,25 @@ public interface IAlignmentLimits {
|
||||
}
|
||||
|
||||
public Builder deny(Rotation fd) {
|
||||
ExtendedFacing.getAllWith(fd).stream()
|
||||
.mapToInt(ExtendedFacing::getIndex)
|
||||
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
||||
.forEach(v -> validStates[v] = false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder allow(Rotation fd) {
|
||||
ExtendedFacing.getAllWith(fd).stream()
|
||||
.mapToInt(ExtendedFacing::getIndex)
|
||||
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
||||
.forEach(v -> validStates[v] = true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder deny(Flip fd) {
|
||||
ExtendedFacing.getAllWith(fd).stream()
|
||||
.mapToInt(ExtendedFacing::getIndex)
|
||||
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
||||
.forEach(v -> validStates[v] = false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder allow(Flip fd) {
|
||||
ExtendedFacing.getAllWith(fd).stream()
|
||||
.mapToInt(ExtendedFacing::getIndex)
|
||||
ExtendedFacing.getAllWith(fd).stream().mapToInt(ExtendedFacing::getIndex)
|
||||
.forEach(v -> validStates[v] = true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.alignment;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface IAlignmentProvider {
|
||||
|
||||
@Nullable
|
||||
IAlignment getAlignment();
|
||||
}
|
||||
@@ -2,12 +2,14 @@ package com.gtnewhorizon.structurelib.alignment;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Direction;
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.Direction;
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
|
||||
public class IntegerAxisSwap {
|
||||
|
||||
private final Vec3Impl forFirstAxis;
|
||||
private final Vec3Impl forSecondAxis;
|
||||
private final Vec3Impl forThirdAxis;
|
||||
@@ -20,61 +22,49 @@ public class IntegerAxisSwap {
|
||||
|| abs(this.forFirstAxis.get1()) + abs(this.forSecondAxis.get1()) + abs(this.forThirdAxis.get1()) != 1
|
||||
|| abs(this.forFirstAxis.get2()) + abs(this.forSecondAxis.get2()) + abs(this.forThirdAxis.get2())
|
||||
!= 1) {
|
||||
throw new IllegalArgumentException("Axis are overlapping/missing! " + forFirstAxis.name()
|
||||
+ " " + forSecondAxis.name()
|
||||
+ " " + forThirdAxis.name());
|
||||
throw new IllegalArgumentException(
|
||||
"Axis are overlapping/missing! " + forFirstAxis
|
||||
.name() + " " + forSecondAxis.name() + " " + forThirdAxis.name());
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3Impl translate(Vec3Impl point) {
|
||||
return new Vec3Impl(
|
||||
forFirstAxis.get0() * point.get0()
|
||||
+ forFirstAxis.get1() * point.get1()
|
||||
forFirstAxis.get0() * point.get0() + forFirstAxis.get1() * point.get1()
|
||||
+ forFirstAxis.get2() * point.get2(),
|
||||
forSecondAxis.get0() * point.get0()
|
||||
+ forSecondAxis.get1() * point.get1()
|
||||
forSecondAxis.get0() * point.get0() + forSecondAxis.get1() * point.get1()
|
||||
+ forSecondAxis.get2() * point.get2(),
|
||||
forThirdAxis.get0() * point.get0()
|
||||
+ forThirdAxis.get1() * point.get1()
|
||||
forThirdAxis.get0() * point.get0() + forThirdAxis.get1() * point.get1()
|
||||
+ forThirdAxis.get2() * point.get2());
|
||||
}
|
||||
|
||||
public Vec3Impl inverseTranslate(Vec3Impl point) {
|
||||
return new Vec3Impl(
|
||||
forFirstAxis.get0() * point.get0()
|
||||
+ forSecondAxis.get0() * point.get1()
|
||||
forFirstAxis.get0() * point.get0() + forSecondAxis.get0() * point.get1()
|
||||
+ forThirdAxis.get0() * point.get2(),
|
||||
forFirstAxis.get1() * point.get0()
|
||||
+ forSecondAxis.get1() * point.get1()
|
||||
forFirstAxis.get1() * point.get0() + forSecondAxis.get1() * point.get1()
|
||||
+ forThirdAxis.get1() * point.get2(),
|
||||
forFirstAxis.get2() * point.get0()
|
||||
+ forSecondAxis.get2() * point.get1()
|
||||
forFirstAxis.get2() * point.get0() + forSecondAxis.get2() * point.get1()
|
||||
+ forThirdAxis.get2() * point.get2());
|
||||
}
|
||||
|
||||
public Vec3 translate(Vec3 point) {
|
||||
return Vec3.createVectorHelper(
|
||||
forFirstAxis.get0() * point.xCoord
|
||||
+ forFirstAxis.get1() * point.yCoord
|
||||
forFirstAxis.get0() * point.xCoord + forFirstAxis.get1() * point.yCoord
|
||||
+ forFirstAxis.get2() * point.zCoord,
|
||||
forSecondAxis.get0() * point.xCoord
|
||||
+ forSecondAxis.get1() * point.yCoord
|
||||
forSecondAxis.get0() * point.xCoord + forSecondAxis.get1() * point.yCoord
|
||||
+ forSecondAxis.get2() * point.zCoord,
|
||||
forThirdAxis.get0() * point.xCoord
|
||||
+ forThirdAxis.get1() * point.yCoord
|
||||
forThirdAxis.get0() * point.xCoord + forThirdAxis.get1() * point.yCoord
|
||||
+ forThirdAxis.get2() * point.zCoord);
|
||||
}
|
||||
|
||||
public Vec3 inverseTranslate(Vec3 point) {
|
||||
return Vec3.createVectorHelper(
|
||||
forFirstAxis.get0() * point.xCoord
|
||||
+ forSecondAxis.get0() * point.yCoord
|
||||
forFirstAxis.get0() * point.xCoord + forSecondAxis.get0() * point.yCoord
|
||||
+ forThirdAxis.get0() * point.zCoord,
|
||||
forFirstAxis.get1() * point.xCoord
|
||||
+ forSecondAxis.get1() * point.yCoord
|
||||
forFirstAxis.get1() * point.xCoord + forSecondAxis.get1() * point.yCoord
|
||||
+ forThirdAxis.get1() * point.zCoord,
|
||||
forFirstAxis.get2() * point.xCoord
|
||||
+ forSecondAxis.get2() * point.yCoord
|
||||
forFirstAxis.get2() * point.xCoord + forSecondAxis.get2() * point.yCoord
|
||||
+ forThirdAxis.get2() * point.zCoord);
|
||||
}
|
||||
|
||||
|
||||
+39
-46
@@ -3,23 +3,27 @@ package com.gtnewhorizon.structurelib.alignment.constructable;
|
||||
import static com.gtnewhorizon.structurelib.util.MiscUtils.getTagKeys;
|
||||
import static net.minecraftforge.common.util.Constants.NBT.TAG_COMPOUND;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
|
||||
/**
|
||||
* Provide accessor methods for channel data from trigger item.
|
||||
*
|
||||
* <a href="{@docRoot}/overview-summary.html#channels">Channels section on overview</a>
|
||||
*/
|
||||
public class ChannelDataAccessor {
|
||||
|
||||
private static final String SECONDARY_HINT_TAG = "channels";
|
||||
|
||||
private ChannelDataAccessor() {}
|
||||
@@ -27,29 +31,25 @@ public class ChannelDataAccessor {
|
||||
/**
|
||||
* Return a trigger item that
|
||||
* <ul>
|
||||
* <li>Still carry all the subchannel in some unspecified ways</li>
|
||||
* <li>Have its master channel data replaced with specified subchannel's data</li>
|
||||
* <li>Still carry all the subchannel in some unspecified ways</li>
|
||||
* <li>Have its master channel data replaced with specified subchannel's data</li>
|
||||
* </ul>
|
||||
*
|
||||
* If given subchannel does not exist, masterStack may or may not be returned to save performance.
|
||||
* Code within StructureLib can depend on this behavior, you cannot.
|
||||
* If given subchannel does not exist, masterStack may or may not be returned to save performance. Code within
|
||||
* StructureLib can depend on this behavior, you cannot.
|
||||
*
|
||||
* @param masterStack trigger item. can be the return value of another {@link #withChannel(ItemStack, String)} call
|
||||
* @param channel subchannel to use. will use current master channel data instead if this channel does not exist
|
||||
* Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @param channel subchannel to use. will use current master channel data instead if this channel does not exist
|
||||
* Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @return a trigger item with new master channel
|
||||
*/
|
||||
public static ItemStack withChannel(ItemStack masterStack, String channel) {
|
||||
if (StringUtils.isEmpty(channel) || masterStack == null) throw new IllegalArgumentException();
|
||||
if (StructureLibAPI.isDebugEnabled()
|
||||
&& !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
if (StructureLibAPI.isDebugEnabled() && !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
throw new IllegalArgumentException("Channel name can be lower case ONLY");
|
||||
if (!masterStack.hasTagCompound()
|
||||
|| !masterStack.stackTagCompound.hasKey(SECONDARY_HINT_TAG, TAG_COMPOUND)
|
||||
|| !masterStack
|
||||
.stackTagCompound
|
||||
.getCompoundTag(SECONDARY_HINT_TAG)
|
||||
.hasKey(channel, NBT.TAG_INT)) return masterStack;
|
||||
if (!masterStack.hasTagCompound() || !masterStack.stackTagCompound.hasKey(SECONDARY_HINT_TAG, TAG_COMPOUND)
|
||||
|| !masterStack.stackTagCompound.getCompoundTag(SECONDARY_HINT_TAG).hasKey(channel, NBT.TAG_INT))
|
||||
return masterStack;
|
||||
ItemStack ret = new ItemStack(
|
||||
masterStack.getItem(),
|
||||
masterStack.stackTagCompound.getCompoundTag(SECONDARY_HINT_TAG).getInteger(channel),
|
||||
@@ -60,6 +60,7 @@ public class ChannelDataAccessor {
|
||||
|
||||
/**
|
||||
* Check if given trigger item contains any subchannel
|
||||
*
|
||||
* @param masterStack trigger stack to check
|
||||
* @return true if contains any subchannel
|
||||
*/
|
||||
@@ -70,57 +71,47 @@ public class ChannelDataAccessor {
|
||||
|
||||
/**
|
||||
* Check if given trigger item contains specified subchannel
|
||||
*
|
||||
* @param masterStack trigger stack to check
|
||||
* @param channel channel identifier.
|
||||
* Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @param channel channel identifier. Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @return true if contains specified subchannel
|
||||
*/
|
||||
public static boolean hasSubChannel(ItemStack masterStack, String channel) {
|
||||
if (StringUtils.isEmpty(channel) || masterStack == null) throw new IllegalArgumentException();
|
||||
if (StructureLibAPI.isDebugEnabled()
|
||||
&& !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
if (StructureLibAPI.isDebugEnabled() && !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
throw new IllegalArgumentException("Channel name can be lower case ONLY");
|
||||
return !channel.isEmpty()
|
||||
&& masterStack.hasTagCompound()
|
||||
return !channel.isEmpty() && masterStack.hasTagCompound()
|
||||
&& masterStack.stackTagCompound.hasKey(SECONDARY_HINT_TAG, TAG_COMPOUND)
|
||||
&& masterStack
|
||||
.stackTagCompound
|
||||
.getCompoundTag(SECONDARY_HINT_TAG)
|
||||
.hasKey(channel, NBT.TAG_INT);
|
||||
&& masterStack.stackTagCompound.getCompoundTag(SECONDARY_HINT_TAG).hasKey(channel, NBT.TAG_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subchannel data from given trigger item. Will use master channel instead if not present.
|
||||
*
|
||||
* @param masterStack trigger stack to query from
|
||||
* @param channel channel identifier.
|
||||
* Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @param channel channel identifier. Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @return channel data
|
||||
*/
|
||||
public static int getChannelData(ItemStack masterStack, String channel) {
|
||||
if (StringUtils.isEmpty(channel) || masterStack == null) throw new IllegalArgumentException();
|
||||
if (StructureLibAPI.isDebugEnabled()
|
||||
&& !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
if (StructureLibAPI.isDebugEnabled() && !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
throw new IllegalArgumentException("Channel name can be lower case ONLY");
|
||||
if (!masterStack.hasTagCompound()
|
||||
|| !masterStack.stackTagCompound.hasKey(SECONDARY_HINT_TAG, TAG_COMPOUND)
|
||||
|| !masterStack
|
||||
.stackTagCompound
|
||||
.getCompoundTag(SECONDARY_HINT_TAG)
|
||||
.hasKey(channel, NBT.TAG_INT)) return masterStack.stackSize;
|
||||
if (!masterStack.hasTagCompound() || !masterStack.stackTagCompound.hasKey(SECONDARY_HINT_TAG, TAG_COMPOUND)
|
||||
|| !masterStack.stackTagCompound.getCompoundTag(SECONDARY_HINT_TAG).hasKey(channel, NBT.TAG_INT))
|
||||
return masterStack.stackSize;
|
||||
return masterStack.stackTagCompound.getCompoundTag(SECONDARY_HINT_TAG).getInteger(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subchannel data on given trigger item
|
||||
*
|
||||
* @param masterStack trigger stack to check
|
||||
* @param channel channel identifier.
|
||||
* Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @param data subchannel data. should always be a positive value
|
||||
* @param channel channel identifier. Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @param data subchannel data. should always be a positive value
|
||||
*/
|
||||
public static void setChannelData(ItemStack masterStack, String channel, int data) {
|
||||
if (StringUtils.isEmpty(channel) || masterStack == null) throw new IllegalArgumentException();
|
||||
if (StructureLibAPI.isDebugEnabled()
|
||||
&& !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
if (StructureLibAPI.isDebugEnabled() && !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
throw new IllegalArgumentException("Channel name can be lower case ONLY");
|
||||
if (data <= 0) throw new IllegalArgumentException();
|
||||
if (masterStack.stackTagCompound == null) masterStack.stackTagCompound = new NBTTagCompound();
|
||||
@@ -131,14 +122,13 @@ public class ChannelDataAccessor {
|
||||
|
||||
/**
|
||||
* Clear the given subchannel from given trigger item, if it exists
|
||||
*
|
||||
* @param masterStack trigger stack to unset
|
||||
* @param channel channel identifier.
|
||||
* Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
* @param channel channel identifier. Note: all channel identifiers are supposed to be lower case and not empty.
|
||||
*/
|
||||
public static void unsetChannelData(ItemStack masterStack, String channel) {
|
||||
if (StringUtils.isEmpty(channel) || masterStack == null) throw new IllegalArgumentException();
|
||||
if (StructureLibAPI.isDebugEnabled()
|
||||
&& !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
if (StructureLibAPI.isDebugEnabled() && !channel.toLowerCase(Locale.ROOT).equals(channel))
|
||||
throw new IllegalArgumentException("Channel name can be lower case ONLY");
|
||||
if (masterStack.stackTagCompound == null) masterStack.stackTagCompound = new NBTTagCompound();
|
||||
NBTTagCompound main = masterStack.stackTagCompound;
|
||||
@@ -151,6 +141,7 @@ public class ChannelDataAccessor {
|
||||
|
||||
/**
|
||||
* Wipe all subchannel data on given trigger item
|
||||
*
|
||||
* @param masterStack trigger stack to wipe
|
||||
*/
|
||||
public static void wipeChannelData(ItemStack masterStack) {
|
||||
@@ -160,10 +151,11 @@ public class ChannelDataAccessor {
|
||||
|
||||
/**
|
||||
* Iterate over all subchannel data on trigger stack. Does not include master channel!!
|
||||
*
|
||||
* @param masterStack trigger stack to check
|
||||
* @return A java8 stream of pairs. Key is channel identifier and value is channel data. Pairs do not support
|
||||
* mutation nor removal. Can still cause {@link java.util.ConcurrentModificationException} if underlying channel
|
||||
* data is modified while stream is working.
|
||||
* mutation nor removal. Can still cause {@link java.util.ConcurrentModificationException} if underlying
|
||||
* channel data is modified while stream is working.
|
||||
*/
|
||||
public static Stream<Entry<String, Integer>> iterateChannelData(ItemStack masterStack) {
|
||||
if (!hasSubChannel(masterStack)) return Stream.empty();
|
||||
@@ -173,6 +165,7 @@ public class ChannelDataAccessor {
|
||||
|
||||
/**
|
||||
* Get the number of subchannels present on given trigger item. Does not include master channel.
|
||||
*
|
||||
* @param masterStack trigger stack to query from
|
||||
* @return subchannel count
|
||||
*/
|
||||
|
||||
+22
-21
@@ -1,13 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.alignment.constructable;
|
||||
|
||||
import com.gtnewhorizon.structurelib.ConfigurationHandler;
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.IItemSource;
|
||||
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -17,6 +11,14 @@ import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.structurelib.ConfigurationHandler;
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.IItemSource;
|
||||
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
|
||||
|
||||
public class ConstructableUtility {
|
||||
|
||||
private static final WeakHashMap<EntityPlayerMP, Long> lastUse = new WeakHashMap<>();
|
||||
@@ -24,16 +26,16 @@ public class ConstructableUtility {
|
||||
|
||||
private ConstructableUtility() {}
|
||||
|
||||
public static boolean handle(
|
||||
ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, int aSide) {
|
||||
public static boolean handle(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
|
||||
int aSide) {
|
||||
StructureLibAPI.startHinting(aWorld);
|
||||
boolean ret = handle0(aStack, aPlayer, aWorld, aX, aY, aZ, aSide);
|
||||
StructureLibAPI.endHinting(aWorld);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static boolean handle0(
|
||||
ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, int aSide) {
|
||||
private static boolean handle0(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
|
||||
int aSide) {
|
||||
TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
|
||||
if (tTileEntity == null || aPlayer instanceof FakePlayer) {
|
||||
return aPlayer instanceof EntityPlayerMP;
|
||||
@@ -44,9 +46,10 @@ public class ConstructableUtility {
|
||||
|
||||
long timePast = System.currentTimeMillis() - getLastUseMilis(aPlayer);
|
||||
if (timePast < ConfigurationHandler.INSTANCE.getAutoPlaceInterval()) {
|
||||
aPlayer.addChatComponentMessage(new ChatComponentTranslation(
|
||||
"item.structurelib.constructableTrigger.too_fast",
|
||||
ConfigurationHandler.INSTANCE.getAutoPlaceInterval() - timePast));
|
||||
aPlayer.addChatComponentMessage(
|
||||
new ChatComponentTranslation(
|
||||
"item.structurelib.constructableTrigger.too_fast",
|
||||
ConfigurationHandler.INSTANCE.getAutoPlaceInterval() - timePast));
|
||||
return true;
|
||||
}
|
||||
} else if (!StructureLib.isCurrentPlayer(aPlayer)) {
|
||||
@@ -59,8 +62,7 @@ public class ConstructableUtility {
|
||||
else if (tTileEntity instanceof IConstructable) {
|
||||
constructable = (IConstructable) tTileEntity;
|
||||
} else if (IMultiblockInfoContainer.contains(tTileEntity.getClass())) {
|
||||
ExtendedFacing facing = tTileEntity instanceof IAlignment
|
||||
? ((IAlignment) tTileEntity).getExtendedFacing()
|
||||
ExtendedFacing facing = tTileEntity instanceof IAlignment ? ((IAlignment) tTileEntity).getExtendedFacing()
|
||||
: ExtendedFacing.of(ForgeDirection.getOrientation(aSide));
|
||||
constructable = IMultiblockInfoContainer.<TileEntity>get(tTileEntity.getClass())
|
||||
.toConstructable(tTileEntity, facing);
|
||||
@@ -75,11 +77,10 @@ public class ConstructableUtility {
|
||||
if (aPlayer.capabilities.isCreativeMode) {
|
||||
constructable.construct(aStack, false);
|
||||
} else if (constructable instanceof ISurvivalConstructable) {
|
||||
int built = ((ISurvivalConstructable) constructable)
|
||||
.survivalConstruct(
|
||||
aStack,
|
||||
ConfigurationHandler.INSTANCE.getAutoPlaceBudget(),
|
||||
ISurvivalBuildEnvironment.create(IItemSource.fromPlayer(playerMP), playerMP));
|
||||
int built = ((ISurvivalConstructable) constructable).survivalConstruct(
|
||||
aStack,
|
||||
ConfigurationHandler.INSTANCE.getAutoPlaceBudget(),
|
||||
ISurvivalBuildEnvironment.create(IItemSource.fromPlayer(playerMP), playerMP));
|
||||
if (built > 0) {
|
||||
playerMP.addChatMessage(new ChatComponentTranslation("structurelib.autoplace.built_stat", built));
|
||||
} else if (built == -1) {
|
||||
|
||||
+4
-1
@@ -1,14 +1,17 @@
|
||||
package com.gtnewhorizon.structurelib.alignment.constructable;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Created by Tec on 24.03.2017.
|
||||
*/
|
||||
public interface IConstructable {
|
||||
|
||||
void construct(ItemStack stackSize, boolean hintsOnly);
|
||||
|
||||
/**
|
||||
|
||||
+1
@@ -6,6 +6,7 @@ import javax.annotation.Nullable;
|
||||
* Implement this interface if this tile entity MIGHT be constructable
|
||||
*/
|
||||
public interface IConstructableProvider {
|
||||
|
||||
/**
|
||||
* @return null if not constructable, an instance otherwise.
|
||||
*/
|
||||
|
||||
+19
-16
@@ -1,19 +1,23 @@
|
||||
package com.gtnewhorizon.structurelib.alignment.constructable;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.IItemSource;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.IItemSource;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
/**
|
||||
* To implement IConstructable on not own TileEntities
|
||||
*/
|
||||
public interface IMultiblockInfoContainer<T> {
|
||||
|
||||
HashMap<String, IMultiblockInfoContainer<?>> MULTIBLOCK_MAP = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -36,16 +40,13 @@ public interface IMultiblockInfoContainer<T> {
|
||||
void construct(ItemStack stackSize, boolean hintsOnly, T tileEntity, ExtendedFacing aSide);
|
||||
|
||||
/**
|
||||
* Construct the structure using {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, java.util.function.Consumer)}
|
||||
* Construct the structure using
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, java.util.function.Consumer)}
|
||||
*
|
||||
* @return -1 if done, a helping pointer
|
||||
*/
|
||||
default int survivalConstruct(
|
||||
ItemStack stackSize,
|
||||
int elementBudge,
|
||||
IItemSource source,
|
||||
EntityPlayerMP actorProfile,
|
||||
T tileEntity,
|
||||
ExtendedFacing aSide) {
|
||||
default int survivalConstruct(ItemStack stackSize, int elementBudge, IItemSource source,
|
||||
EntityPlayerMP actorProfile, T tileEntity, ExtendedFacing aSide) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ public interface IMultiblockInfoContainer<T> {
|
||||
*/
|
||||
default IConstructable toConstructable(T tileEntity, ExtendedFacing aSide) {
|
||||
return new IConstructable() {
|
||||
|
||||
@Override
|
||||
public void construct(ItemStack stackSize, boolean hintsOnly) {
|
||||
IMultiblockInfoContainer.this.construct(stackSize, hintsOnly, tileEntity, aSide);
|
||||
@@ -70,12 +72,13 @@ public interface IMultiblockInfoContainer<T> {
|
||||
};
|
||||
}
|
||||
|
||||
static <T> ISurvivalConstructable toConstructable(
|
||||
IMultiblockInfoContainer<T> thiz, T tileEntity, ExtendedFacing aSide) {
|
||||
static <T> ISurvivalConstructable toConstructable(IMultiblockInfoContainer<T> thiz, T tileEntity,
|
||||
ExtendedFacing aSide) {
|
||||
return new ISurvivalConstructable() {
|
||||
|
||||
@Override
|
||||
public int survivalConstruct(
|
||||
ItemStack stackSize, int elementBudget, IItemSource source, EntityPlayerMP actor) {
|
||||
public int survivalConstruct(ItemStack stackSize, int elementBudget, IItemSource source,
|
||||
EntityPlayerMP actor) {
|
||||
return thiz.survivalConstruct(stackSize, elementBudget, source, actor, tileEntity, aSide);
|
||||
}
|
||||
|
||||
|
||||
+19
-12
@@ -1,31 +1,35 @@
|
||||
package com.gtnewhorizon.structurelib.alignment.constructable;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
|
||||
import com.gtnewhorizon.structurelib.structure.IItemSource;
|
||||
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
|
||||
import com.gtnewhorizon.structurelib.structure.IItemSource;
|
||||
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
|
||||
|
||||
/**
|
||||
* An extension to {@link IConstructable}. Tile Entities (or delegates returned by {@link IConstructableProvider#getConstructable()}
|
||||
* should implement this interface to allow third party tools and StructureLib builtin constructable tools to trigger
|
||||
* autoplace in survival mode.
|
||||
* An extension to {@link IConstructable}. Tile Entities (or delegates returned by
|
||||
* {@link IConstructableProvider#getConstructable()} should implement this interface to allow third party tools and
|
||||
* StructureLib builtin constructable tools to trigger autoplace in survival mode.
|
||||
* <p>
|
||||
* While not originally planned, a creative player can also use this interface to trigger autoplace by using an
|
||||
* {@link IItemSource} with every possible items in the game.
|
||||
*/
|
||||
public interface ISurvivalConstructable extends IConstructable {
|
||||
|
||||
/**
|
||||
* End player might want to disable this hack if it turns out to be too crashy
|
||||
*/
|
||||
boolean DISABLE_HACKY_MIGRATION_CODE = Boolean.getBoolean("structurelib.disable_isc_migration_hack");
|
||||
|
||||
/**
|
||||
* Construct the structure using {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, java.util.function.Consumer)}
|
||||
* or {@link com.gtnewhorizon.structurelib.structure.IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, IItemSource, EntityPlayerMP, boolean)}
|
||||
* Construct the structure using
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, java.util.function.Consumer)}
|
||||
* or
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, IItemSource, EntityPlayerMP, boolean)}
|
||||
*
|
||||
* @param elementBudget The server configured element budget. The implementor can choose to tune this up a bit if
|
||||
* the structure is too big, but generally should not be a 4 digits number to not overwhelm the
|
||||
@@ -38,14 +42,16 @@ public interface ISurvivalConstructable extends IConstructable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the structure using {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
* or {@link com.gtnewhorizon.structurelib.structure.IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, ISurvivalBuildEnvironment, boolean)}
|
||||
* Construct the structure using
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
* or
|
||||
* {@link com.gtnewhorizon.structurelib.structure.IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, ISurvivalBuildEnvironment, boolean)}
|
||||
*
|
||||
* @param elementBudget The server configured element budget. The implementor can choose to tune this up a bit if
|
||||
* the structure is too big, but generally should not be a 4 digits number to not overwhelm the
|
||||
* server
|
||||
* @return -1 if done, -2 if not supported (e.g. due to an incompatible change in the API of env, otherwise number
|
||||
* of elements placed this round
|
||||
* of elements placed this round
|
||||
*/
|
||||
default int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
|
||||
EntityPlayer actor = env.getActor();
|
||||
@@ -74,5 +80,6 @@ public interface ISurvivalConstructable extends IConstructable {
|
||||
}
|
||||
|
||||
class GlobalStates {
|
||||
|
||||
public static final ThreadLocal<EntityPlayer> entityPlayer = new ThreadLocal<>();
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
package com.gtnewhorizon.structurelib.alignment.enumerable;
|
||||
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
|
||||
public enum Direction {
|
||||
|
||||
DOWN(ForgeDirection.DOWN),
|
||||
UP(ForgeDirection.UP),
|
||||
NORTH(ForgeDirection.NORTH),
|
||||
@@ -18,8 +21,8 @@ public enum Direction {
|
||||
private final ForgeDirection forgeDirection;
|
||||
private final Vec3Impl axisVector;
|
||||
public static final Direction[] VALUES = values();
|
||||
private static final Map<Vec3Impl, Direction> reverseMap =
|
||||
Arrays.stream(VALUES).collect(Collectors.toMap(d -> d.axisVector, Function.identity()));
|
||||
private static final Map<Vec3Impl, Direction> reverseMap = Arrays.stream(VALUES)
|
||||
.collect(Collectors.toMap(d -> d.axisVector, Function.identity()));
|
||||
|
||||
Direction(ForgeDirection forgeDirection) {
|
||||
this.forgeDirection = forgeDirection;
|
||||
|
||||
+29
-26
@@ -6,16 +6,19 @@ import static java.lang.Math.abs;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.Collectors.*;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IntegerAxisSwap;
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
import java.util.*;
|
||||
|
||||
import net.minecraft.util.StatCollector;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IntegerAxisSwap;
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
|
||||
public enum ExtendedFacing {
|
||||
|
||||
DOWN_NORMAL_NONE("down normal none"),
|
||||
DOWN_NORMAL_HORIZONTAL("down normal horizontal"),
|
||||
DOWN_NORMAL_VERTICAL("down normal vertical"),
|
||||
@@ -119,31 +122,31 @@ public enum ExtendedFacing {
|
||||
public static final int STATES_COUNT = VALUES.length;
|
||||
|
||||
static {
|
||||
stream(values())
|
||||
.forEach(extendedFacing ->
|
||||
FOR_FACING.compute(extendedFacing.direction, ((forgeDirection, extendedFacings) -> {
|
||||
if (extendedFacings == null) {
|
||||
extendedFacings = new ArrayList<>();
|
||||
}
|
||||
extendedFacings.add(extendedFacing);
|
||||
return extendedFacings;
|
||||
})));
|
||||
stream(values()).forEach(
|
||||
extendedFacing -> FOR_FACING.compute(extendedFacing.direction, ((forgeDirection, extendedFacings) -> {
|
||||
if (extendedFacings == null) {
|
||||
extendedFacings = new ArrayList<>();
|
||||
}
|
||||
extendedFacings.add(extendedFacing);
|
||||
return extendedFacings;
|
||||
})));
|
||||
}
|
||||
|
||||
private static final Map<String, ExtendedFacing> NAME_LOOKUP =
|
||||
stream(VALUES).collect(toMap(ExtendedFacing::getName2, (extendedFacing) -> extendedFacing));
|
||||
private static final Map<String, ExtendedFacing> NAME_LOOKUP = stream(VALUES)
|
||||
.collect(toMap(ExtendedFacing::getName2, (extendedFacing) -> extendedFacing));
|
||||
private static final EnumMap<ForgeDirection, ImmutableSet<ExtendedFacing>> LOOKUP_BY_DIRECTION = stream(VALUES)
|
||||
.collect(groupingBy(
|
||||
ExtendedFacing::getDirection,
|
||||
() -> new EnumMap<>(ForgeDirection.class),
|
||||
collectingAndThen(toSet(), ImmutableSet::copyOf)));
|
||||
private static final EnumMap<Rotation, ImmutableSet<ExtendedFacing>> LOOKUP_BY_ROTATION = stream(VALUES)
|
||||
.collect(groupingBy(
|
||||
.collect(
|
||||
groupingBy(
|
||||
ExtendedFacing::getDirection,
|
||||
() -> new EnumMap<>(ForgeDirection.class),
|
||||
collectingAndThen(toSet(), ImmutableSet::copyOf)));
|
||||
private static final EnumMap<Rotation, ImmutableSet<ExtendedFacing>> LOOKUP_BY_ROTATION = stream(VALUES).collect(
|
||||
groupingBy(
|
||||
ExtendedFacing::getRotation,
|
||||
() -> new EnumMap<>(Rotation.class),
|
||||
collectingAndThen(toSet(), ImmutableSet::copyOf)));
|
||||
private static final EnumMap<Flip, ImmutableSet<ExtendedFacing>> LOOKUP_BY_FLIP = stream(VALUES)
|
||||
.collect(groupingBy(
|
||||
private static final EnumMap<Flip, ImmutableSet<ExtendedFacing>> LOOKUP_BY_FLIP = stream(VALUES).collect(
|
||||
groupingBy(
|
||||
ExtendedFacing::getFlip,
|
||||
() -> new EnumMap<>(Flip.class),
|
||||
collectingAndThen(toSet(), ImmutableSet::copyOf)));
|
||||
@@ -333,7 +336,7 @@ public enum ExtendedFacing {
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates relative to front facing offset to world offset
|
||||
* Translates relative to front facing offset to world offset
|
||||
*
|
||||
* @param abcOffset A,B,C offset (facing relative {@code L-->R,U-->D,F-->B})
|
||||
* @return X, Y, Z offset in world
|
||||
@@ -377,10 +380,10 @@ public enum ExtendedFacing {
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates world offset to relative front facing offset
|
||||
* Translates world offset to relative front facing offset
|
||||
*
|
||||
* @param xyzOffset X,Y,Z offset in world
|
||||
* @return A, B, C offset (facing relative {@code L-->R,U-->D,F-->B})
|
||||
* @return A, B, C offset (facing relative {@code L-->R,U-->D,F-->B})
|
||||
*/
|
||||
public Vec3 getOffsetABC(Vec3 xyzOffset) {
|
||||
return integerAxisSwap.translate(xyzOffset);
|
||||
|
||||
@@ -7,9 +7,11 @@ import static java.util.stream.Collectors.toMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public enum Flip {
|
||||
|
||||
NONE(3, "none"),
|
||||
HORIZONTAL(2, "horizontal"),
|
||||
VERTICAL(1, "vertical"),
|
||||
|
||||
@@ -7,9 +7,11 @@ import static java.util.stream.Collectors.toMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public enum Rotation {
|
||||
|
||||
NORMAL(2, "normal"),
|
||||
CLOCKWISE(3, "clockwise"),
|
||||
UPSIDE_DOWN(0, "upside down"),
|
||||
@@ -19,8 +21,8 @@ public enum Rotation {
|
||||
private final String name;
|
||||
|
||||
public static final Rotation[] VALUES = values();
|
||||
private static final Map<String, Rotation> NAME_LOOKUP =
|
||||
stream(VALUES).collect(toMap(Rotation::getName2, (rotation) -> rotation));
|
||||
private static final Map<String, Rotation> NAME_LOOKUP = stream(VALUES)
|
||||
.collect(toMap(Rotation::getName2, (rotation) -> rotation));
|
||||
|
||||
Rotation(int oppositeIn, String nameIn) {
|
||||
this.opposite = oppositeIn;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* This package provide a framework for rotating a given block, or a multiblock structure.
|
||||
* <p>
|
||||
* All public stuff in this package and its subpackages are considered part of the public API.
|
||||
* Backwards compatibility is maintained to the maximum extend possible.
|
||||
* All public stuff in this package and its subpackages are considered part of the public API. Backwards compatibility
|
||||
* is maintained to the maximum extend possible.
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.alignment;
|
||||
@@ -1,10 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.block;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
@@ -14,7 +11,14 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class BlockHint extends Block {
|
||||
|
||||
private static final IIcon[] hint = new IIcon[16];
|
||||
|
||||
public BlockHint() {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.gtnewhorizon.structurelib.command;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.command.WrongUsageException;
|
||||
@@ -13,7 +12,11 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
|
||||
public class CommandConfigureChannels extends CommandBase {
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "sl_channel";
|
||||
@@ -58,13 +61,12 @@ public class CommandConfigureChannels extends CommandBase {
|
||||
if (!ChannelDataAccessor.hasSubChannel(heldItem)) {
|
||||
sender.addChatMessage(new ChatComponentText("No subchannel"));
|
||||
} else {
|
||||
sender.addChatMessage(new ChatComponentTranslation(
|
||||
"item.structurelib.constructableTrigger.desc.lshift.0",
|
||||
ChannelDataAccessor.countChannelData(heldItem)));
|
||||
ChannelDataAccessor.iterateChannelData(heldItem)
|
||||
.map(e -> e.getKey() + ": " + e.getValue())
|
||||
.map(ChatComponentText::new)
|
||||
.forEach(player::addChatMessage);
|
||||
sender.addChatMessage(
|
||||
new ChatComponentTranslation(
|
||||
"item.structurelib.constructableTrigger.desc.lshift.0",
|
||||
ChannelDataAccessor.countChannelData(heldItem)));
|
||||
ChannelDataAccessor.iterateChannelData(heldItem).map(e -> e.getKey() + ": " + e.getValue())
|
||||
.map(ChatComponentText::new).forEach(player::addChatMessage);
|
||||
}
|
||||
return;
|
||||
case "wipe":
|
||||
@@ -73,13 +75,11 @@ public class CommandConfigureChannels extends CommandBase {
|
||||
case "get":
|
||||
case "unset":
|
||||
if (args.length < 2) throw new WrongUsageException(getCommandUsage(sender));
|
||||
channel =
|
||||
args.length == 2 ? args[1] : Arrays.stream(args).skip(1).collect(Collectors.joining());
|
||||
channel = args.length == 2 ? args[1] : Arrays.stream(args).skip(1).collect(Collectors.joining());
|
||||
break;
|
||||
case "set":
|
||||
if (args.length < 3) throw new WrongUsageException(getCommandUsage(sender));
|
||||
channel = args.length == 3
|
||||
? args[1]
|
||||
channel = args.length == 3 ? args[1]
|
||||
: Arrays.stream(args).skip(1).limit(args.length - 2).collect(Collectors.joining());
|
||||
break;
|
||||
default:
|
||||
@@ -88,9 +88,9 @@ public class CommandConfigureChannels extends CommandBase {
|
||||
|
||||
switch (args[0]) {
|
||||
case "get":
|
||||
if (ChannelDataAccessor.hasSubChannel(heldItem, channel))
|
||||
sender.addChatMessage(new ChatComponentText(
|
||||
channel + " value: " + ChannelDataAccessor.getChannelData(heldItem, channel)));
|
||||
if (ChannelDataAccessor.hasSubChannel(heldItem, channel)) sender.addChatMessage(
|
||||
new ChatComponentText(
|
||||
channel + " value: " + ChannelDataAccessor.getChannelData(heldItem, channel)));
|
||||
else sender.addChatMessage(new ChatComponentText(channel + " value: N/A"));
|
||||
break;
|
||||
case "clear":
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
package com.gtnewhorizon.structurelib.entity.fx;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.particle.EntityFX;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class WeightlessParticleFX extends EntityFX {
|
||||
public WeightlessParticleFX(
|
||||
World p_i1205_1_,
|
||||
double p_i1205_2_,
|
||||
double p_i1205_4_,
|
||||
double p_i1205_6_,
|
||||
double p_i1205_8_,
|
||||
double p_i1205_10_,
|
||||
double p_i1205_12_) {
|
||||
|
||||
public WeightlessParticleFX(World p_i1205_1_, double p_i1205_2_, double p_i1205_4_, double p_i1205_6_,
|
||||
double p_i1205_8_, double p_i1205_10_, double p_i1205_12_) {
|
||||
super(p_i1205_1_, p_i1205_2_, p_i1205_4_, p_i1205_6_, p_i1205_8_, p_i1205_10_, p_i1205_12_);
|
||||
this.motionX = p_i1205_8_ + (double) ((float) (Math.random() * 2.0D - 1.0D) * 0.05F);
|
||||
this.motionY = p_i1205_10_ + (double) ((float) (Math.random() * 2.0D - 1.0D) * 0.05F);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package com.gtnewhorizon.structurelib.gui;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.gui.GuiScrollableList.IGuiScreen;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
@@ -15,12 +13,18 @@ import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.gui.GuiScrollableList.IGuiScreen;
|
||||
|
||||
public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen {
|
||||
|
||||
private static final int KEY_MAX_WIDTH = 50;
|
||||
private final ItemStack trigger;
|
||||
private final GuiChannelsList list;
|
||||
@@ -48,6 +52,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
guiTop = (this.height - this.getYSize()) / 2;
|
||||
|
||||
key = new GuiTextField(fontRendererObj, guiLeft + 45, guiTop + 119, 151 + 12 - 45, 12) {
|
||||
|
||||
@Override
|
||||
public void writeText(String text) {
|
||||
// force lower case
|
||||
@@ -58,8 +63,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
@Override
|
||||
public void mouseClicked(int p_146192_1_, int p_146192_2_, int p_146192_3_) {
|
||||
super.mouseClicked(p_146192_1_, p_146192_2_, p_146192_3_);
|
||||
boolean flag = p_146192_1_ >= this.xPosition
|
||||
&& p_146192_1_ < this.xPosition + this.width
|
||||
boolean flag = p_146192_1_ >= this.xPosition && p_146192_1_ < this.xPosition + this.width
|
||||
&& p_146192_2_ >= this.yPosition
|
||||
&& p_146192_2_ < this.yPosition + this.height;
|
||||
if (flag && p_146192_3_ == 1) {
|
||||
@@ -75,6 +79,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
}
|
||||
};
|
||||
value = new GuiTextField(fontRendererObj, guiLeft + 45, guiTop + 139, 151 + 12 - 45, 12) {
|
||||
|
||||
@Override
|
||||
public void writeText(String text) {
|
||||
// ignore write requests containing non digit characters.
|
||||
@@ -104,8 +109,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
@Override
|
||||
public void mouseClicked(int p_146192_1_, int p_146192_2_, int p_146192_3_) {
|
||||
super.mouseClicked(p_146192_1_, p_146192_2_, p_146192_3_);
|
||||
boolean flag = p_146192_1_ >= this.xPosition
|
||||
&& p_146192_1_ < this.xPosition + this.width
|
||||
boolean flag = p_146192_1_ >= this.xPosition && p_146192_1_ < this.xPosition + this.width
|
||||
&& p_146192_2_ >= this.yPosition
|
||||
&& p_146192_2_ < this.yPosition + this.height;
|
||||
if (flag && p_146192_3_ == 1) {
|
||||
@@ -122,22 +126,30 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
|
||||
list.onGuiInit(this);
|
||||
|
||||
addButton(new GuiButton(
|
||||
0, guiLeft + 12, guiTop + 157, 47, 20, I18n.format("item.structurelib.constructableTrigger.gui.add")));
|
||||
addButton(new GuiButton(
|
||||
1,
|
||||
guiLeft + 65,
|
||||
guiTop + 157,
|
||||
47,
|
||||
20,
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.unset")));
|
||||
addButton(new GuiButton(
|
||||
2,
|
||||
guiLeft + 118,
|
||||
guiTop + 157,
|
||||
47,
|
||||
20,
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.wipe")));
|
||||
addButton(
|
||||
new GuiButton(
|
||||
0,
|
||||
guiLeft + 12,
|
||||
guiTop + 157,
|
||||
47,
|
||||
20,
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.add")));
|
||||
addButton(
|
||||
new GuiButton(
|
||||
1,
|
||||
guiLeft + 65,
|
||||
guiTop + 157,
|
||||
47,
|
||||
20,
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.unset")));
|
||||
addButton(
|
||||
new GuiButton(
|
||||
2,
|
||||
guiLeft + 118,
|
||||
guiTop + 157,
|
||||
47,
|
||||
20,
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.wipe")));
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
@@ -238,8 +250,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
// STACKOVERFLOW!
|
||||
String keyText = key.getText();
|
||||
boolean existing = !StringUtils.isEmpty(keyText) && ChannelDataAccessor.hasSubChannel(trigger, keyText);
|
||||
getButtonList().get(0).displayString = existing
|
||||
? I18n.format("item.structurelib.constructableTrigger.gui.set")
|
||||
getButtonList().get(0).displayString = existing ? I18n.format("item.structurelib.constructableTrigger.gui.set")
|
||||
: I18n.format("item.structurelib.constructableTrigger.gui.add");
|
||||
getButtonList().get(0).enabled = !StringUtils.isBlank(value.getText());
|
||||
getButtonList().get(1).enabled = existing && !StringUtils.isBlank(value.getText());
|
||||
@@ -300,14 +311,21 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
super.drawScreen(mX, mY, partialTick);
|
||||
list.drawScreen(mX, mY, partialTick);
|
||||
fontRendererObj.drawString(
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.key"), guiLeft + 12, guiTop + 122, 0);
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.key"),
|
||||
guiLeft + 12,
|
||||
guiTop + 122,
|
||||
0);
|
||||
key.drawTextBox();
|
||||
fontRendererObj.drawString(
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.value"), guiLeft + 12, guiTop + 142, 0);
|
||||
I18n.format("item.structurelib.constructableTrigger.gui.value"),
|
||||
guiLeft + 12,
|
||||
guiTop + 142,
|
||||
0);
|
||||
value.drawTextBox();
|
||||
}
|
||||
|
||||
private class GuiChannelsList extends GuiScrollableList<Entry<String, Integer>> {
|
||||
|
||||
private List<Entry<String, Integer>> cache;
|
||||
|
||||
public GuiChannelsList(int width, int height, int originX, int originY, int slotHeight) {
|
||||
@@ -316,11 +334,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
|
||||
@Override
|
||||
public Entry<String, Integer> getElementAt(int index) {
|
||||
return ChannelDataAccessor.iterateChannelData(trigger)
|
||||
.sorted()
|
||||
.skip(index)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return ChannelDataAccessor.iterateChannelData(trigger).sorted().skip(index).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,8 +344,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
|
||||
@Override
|
||||
protected boolean elementClicked(int elementIndex, boolean doubleClick, int mXRelative, int mYRelative) {
|
||||
if (mXRelative >= margin + 1
|
||||
&& mXRelative <= margin + 5
|
||||
if (mXRelative >= margin + 1 && mXRelative <= margin + 5
|
||||
&& mYRelative >= margin / 2 + 1
|
||||
&& mYRelative <= margin / 2 + 5) {
|
||||
Entry<String, Integer> e = getElementAt(elementIndex);
|
||||
@@ -349,8 +362,8 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawElement(
|
||||
int elementIndex, int x, int y, int height, Tessellator tessellator, boolean isHovering) {
|
||||
protected void drawElement(int elementIndex, int x, int y, int height, Tessellator tessellator,
|
||||
boolean isHovering) {
|
||||
if (elementIndex < 0 || elementIndex >= cache.size()) {
|
||||
return;
|
||||
}
|
||||
@@ -382,8 +395,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
// TODO optimize this to not create a billion string, or maybe cache this
|
||||
String s = fontRendererObj.trimStringToWidth(e, keyMaxWidth);
|
||||
if (s.length() != e.length()) {
|
||||
StringBuilder buffer =
|
||||
new StringBuilder(s).deleteCharAt(s.length() - 1).append("...");
|
||||
StringBuilder buffer = new StringBuilder(s).deleteCharAt(s.length() - 1).append("...");
|
||||
while ((s = fontRendererObj.trimStringToWidth(buffer.toString(), keyMaxWidth)).length()
|
||||
!= buffer.length())
|
||||
// drop last original char
|
||||
@@ -391,9 +403,7 @@ public class GuiScreenConfigureChannels extends GuiScreen implements IGuiScreen
|
||||
do {
|
||||
buffer.append('.');
|
||||
} while (fontRendererObj.getStringWidth(buffer.toString()) <= keyMaxWidth);
|
||||
s = buffer.deleteCharAt(s.length() - 1)
|
||||
.insert(s.length() - 3, EnumChatFormatting.GRAY)
|
||||
.toString();
|
||||
s = buffer.deleteCharAt(s.length() - 1).insert(s.length() - 3, EnumChatFormatting.GRAY).toString();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -2,31 +2,34 @@ package com.gtnewhorizon.structurelib.gui;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
/**
|
||||
* Shamelessly stolen from EnderCore, with some amount of edit to fit in one file. Original code from CrazyPants.
|
||||
* <p>
|
||||
* As the code has been released into public domain, it is now LGPL as part of this library as a whole.
|
||||
* You can go to EnderCore's repository to obtain a public domain copy though
|
||||
* As the code has been released into public domain, it is now LGPL as part of this library as a whole. You can go to
|
||||
* EnderCore's repository to obtain a public domain copy though
|
||||
*
|
||||
* Major edits
|
||||
* <ul>
|
||||
* <li>Separate dwheel handling to handleDWheel. The next event calls often cause the mouse click event to
|
||||
* not fire on other widgets</li>
|
||||
* <li>scrollbar are now rendered within width</li>
|
||||
* <li>added prepareDrawElements</li>
|
||||
* <li>Separate dwheel handling to handleDWheel. The next event calls often cause the mouse click event to not fire on
|
||||
* other widgets</li>
|
||||
* <li>scrollbar are now rendered within width</li>
|
||||
* <li>added prepareDrawElements</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author CrazyPants
|
||||
* @author glee8e
|
||||
*/
|
||||
public abstract class GuiScrollableList<T> {
|
||||
|
||||
protected final int slotHeight;
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
protected final int originX;
|
||||
@@ -113,8 +116,8 @@ public abstract class GuiScrollableList<T> {
|
||||
|
||||
public abstract int getNumElements();
|
||||
|
||||
protected abstract void drawElement(
|
||||
int elementIndex, int x, int y, int height, Tessellator tessellator, boolean isHovering);
|
||||
protected abstract void drawElement(int elementIndex, int x, int y, int height, Tessellator tessellator,
|
||||
boolean isHovering);
|
||||
|
||||
protected boolean elementClicked(int elementIndex, boolean doubleClick, int mXRelative, int mYRelative) {
|
||||
return true;
|
||||
@@ -165,8 +168,7 @@ public abstract class GuiScrollableList<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the slot to the screen, pass in mouse's current x and y and partial
|
||||
* ticks
|
||||
* draws the slot to the screen, pass in mouse's current x and y and partial ticks
|
||||
*/
|
||||
public void drawScreen(int mX, int mY, float partialTick) {
|
||||
this.mouseX = mX;
|
||||
@@ -343,15 +345,17 @@ public abstract class GuiScrollableList<T> {
|
||||
int y = mouseY - minY + (int) amountScrolled - margin;
|
||||
int mouseOverElement = y / slotHeight;
|
||||
|
||||
if (mouseX >= minX
|
||||
&& mouseX <= maxX
|
||||
if (mouseX >= minX && mouseX <= maxX
|
||||
&& mouseOverElement >= 0
|
||||
&& y >= 0
|
||||
&& mouseOverElement < getNumElements()) {
|
||||
boolean doubleClick =
|
||||
mouseOverElement == selectedIndex && Minecraft.getSystemTime() - lastClickedTime < 250L;
|
||||
boolean doubleClick = mouseOverElement == selectedIndex
|
||||
&& Minecraft.getSystemTime() - lastClickedTime < 250L;
|
||||
if (elementClicked(
|
||||
mouseOverElement, doubleClick, mouseX - minX, y - slotHeight * mouseOverElement)) {
|
||||
mouseOverElement,
|
||||
doubleClick,
|
||||
mouseX - minX,
|
||||
y - slotHeight * mouseOverElement)) {
|
||||
setSelection(mouseOverElement);
|
||||
lastClickedTime = Minecraft.getSystemTime();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.item;
|
||||
import static net.minecraft.util.StatCollector.translateToLocal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -11,6 +12,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
public class ItemBlockHint extends ItemBlock {
|
||||
|
||||
public ItemBlockHint(Block p_i45328_1_) {
|
||||
super(p_i45328_1_);
|
||||
setMaxDamage(0);
|
||||
@@ -35,29 +37,31 @@ public class ItemBlockHint extends ItemBlock {
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
aList.add(EnumChatFormatting.AQUA.toString()
|
||||
+ EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.1")); // Placeholder for a certain group.
|
||||
aList.add(
|
||||
EnumChatFormatting.AQUA.toString() + EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.1")); // Placeholder for a certain
|
||||
// group.
|
||||
break;
|
||||
case 12:
|
||||
aList.add(EnumChatFormatting.AQUA.toString()
|
||||
+ EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.2")); // General placeholder.
|
||||
aList.add(
|
||||
EnumChatFormatting.AQUA.toString() + EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.2")); // General placeholder.
|
||||
break;
|
||||
case 13:
|
||||
aList.add(EnumChatFormatting.AQUA.toString()
|
||||
+ EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.3")); // Make sure it contains Air material.
|
||||
aList.add(
|
||||
EnumChatFormatting.AQUA.toString() + EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.3")); // Make sure it contains Air
|
||||
// material.
|
||||
break;
|
||||
case 14:
|
||||
aList.add(EnumChatFormatting.AQUA.toString()
|
||||
+ EnumChatFormatting.BOLD
|
||||
+ translateToLocal(
|
||||
"structurelib.blockhint.desc.4")); // Make sure it does not contain Air material.
|
||||
aList.add(
|
||||
EnumChatFormatting.AQUA.toString() + EnumChatFormatting.BOLD
|
||||
+ translateToLocal("structurelib.blockhint.desc.4")); // Make sure it does not contain
|
||||
// Air material.
|
||||
break;
|
||||
case 15:
|
||||
aList.add(EnumChatFormatting.BLUE
|
||||
+ translateToLocal("structurelib.blockhint.desc.5")); // ERROR, what did u expect?
|
||||
aList.add(EnumChatFormatting.BLUE + translateToLocal("structurelib.blockhint.desc.5")); // ERROR, what
|
||||
// did u expect?
|
||||
break;
|
||||
default: // WTF?
|
||||
aList.add("Damn son where did you get that!?");
|
||||
|
||||
@@ -5,17 +5,21 @@ import static net.minecraft.util.EnumChatFormatting.BLUE;
|
||||
import static net.minecraft.util.StatCollector.translateToLocal;
|
||||
import static net.minecraft.util.StatCollector.translateToLocalFormatted;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility;
|
||||
|
||||
public class ItemConstructableTrigger extends Item {
|
||||
|
||||
public ItemConstructableTrigger() {
|
||||
setUnlocalizedName("structurelib.constructableTrigger");
|
||||
setTextureName(MOD_ID + ":itemConstructableTrigger");
|
||||
@@ -30,17 +34,8 @@ public class ItemConstructableTrigger extends Item {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUseFirst(
|
||||
ItemStack stack,
|
||||
EntityPlayer player,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
int side,
|
||||
float hitX,
|
||||
float hitY,
|
||||
float hitZ) {
|
||||
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side,
|
||||
float hitX, float hitY, float hitZ) {
|
||||
return ConstructableUtility.handle(stack, player, world, x, y, z, side);
|
||||
}
|
||||
|
||||
@@ -48,27 +43,25 @@ public class ItemConstructableTrigger extends Item {
|
||||
@Override
|
||||
public void addInformation(ItemStack aStack, EntityPlayer ep, List aList, boolean boo) {
|
||||
if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
|
||||
aList.add(translateToLocalFormatted(
|
||||
"item.structurelib.constructableTrigger.desc.lshift.0",
|
||||
ChannelDataAccessor.countChannelData(aStack)));
|
||||
ChannelDataAccessor.iterateChannelData(aStack)
|
||||
.map(e -> e.getKey() + ": " + e.getValue())
|
||||
aList.add(
|
||||
translateToLocalFormatted(
|
||||
"item.structurelib.constructableTrigger.desc.lshift.0",
|
||||
ChannelDataAccessor.countChannelData(aStack)));
|
||||
ChannelDataAccessor.iterateChannelData(aStack).map(e -> e.getKey() + ": " + e.getValue())
|
||||
.forEach(aList::add);
|
||||
} else {
|
||||
aList.add(translateToLocal(
|
||||
"item.structurelib.constructableTrigger.desc.0")); // Triggers Constructable Interface
|
||||
aList.add(BLUE
|
||||
+ translateToLocal(
|
||||
"item.structurelib.constructableTrigger.desc.1")); // Shows multiblock construction details,
|
||||
aList.add(BLUE
|
||||
+ translateToLocal(
|
||||
"item.structurelib.constructableTrigger.desc.2")); // just Use on a multiblock controller.
|
||||
aList.add(BLUE
|
||||
+ translateToLocal(
|
||||
"item.structurelib.constructableTrigger.desc.3")); // (Sneak Use in creative to build)
|
||||
aList.add(BLUE
|
||||
+ translateToLocal(
|
||||
"item.structurelib.constructableTrigger.desc.4")); // Quantity affects tier/mode/type
|
||||
aList.add(translateToLocal("item.structurelib.constructableTrigger.desc.0")); // Triggers Constructable
|
||||
// Interface
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.1")); // Shows multiblock
|
||||
// construction
|
||||
// details,
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.2")); // just Use on a
|
||||
// multiblock
|
||||
// controller.
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.3")); // (Sneak Use in
|
||||
// creative to build)
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.4")); // Quantity affects
|
||||
// tier/mode/type
|
||||
if (ChannelDataAccessor.hasSubChannel(aStack))
|
||||
aList.add(translateToLocal("item.structurelib.constructableTrigger.desc.5"));
|
||||
}
|
||||
|
||||
@@ -3,18 +3,22 @@ package com.gtnewhorizon.structurelib.item;
|
||||
import static com.gtnewhorizon.structurelib.StructureLibAPI.MOD_ID;
|
||||
import static net.minecraft.util.StatCollector.translateToLocal;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.AlignmentUtility;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.AlignmentUtility;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ItemFrontRotationTool extends Item {
|
||||
|
||||
public ItemFrontRotationTool() {
|
||||
setMaxStackSize(1);
|
||||
setUnlocalizedName("structurelib.frontRotationTool");
|
||||
@@ -23,17 +27,8 @@ public class ItemFrontRotationTool extends Item {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUseFirst(
|
||||
ItemStack stack,
|
||||
EntityPlayer player,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
int side,
|
||||
float hitX,
|
||||
float hitY,
|
||||
float hitZ) {
|
||||
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side,
|
||||
float hitX, float hitY, float hitZ) {
|
||||
return AlignmentUtility.handle(player, world, x, y, z);
|
||||
}
|
||||
|
||||
@@ -41,9 +36,13 @@ public class ItemFrontRotationTool extends Item {
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void addInformation(ItemStack p_77624_1_, EntityPlayer p_77624_2_, List aList, boolean p_77624_4_) {
|
||||
aList.add(translateToLocal("item.structurelib.frontRotationTool.desc.0")); // Triggers Front Rotation Interface
|
||||
aList.add(EnumChatFormatting.BLUE
|
||||
+ translateToLocal("item.structurelib.frontRotationTool.desc.1")); // Rotates only the front panel,
|
||||
aList.add(EnumChatFormatting.BLUE
|
||||
+ translateToLocal("item.structurelib.frontRotationTool.desc.2")); // which allows structure rotation.
|
||||
aList.add(EnumChatFormatting.BLUE + translateToLocal("item.structurelib.frontRotationTool.desc.1")); // Rotates
|
||||
// only the
|
||||
// front
|
||||
// panel,
|
||||
aList.add(EnumChatFormatting.BLUE + translateToLocal("item.structurelib.frontRotationTool.desc.2")); // which
|
||||
// allows
|
||||
// structure
|
||||
// rotation.
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
package com.gtnewhorizon.structurelib.net;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import cpw.mods.fml.common.network.ByteBufUtils;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
|
||||
import cpw.mods.fml.common.network.ByteBufUtils;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public abstract class AlignmentMessage implements IMessage {
|
||||
|
||||
int mPosX;
|
||||
int mPosY;
|
||||
int mPosZ;
|
||||
@@ -66,6 +69,7 @@ public abstract class AlignmentMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class AlignmentQuery extends AlignmentMessage {
|
||||
|
||||
public AlignmentQuery() {}
|
||||
|
||||
public AlignmentQuery(IAlignmentProvider provider) {
|
||||
@@ -78,6 +82,7 @@ public abstract class AlignmentMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class AlignmentData extends AlignmentMessage {
|
||||
|
||||
public AlignmentData() {}
|
||||
|
||||
private AlignmentData(AlignmentQuery query) {
|
||||
@@ -98,11 +103,11 @@ public abstract class AlignmentMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class ClientHandler implements IMessageHandler<AlignmentData, IMessage> {
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(AlignmentData pMessage, MessageContext pCtx) {
|
||||
if (StructureLib.getCurrentPlayer().worldObj.provider.dimensionId == pMessage.mPosD) {
|
||||
TileEntity te = StructureLib.getCurrentPlayer()
|
||||
.worldObj
|
||||
TileEntity te = StructureLib.getCurrentPlayer().worldObj
|
||||
.getTileEntity(pMessage.mPosX, pMessage.mPosY, pMessage.mPosZ);
|
||||
if (te instanceof IAlignmentProvider) {
|
||||
IAlignment alignment = ((IAlignmentProvider) te).getAlignment();
|
||||
@@ -116,6 +121,7 @@ public abstract class AlignmentMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class ServerHandler implements IMessageHandler<AlignmentQuery, AlignmentData> {
|
||||
|
||||
@Override
|
||||
public AlignmentData onMessage(AlignmentQuery pMessage, MessageContext pCtx) {
|
||||
World world = DimensionManager.getWorld(pMessage.mPosD);
|
||||
|
||||
@@ -4,12 +4,14 @@ import static com.gtnewhorizon.structurelib.StructureLib.LOGGER;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class ErrorHintParticleMessage implements IMessage {
|
||||
|
||||
private int x;
|
||||
private short y;
|
||||
private int z;
|
||||
@@ -37,17 +39,21 @@ public class ErrorHintParticleMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<ErrorHintParticleMessage, IMessage> {
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(ErrorHintParticleMessage msg, MessageContext ctx) {
|
||||
boolean updateResult = StructureLibAPI.markHintParticleError(
|
||||
StructureLib.getCurrentPlayer(), StructureLib.getCurrentPlayer().worldObj, msg.x, msg.y, msg.z);
|
||||
if (StructureLibAPI.isDebugEnabled())
|
||||
LOGGER.debug(
|
||||
"Server instructed to mark hint particle at ({}, {}, {}) error, result {}!",
|
||||
msg.x,
|
||||
msg.y,
|
||||
msg.z,
|
||||
updateResult);
|
||||
StructureLib.getCurrentPlayer(),
|
||||
StructureLib.getCurrentPlayer().worldObj,
|
||||
msg.x,
|
||||
msg.y,
|
||||
msg.z);
|
||||
if (StructureLibAPI.isDebugEnabled()) LOGGER.debug(
|
||||
"Server instructed to mark hint particle at ({}, {}, {}) error, result {}!",
|
||||
msg.x,
|
||||
msg.y,
|
||||
msg.z,
|
||||
updateResult);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
package com.gtnewhorizon.structurelib.net;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
|
||||
import cpw.mods.fml.common.network.ByteBufUtils;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
public class SetChannelDataMessage implements IMessage {
|
||||
|
||||
private final List<Map.Entry<String, Integer>> data = new ArrayList<>();
|
||||
|
||||
public SetChannelDataMessage() {}
|
||||
@@ -44,6 +49,7 @@ public class SetChannelDataMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<SetChannelDataMessage, IMessage> {
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(SetChannelDataMessage message, MessageContext ctx) {
|
||||
EntityPlayerMP player = ctx.getServerHandler().playerEntity;
|
||||
|
||||
@@ -4,12 +4,14 @@ import static com.gtnewhorizon.structurelib.StructureLib.LOGGER;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class UpdateHintParticleMessage implements IMessage {
|
||||
|
||||
private int x;
|
||||
private short y;
|
||||
private int z;
|
||||
@@ -53,6 +55,7 @@ public class UpdateHintParticleMessage implements IMessage {
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<UpdateHintParticleMessage, IMessage> {
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(UpdateHintParticleMessage msg, MessageContext ctx) {
|
||||
boolean updateResult = StructureLibAPI.updateHintParticleTint(
|
||||
@@ -61,16 +64,13 @@ public class UpdateHintParticleMessage implements IMessage {
|
||||
msg.x,
|
||||
msg.y,
|
||||
msg.z,
|
||||
new short[] {
|
||||
msg.r, msg.g, msg.b, msg.a,
|
||||
});
|
||||
if (StructureLibAPI.isDebugEnabled())
|
||||
LOGGER.debug(
|
||||
"Server instructed to update hint particle at ({}, {}, {}), result {}!",
|
||||
msg.x,
|
||||
msg.y,
|
||||
msg.z,
|
||||
updateResult);
|
||||
new short[] { msg.r, msg.g, msg.b, msg.a, });
|
||||
if (StructureLibAPI.isDebugEnabled()) LOGGER.debug(
|
||||
"Server instructed to update hint particle at ({}, {}, {}), result {}!",
|
||||
msg.x,
|
||||
msg.y,
|
||||
msg.z,
|
||||
updateResult);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
|
||||
/**
|
||||
* Represent the environment in which autoplace of a single element took place.
|
||||
*/
|
||||
public class AutoPlaceEnvironment {
|
||||
|
||||
private IItemSource source;
|
||||
private final EntityPlayer actor;
|
||||
private final Consumer<IChatComponent> chatter;
|
||||
@@ -23,8 +27,8 @@ public class AutoPlaceEnvironment {
|
||||
final int[] offsetABC;
|
||||
private final int[] baseOffsetABC;
|
||||
|
||||
public static AutoPlaceEnvironment fromLegacy(
|
||||
IItemSource source, EntityPlayer actor, Consumer<IChatComponent> chatter) {
|
||||
public static AutoPlaceEnvironment fromLegacy(IItemSource source, EntityPlayer actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
if (source instanceof WrappedIItemSource) {
|
||||
AutoPlaceEnvironment original = ((WrappedIItemSource) source).container;
|
||||
// feels like this is extremely likely to cause issues, but this does allow us to recover lost info.
|
||||
@@ -40,13 +44,8 @@ public class AutoPlaceEnvironment {
|
||||
return new AutoPlaceEnvironment(source, actor, chatter, null, null, null, null, null);
|
||||
}
|
||||
|
||||
AutoPlaceEnvironment(
|
||||
EntityPlayer actor,
|
||||
Consumer<IChatComponent> chatter,
|
||||
IStructureDefinition<?> definition,
|
||||
String piece,
|
||||
ExtendedFacing facing,
|
||||
int[] baseOffsetABC) {
|
||||
AutoPlaceEnvironment(EntityPlayer actor, Consumer<IChatComponent> chatter, IStructureDefinition<?> definition,
|
||||
String piece, ExtendedFacing facing, int[] baseOffsetABC) {
|
||||
this.source = null;
|
||||
this.actor = actor;
|
||||
this.chatter = chatter;
|
||||
@@ -57,14 +56,8 @@ public class AutoPlaceEnvironment {
|
||||
this.baseOffsetABC = baseOffsetABC;
|
||||
}
|
||||
|
||||
AutoPlaceEnvironment(
|
||||
IItemSource source,
|
||||
EntityPlayer actor,
|
||||
Consumer<IChatComponent> chatter,
|
||||
IStructureDefinition<?> definition,
|
||||
String piece,
|
||||
ExtendedFacing facing,
|
||||
int[] offsetABC,
|
||||
AutoPlaceEnvironment(IItemSource source, EntityPlayer actor, Consumer<IChatComponent> chatter,
|
||||
IStructureDefinition<?> definition, String piece, ExtendedFacing facing, int[] offsetABC,
|
||||
int[] baseOffsetABC) {
|
||||
this.source = definition != null && !(source instanceof WrappedIItemSource)
|
||||
? new WrappedIItemSource(this, source)
|
||||
@@ -97,8 +90,7 @@ public class AutoPlaceEnvironment {
|
||||
}
|
||||
|
||||
public APILevel getAPILevel() {
|
||||
return definition == null
|
||||
? actor instanceof EntityPlayerMP ? APILevel.Legacy : APILevel.LegacyRelaxed
|
||||
return definition == null ? actor instanceof EntityPlayerMP ? APILevel.Legacy : APILevel.LegacyRelaxed
|
||||
: APILevel.V2;
|
||||
}
|
||||
|
||||
@@ -110,8 +102,8 @@ public class AutoPlaceEnvironment {
|
||||
}
|
||||
|
||||
/**
|
||||
* The initiator of actions. for very critical errors you can also just send the error messages here, bypassing
|
||||
* any filter that {@link #getChatter()} might have. You might want to use
|
||||
* The initiator of actions. for very critical errors you can also just send the error messages here, bypassing any
|
||||
* filter that {@link #getChatter()} might have. You might want to use
|
||||
* {@link com.gtnewhorizon.structurelib.StructureLibAPI#addThrottledChat(Object, EntityPlayer, IChatComponent, short)}
|
||||
* to help reduce spam.
|
||||
*/
|
||||
@@ -179,6 +171,7 @@ public class AutoPlaceEnvironment {
|
||||
}
|
||||
|
||||
private static class WrappedIItemSource implements IItemSource {
|
||||
|
||||
final AutoPlaceEnvironment container;
|
||||
final IItemSource delegate;
|
||||
|
||||
@@ -221,13 +214,13 @@ public class AutoPlaceEnvironment {
|
||||
*/
|
||||
public enum APILevel {
|
||||
/**
|
||||
* Implements {@link #getChatter()}, {@link #getActor()} and {@link #getSource()}.
|
||||
* {@link #getActor()} is guaranteed to be an {@link net.minecraft.entity.player.EntityPlayerMP}
|
||||
* Implements {@link #getChatter()}, {@link #getActor()} and {@link #getSource()}. {@link #getActor()} is
|
||||
* guaranteed to be an {@link net.minecraft.entity.player.EntityPlayerMP}
|
||||
*/
|
||||
Legacy,
|
||||
/**
|
||||
* Implements {@link #getChatter()}, {@link #getActor()} and {@link #getSource()}.
|
||||
* {@link #getActor()} is <b>NOT</b> guaranteed to be an {@link net.minecraft.entity.player.EntityPlayerMP}
|
||||
* Implements {@link #getChatter()}, {@link #getActor()} and {@link #getSource()}. {@link #getActor()} is
|
||||
* <b>NOT</b> guaranteed to be an {@link net.minecraft.entity.player.EntityPlayerMP}
|
||||
*/
|
||||
LegacyRelaxed,
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
class ChatThrottleKey {
|
||||
|
||||
static class NoExplicitChannel {
|
||||
|
||||
private static final int hashOffset = NoExplicitChannel.class.hashCode();
|
||||
private final String subchannel;
|
||||
|
||||
|
||||
+1
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
|
||||
class DefaultSurvivalBuildEnvironment implements ISurvivalBuildEnvironment {
|
||||
|
||||
private final IItemSource source;
|
||||
private final EntityPlayer actor;
|
||||
|
||||
|
||||
@@ -3,5 +3,6 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IBlockPosConsumer {
|
||||
|
||||
void consume(World world, int x, int y, int z);
|
||||
}
|
||||
@@ -4,9 +4,10 @@ import net.minecraft.block.Block;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface ICustomBlockSetting {
|
||||
|
||||
/**
|
||||
* Default block setting calls {@link World#setBlock(int x, int y, int z, Block block, int meta, int updateType)} like:
|
||||
* {@code world.setBlock(x,y,z,this/block,meta,2)} where updateType 2 means to update lighting and stuff
|
||||
* Default block setting calls {@link World#setBlock(int x, int y, int z, Block block, int meta, int updateType)}
|
||||
* like: {@code world.setBlock(x,y,z,this/block,meta,2)} where updateType 2 means to update lighting and stuff
|
||||
*
|
||||
* @param world world that should be affected
|
||||
* @param x x position to set
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import com.gtnewhorizon.structurelib.util.InventoryIterable;
|
||||
import com.gtnewhorizon.structurelib.util.InventoryUtility;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nonnull;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Represent an item source. Take only, cannot be placed back.
|
||||
*/
|
||||
public interface IItemSource {
|
||||
|
||||
/**
|
||||
* Retrieve some amount of items from this item source matching given filter.
|
||||
* <p>
|
||||
* We probably don't need to get a lot of items from this method,
|
||||
* so I don't care about the overhead of storing all fetched items even if downstream code doesn't need it
|
||||
* We probably don't need to get a lot of items from this method, so I don't care about the overhead of storing all
|
||||
* fetched items even if downstream code doesn't need it
|
||||
*
|
||||
* @param predicate filtering predicate. should return true for ItemStacks that should be added to result collection
|
||||
* @param simulate whether to actually commit the modification. true for dry run, false otherwise.
|
||||
@@ -64,11 +68,11 @@ public interface IItemSource {
|
||||
/**
|
||||
* Take exactly one item. ItemStack given must have a stack size of 1.
|
||||
* <p>
|
||||
* This is meant to be an optimized version of {@link #takeOne(Predicate, boolean)}.
|
||||
* Implementations that support item storage indexed by ItemStack can use this to speed up calculation.
|
||||
* This is meant to be an optimized version of {@link #takeOne(Predicate, boolean)}. Implementations that support
|
||||
* item storage indexed by ItemStack can use this to speed up calculation.
|
||||
*
|
||||
* @param stack what item to extract. The NBT tag of this ItemStack is siginifcant and will be
|
||||
* considered during matching. must have a stack size of 1.
|
||||
* @param stack what item to extract. The NBT tag of this ItemStack is siginifcant and will be considered during
|
||||
* matching. must have a stack size of 1.
|
||||
* @param simulate whether to actually commit the modification. true for dry run, false otherwise.
|
||||
* @return true if found. false otherwise
|
||||
* @throws IllegalArgumentException if given stack is invalid, or has a stack size other than 1.
|
||||
@@ -82,8 +86,8 @@ public interface IItemSource {
|
||||
/**
|
||||
* Take some item. Will not take item if it cannot find enough items to take.
|
||||
* <p>
|
||||
* This is meant to be an optimized version of {@link #takeOne(Predicate, boolean)}.
|
||||
* Implementations that support indexing off ItemStack can use this to speed up calculation.
|
||||
* This is meant to be an optimized version of {@link #takeOne(Predicate, boolean)}. Implementations that support
|
||||
* indexing off ItemStack can use this to speed up calculation.
|
||||
*
|
||||
* @param stack what item and how many to extract. The NBT tag of this ItemStack is siginifcant and will be
|
||||
* considered during matching
|
||||
@@ -110,6 +114,7 @@ public interface IItemSource {
|
||||
*/
|
||||
static IItemSource fromPlayer(EntityPlayerMP player) {
|
||||
return new IItemSource() {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Map<ItemStack, Integer> take(Predicate<ItemStack> p, boolean s, int c) {
|
||||
|
||||
@@ -3,5 +3,6 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
public interface ISpecialItemBlock {
|
||||
|
||||
int getItemMetaFromBlockMeta(Block block, int blockMeta);
|
||||
}
|
||||
@@ -3,26 +3,28 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
import static com.gtnewhorizon.structurelib.structure.IStructureWalker.ignoreBlockUnloaded;
|
||||
import static com.gtnewhorizon.structurelib.structure.IStructureWalker.skipBlockUnloaded;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
|
||||
/**
|
||||
* This is the structure definition of your multi. You will have one of these for each multi.
|
||||
*
|
||||
* <h2>Cache the instances of this class</h2>
|
||||
* <p>
|
||||
* You will construct this definition once per multi, either at class load or at first call to your variant of {@code getStructureDefinition()}.
|
||||
* You can use a {@link ClassValue ClassValue<IStructureDefinition<?>>} if you have a template for subclass.
|
||||
* You can also use {@link StructureUtility#defer(Function) defer()} or its overloads for simpler cases, but it is
|
||||
* slightly less performant as it will allocate new objects on each structure check, whereas {@link ClassValue} will
|
||||
* allocate once and cache it onwards.
|
||||
* You will construct this definition once per multi, either at class load or at first call to your variant of
|
||||
* {@code getStructureDefinition()}. You can use a {@link ClassValue ClassValue<IStructureDefinition<?>>} if you
|
||||
* have a template for subclass. You can also use {@link StructureUtility#defer(Function) defer()} or its overloads for
|
||||
* simpler cases, but it is slightly less performant as it will allocate new objects on each structure check, whereas
|
||||
* {@link ClassValue} will allocate once and cache it onwards.
|
||||
* <p>
|
||||
* <h2>Constructing</h2>
|
||||
* <p>
|
||||
@@ -30,30 +32,39 @@ import net.minecraft.world.World;
|
||||
* <p>
|
||||
* Builder has two main methods:
|
||||
* <ul>
|
||||
* <li>{@link com.gtnewhorizon.structurelib.structure.StructureDefinition.Builder#addShape(String, String[][]) addShape()}
|
||||
* is a 2d string array describing the layout of structure. You can optionally use `StructureUtility#transpose()`
|
||||
* to transpose the array to make the structure look nicer in source code.
|
||||
* <li>{@link com.gtnewhorizon.structurelib.structure.StructureDefinition.Builder#addElement(Character, IStructureElement) addElement()}. It takes a char identifier (mapped to a char in any of {@link com.gtnewhorizon.structurelib.structure.StructureDefinition.Builder#addShape(String, String[][]) addShape()} calls) and a {@link IStructureElement}.
|
||||
* <li>{@link com.gtnewhorizon.structurelib.structure.StructureDefinition.Builder#addShape(String, String[][])
|
||||
* addShape()} is a 2d string array describing the layout of structure. You can optionally use
|
||||
* `StructureUtility#transpose()` to transpose the array to make the structure look nicer in source code.
|
||||
* <li>{@link com.gtnewhorizon.structurelib.structure.StructureDefinition.Builder#addElement(Character, IStructureElement)
|
||||
* addElement()}. It takes a char identifier (mapped to a char in any of
|
||||
* {@link com.gtnewhorizon.structurelib.structure.StructureDefinition.Builder#addShape(String, String[][]) addShape()}
|
||||
* calls) and a {@link IStructureElement}.
|
||||
* </ul>
|
||||
* <h2>Position A, B and C</h2>
|
||||
*
|
||||
* Imagine you stand in front of the controller, with controller facing towards you not rotated or flipped.
|
||||
* <ul>
|
||||
* <li>The "A" position would be the number of blocks on the left side of the controller, not counting controller itself.</li>
|
||||
* <li>The "B" position would be the number of blocks on the top side of the controller, not counting controller itself.</li>
|
||||
* <li>The "A" position would be the number of blocks on the left side of the controller, not counting controller
|
||||
* itself.</li>
|
||||
* <li>The "B" position would be the number of blocks on the top side of the controller, not counting controller
|
||||
* itself.</li>
|
||||
* <li>The "C" position would be the number of blocks between you and controller, not counting controller itself.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <T> Type of the context object. Usually this will be the multiblock controller.
|
||||
*/
|
||||
public interface IStructureDefinition<T> {
|
||||
|
||||
/**
|
||||
* Used internally
|
||||
* <p>
|
||||
* Might, but is not required, to throw {@link java.util.NoSuchElementException} if the given structure piece is not found.
|
||||
* Might, but is not required, to throw {@link java.util.NoSuchElementException} if the given structure piece is not
|
||||
* found.
|
||||
*
|
||||
* @param name same name as for other methods here
|
||||
* @return the array of elements to process
|
||||
* @throws java.util.NoSuchElementException if the given structure piece is not found and the moon phase perfectly matches
|
||||
* @throws java.util.NoSuchElementException if the given structure piece is not found and the moon phase perfectly
|
||||
* matches
|
||||
*/
|
||||
IStructureElement<T>[] getStructureFor(String name);
|
||||
|
||||
@@ -61,30 +72,22 @@ public interface IStructureDefinition<T> {
|
||||
|
||||
/**
|
||||
* Run a structure check.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param forceCheckAllBlocks check all location even if chunk not currently loaded.
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
default boolean check(
|
||||
T object,
|
||||
String piece,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
int basePositionC,
|
||||
default boolean check(T object, String piece, World world, ExtendedFacing extendedFacing, int basePositionX,
|
||||
int basePositionY, int basePositionZ, int basePositionA, int basePositionB, int basePositionC,
|
||||
boolean forceCheckAllBlocks) {
|
||||
return iterate(
|
||||
object,
|
||||
@@ -104,29 +107,21 @@ public interface IStructureDefinition<T> {
|
||||
|
||||
/**
|
||||
* Spawn hint particles. Should not be called on server side.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
default boolean hints(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
String piece,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
default boolean hints(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
|
||||
int basePositionX, int basePositionY, int basePositionZ, int basePositionA, int basePositionB,
|
||||
int basePositionC) {
|
||||
return iterate(
|
||||
object,
|
||||
@@ -148,30 +143,21 @@ public interface IStructureDefinition<T> {
|
||||
* Build the multi in creative mode on a best-effort basis. Does not guarantee the structure is correct after a
|
||||
* successful call.
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @return true if sucessful, false otherwise
|
||||
*/
|
||||
default boolean build(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
String piece,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
default boolean build(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
|
||||
int basePositionX, int basePositionY, int basePositionZ, int basePositionA, int basePositionB,
|
||||
int basePositionC) {
|
||||
return iterate(
|
||||
object,
|
||||
@@ -190,38 +176,29 @@ public interface IStructureDefinition<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #build(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)} if {@code hintsOnly},
|
||||
* call {@link #hints(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)} otherwise.
|
||||
* Call {@link #build(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)} if
|
||||
* {@code hintsOnly}, call
|
||||
* {@link #hints(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)} otherwise.
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param hintsOnly whether to spawn hints or do creative build.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param hintsOnly whether to spawn hints or do creative build.
|
||||
* @return true if sucessful, false otherwise
|
||||
* @see #hints(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)
|
||||
* @see #build(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)
|
||||
*/
|
||||
default boolean buildOrHints(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
String piece,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
int basePositionC,
|
||||
boolean hintsOnly) {
|
||||
default boolean buildOrHints(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
|
||||
int basePositionX, int basePositionY, int basePositionZ, int basePositionA, int basePositionB,
|
||||
int basePositionC, boolean hintsOnly) {
|
||||
return iterate(
|
||||
object,
|
||||
trigger,
|
||||
@@ -241,44 +218,31 @@ public interface IStructureDefinition<T> {
|
||||
/**
|
||||
* Cause a survival build.
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param elementBudget build up to this many elements
|
||||
* @param source from where to drain resource
|
||||
* @param actor source of action
|
||||
* @param check whether {@link IStructureElement#check(Object, World, int, int, int)} should be called if anything
|
||||
* would be placed. use with caution.
|
||||
* if in doubt, call {@link #check(Object, String, World, ExtendedFacing, int, int, int, int, int, int, boolean)}
|
||||
* after this call and set this parameter to false
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param elementBudget build up to this many elements
|
||||
* @param source from where to drain resource
|
||||
* @param actor source of action
|
||||
* @param check whether {@link IStructureElement#check(Object, World, int, int, int)} should be called if
|
||||
* anything would be placed. use with caution. if in doubt, call
|
||||
* {@link #check(Object, String, World, ExtendedFacing, int, int, int, int, int, int, boolean)}
|
||||
* after this call and set this parameter to false
|
||||
* @return number of elements built, or -1 if structure done
|
||||
* @see #build(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)
|
||||
*/
|
||||
@Deprecated
|
||||
default int survivalBuild(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
String piece,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
int basePositionC,
|
||||
int elementBudget,
|
||||
IItemSource source,
|
||||
EntityPlayerMP actor,
|
||||
boolean check) {
|
||||
default int survivalBuild(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
|
||||
int basePositionX, int basePositionY, int basePositionZ, int basePositionA, int basePositionB,
|
||||
int basePositionC, int elementBudget, IItemSource source, EntityPlayerMP actor, boolean check) {
|
||||
EntityPlayer realActor;
|
||||
if (actor == null) {
|
||||
realActor = ISurvivalConstructable.__get_player();
|
||||
@@ -306,41 +270,29 @@ public interface IStructureDefinition<T> {
|
||||
/**
|
||||
* Cause a survival build.
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param piece the structure piece's string identifier.
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param elementBudget build up to this many elements
|
||||
* @param env build environment.
|
||||
* @param check whether {@link IStructureElement#check(Object, World, int, int, int)} should be called if anything
|
||||
* would be placed. use with caution.
|
||||
* if in doubt, call {@link IStructureDefinition#check(Object, String, World, ExtendedFacing, int, int, int, int, int, int, boolean)}
|
||||
* after this call and set this parameter to false
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param elementBudget build up to this many elements
|
||||
* @param env build environment.
|
||||
* @param check whether {@link IStructureElement#check(Object, World, int, int, int)} should be called if
|
||||
* anything would be placed. use with caution. if in doubt, call
|
||||
* {@link IStructureDefinition#check(Object, String, World, ExtendedFacing, int, int, int, int, int, int, boolean)}
|
||||
* after this call and set this parameter to false
|
||||
* @return number of elements built, or -1 if structure done
|
||||
* @see #build(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int)
|
||||
*/
|
||||
default int survivalBuild(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
String piece,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
int basePositionC,
|
||||
int elementBudget,
|
||||
ISurvivalBuildEnvironment env,
|
||||
boolean check) {
|
||||
default int survivalBuild(T object, ItemStack trigger, String piece, World world, ExtendedFacing extendedFacing,
|
||||
int basePositionX, int basePositionY, int basePositionZ, int basePositionA, int basePositionB,
|
||||
int basePositionC, int elementBudget, ISurvivalBuildEnvironment env, boolean check) {
|
||||
SurvivalBuildStructureWalker<T> walker = new SurvivalBuildStructureWalker<>(
|
||||
object,
|
||||
trigger,
|
||||
@@ -349,7 +301,7 @@ public interface IStructureDefinition<T> {
|
||||
this,
|
||||
piece,
|
||||
extendedFacing,
|
||||
new int[] {basePositionA, basePositionB, basePositionC},
|
||||
new int[] { basePositionA, basePositionB, basePositionC },
|
||||
check);
|
||||
StructureUtility.iterateV2(
|
||||
getStructureFor(piece),
|
||||
@@ -368,37 +320,28 @@ public interface IStructureDefinition<T> {
|
||||
|
||||
/**
|
||||
* Low level utility.
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param elements the structure piece
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param hintsOnly whether to spawn hints or do creative build. no effect if {@code checkBlocksIfNotNullForceCheckAllIfTrue} is not null.
|
||||
* @param checkBlocksIfNotNullForceCheckAllIfTrue creative build or spawn hints if null. Force check not loaded chunk
|
||||
* if true. Check only loaded chunk is false.
|
||||
*
|
||||
* @param object context object. usually multiblock controller.
|
||||
* @param trigger The trigger item that contains channel data.
|
||||
* @param elements the structure piece
|
||||
* @param world the world object this check takes place in.
|
||||
* @param extendedFacing the current structure's orientation.
|
||||
* @param basePositionX X location of the structure
|
||||
* @param basePositionY Y location of the structure
|
||||
* @param basePositionZ Z location of the structure
|
||||
* @param basePositionA see class javadoc
|
||||
* @param basePositionB see class javadoc
|
||||
* @param basePositionC see class javadoc
|
||||
* @param hintsOnly whether to spawn hints or do creative build. no effect if
|
||||
* {@code checkBlocksIfNotNullForceCheckAllIfTrue} is not null.
|
||||
* @param checkBlocksIfNotNullForceCheckAllIfTrue creative build or spawn hints if null. Force check not loaded
|
||||
* chunk if true. Check only loaded chunk is false.
|
||||
* @return true if iteration completed successfully.
|
||||
* @param <T> type of context object.
|
||||
*/
|
||||
static <T> boolean iterate(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
IStructureElement<T>[] elements,
|
||||
World world,
|
||||
ExtendedFacing extendedFacing,
|
||||
int basePositionX,
|
||||
int basePositionY,
|
||||
int basePositionZ,
|
||||
int basePositionA,
|
||||
int basePositionB,
|
||||
int basePositionC,
|
||||
boolean hintsOnly,
|
||||
Boolean checkBlocksIfNotNullForceCheckAllIfTrue) {
|
||||
static <T> boolean iterate(T object, ItemStack trigger, IStructureElement<T>[] elements, World world,
|
||||
ExtendedFacing extendedFacing, int basePositionX, int basePositionY, int basePositionZ, int basePositionA,
|
||||
int basePositionB, int basePositionC, boolean hintsOnly, Boolean checkBlocksIfNotNullForceCheckAllIfTrue) {
|
||||
if (!world.isRemote && hintsOnly) {
|
||||
return false;
|
||||
}
|
||||
@@ -433,8 +376,8 @@ public interface IStructureDefinition<T> {
|
||||
"check force");
|
||||
}
|
||||
if (StructureLibAPI.isDebugEnabled() && success) {
|
||||
StructureLib.LOGGER.info(
|
||||
"Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] pass");
|
||||
StructureLib.LOGGER
|
||||
.info("Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] pass");
|
||||
}
|
||||
return success;
|
||||
} else {
|
||||
@@ -477,6 +420,7 @@ public interface IStructureDefinition<T> {
|
||||
|
||||
/**
|
||||
* Create a new instance of builder.
|
||||
*
|
||||
* @param <T> type of context object
|
||||
*/
|
||||
static <T> StructureDefinition.Builder<T> builder() {
|
||||
|
||||
@@ -3,15 +3,14 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.LOGGER;
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.PANIC_MODE;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@@ -21,11 +20,16 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
|
||||
/**
|
||||
* Use StructureUtility to instantiate. These are the building blocks for your {@link IStructureDefinition}. It represents
|
||||
* what a particular element can be and how this particular element should be autoplaced.
|
||||
* Use StructureUtility to instantiate. These are the building blocks for your {@link IStructureDefinition}. It
|
||||
* represents what a particular element can be and how this particular element should be autoplaced.
|
||||
*/
|
||||
public interface IStructureElement<T> {
|
||||
|
||||
boolean check(T t, World world, int x, int y, int z);
|
||||
|
||||
boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger);
|
||||
@@ -35,35 +39,27 @@ public interface IStructureElement<T> {
|
||||
/**
|
||||
* Try place the block by taking resource from given IItemSource.
|
||||
* <p>
|
||||
* You might want to use {@link StructureUtility#survivalPlaceBlock(Block, int, World, int, int, int, IItemSource, net.minecraft.entity.player.EntityPlayer)}
|
||||
* You might want to use
|
||||
* {@link StructureUtility#survivalPlaceBlock(Block, int, World, int, int, int, IItemSource, net.minecraft.entity.player.EntityPlayer)}
|
||||
* or its overloads to implement this.
|
||||
*
|
||||
* @param trigger trigger item
|
||||
* @param s drain resources from this place
|
||||
* @param actor source of action. for very critical errors you can also just send the error messages here, bypassing
|
||||
* any filter that chatter might have.
|
||||
* @param actor source of action. for very critical errors you can also just send the error messages here,
|
||||
* bypassing any filter that chatter might have.
|
||||
* @param chatter send error messages here. Caller will choose an appropriate way to forward it to player if the
|
||||
* other fallbacks also fails.
|
||||
* @deprecated caller should call the non deprecated overload. implementor for reusable {@link IStructureElement}
|
||||
* should still implement this. implementor for private implementations can freely ignore this as long as you know
|
||||
* the caller will not call this overload.
|
||||
* should still implement this. implementor for private implementations can freely ignore this as long
|
||||
* as you know the caller will not call this overload.
|
||||
*/
|
||||
@Deprecated
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
if (PANIC_MODE) throw new RuntimeException("Panic Tripwire hit");
|
||||
if (StructureLibAPI.isDebugEnabled())
|
||||
LOGGER.error(
|
||||
"Default implementation of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}",
|
||||
getClass().getName());
|
||||
if (StructureLibAPI.isDebugEnabled()) LOGGER.error(
|
||||
"Default implementation of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}",
|
||||
getClass().getName());
|
||||
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT;
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
@@ -73,54 +69,64 @@ public interface IStructureElement<T> {
|
||||
* <p>
|
||||
* <b>BY OVERRIDING THIS TO NULL, YOU ACKNOWLEDGE THAT THE {@link #check(Object, World, int, int, int)} OF THIS
|
||||
* CLASS IS SIDE EFFECT FREE AND CAN HAVE ITS CHECK CALLED WITHOUT BREAKING ANYTHING. OTHERWISE OVERRIDE THE
|
||||
* {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)} TO PROVIDE A SIDEEFFECT
|
||||
* FREE {@link PlaceResult#SKIP}.</b>
|
||||
* {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)} TO PROVIDE A
|
||||
* SIDEEFFECT FREE {@link PlaceResult#SKIP}.</b>
|
||||
* <p>
|
||||
* It should be noticed that this filter is only advisory and the actual {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
* or {@link #check(Object, World, int, int, int)} are free to reject/accept/place blocks not contained in this list,
|
||||
* It should be noticed that this filter is only advisory and the actual
|
||||
* {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)} or
|
||||
* {@link #check(Object, World, int, int, int)} are free to reject/accept/place blocks not contained in this list,
|
||||
* e.g. when the element can be placed anywhere in the structure, but no more than 3 overall; when the structure
|
||||
* element cannot know all blocks it will accept at the time of calling; when this is backed by a legacy
|
||||
* {@link IStructureElement} that just didn't implement this API.
|
||||
*
|
||||
* @param trigger trigger item
|
||||
* @param env autoplacing environment
|
||||
* @return null if not implemented, otherwise an instance describing what kind of blocks will be placed by {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
* @return null if not implemented, otherwise an instance describing what kind of blocks will be placed by
|
||||
* {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
|
||||
*/
|
||||
@Nullable
|
||||
default BlocksToPlace getBlocksToPlace(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default BlocksToPlace getBlocksToPlace(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try place the block by taking resource from given {@link IItemSource}.
|
||||
* <p>
|
||||
* You might want to use {@link StructureUtility#survivalPlaceBlock(Block, int, World, int, int, int, IItemSource, net.minecraft.entity.player.EntityPlayer)}
|
||||
* You might want to use
|
||||
* {@link StructureUtility#survivalPlaceBlock(Block, int, World, int, int, int, IItemSource, net.minecraft.entity.player.EntityPlayer)}
|
||||
* or its overloads to implement this.
|
||||
* <p>
|
||||
* The default implementation provided will
|
||||
* <ol>
|
||||
* <li>Get {@link BlocksToPlace} via {@link #getBlocksToPlace(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}. If not null
|
||||
* <ol>
|
||||
* <li>call {@link #check(Object, World, int, int, int)}. If this returns {@code true}, {@link PlaceResult#SKIP} will be returned without further action.</li>
|
||||
* <li>Use the {@link BlocksToPlace} retrieved earlier and passed in {@link IItemSource} to determine an item to place</li>
|
||||
* <li>Hand over control to {@link StructureUtility#survivalPlaceBlock(ItemStack, NBTMode, NBTTagCompound, boolean, World, int, int, int, IItemSource, EntityPlayer, Consumer)}</li>
|
||||
* </ol>
|
||||
* </li>
|
||||
* <li>Call legacy {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, Consumer)} if {@code env.getActor()} contains an {@link EntityPlayerMP}</li>
|
||||
* <li>Emit warning under debug mode (or throw exception under panic mode), then return {@link PlaceResult#SKIP}</li>
|
||||
* <li>Get {@link BlocksToPlace} via
|
||||
* {@link #getBlocksToPlace(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}. If not null
|
||||
* <ol>
|
||||
* <li>call {@link #check(Object, World, int, int, int)}. If this returns {@code true}, {@link PlaceResult#SKIP}
|
||||
* will be returned without further action.</li>
|
||||
* <li>Use the {@link BlocksToPlace} retrieved earlier and passed in {@link IItemSource} to determine an item to
|
||||
* place</li>
|
||||
* <li>Hand over control to
|
||||
* {@link StructureUtility#survivalPlaceBlock(ItemStack, NBTMode, NBTTagCompound, boolean, World, int, int, int, IItemSource, EntityPlayer, Consumer)}</li>
|
||||
* </ol>
|
||||
* </li>
|
||||
* <li>Call legacy
|
||||
* {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, Consumer)} if
|
||||
* {@code env.getActor()} contains an {@link EntityPlayerMP}</li>
|
||||
* <li>Emit warning under debug mode (or throw exception under panic mode), then return
|
||||
* {@link PlaceResult#SKIP}</li>
|
||||
* </ol>
|
||||
* It should be noticed that the default implementation is likely to cause unexpected issues if the
|
||||
* {@link #check(Object, World, int, int, int)} is not side effect free, or is not idempotent.
|
||||
* E.g. the {@link #check(Object, World, int, int, int)} will add current coord to a {@link java.util.List}. As
|
||||
* this method might be invoked at a location that is already accepted, this will cause the machine to have multiple
|
||||
* of this coord in its list.
|
||||
* {@link #check(Object, World, int, int, int)} is not side effect free, or is not idempotent. E.g. the
|
||||
* {@link #check(Object, World, int, int, int)} will add current coord to a {@link java.util.List}. As this method
|
||||
* might be invoked at a location that is already accepted, this will cause the machine to have multiple of this
|
||||
* coord in its list.
|
||||
*
|
||||
* @param trigger trigger item
|
||||
* @param env autoplacing environment
|
||||
*/
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
BlocksToPlace e = getBlocksToPlace(t, world, x, y, z, trigger, env);
|
||||
IItemSource source = env.getSource();
|
||||
EntityPlayer actor = env.getActor();
|
||||
@@ -130,22 +136,41 @@ public interface IStructureElement<T> {
|
||||
if (e.getStacks() == null) {
|
||||
ItemStack taken = source.takeOne(e.getPredicate(), true);
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
taken, NBTMode.EXACT, taken.stackTagCompound, true, world, x, y, z, source, actor, chatter);
|
||||
taken,
|
||||
NBTMode.EXACT,
|
||||
taken.stackTagCompound,
|
||||
true,
|
||||
world,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
source,
|
||||
actor,
|
||||
chatter);
|
||||
}
|
||||
for (ItemStack stack : e.getStacks()) {
|
||||
if (!source.takeOne(stack, true)) continue;
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
stack, NBTMode.EXACT, stack.stackTagCompound, true, world, x, y, z, source, actor, chatter);
|
||||
stack,
|
||||
NBTMode.EXACT,
|
||||
stack.stackTagCompound,
|
||||
true,
|
||||
world,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
source,
|
||||
actor,
|
||||
chatter);
|
||||
}
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
if (actor instanceof EntityPlayerMP)
|
||||
return survivalPlaceBlock(t, world, x, y, z, trigger, source, (EntityPlayerMP) actor, chatter);
|
||||
if (PANIC_MODE) throw new RuntimeException("Panic Tripwire hit");
|
||||
if (StructureLibAPI.isDebugEnabled())
|
||||
LOGGER.info(
|
||||
"Fallback shim code of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}",
|
||||
getClass().getName());
|
||||
if (StructureLibAPI.isDebugEnabled()) LOGGER.info(
|
||||
"Fallback shim code of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}",
|
||||
getClass().getName());
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
|
||||
@@ -197,18 +222,19 @@ public interface IStructureElement<T> {
|
||||
|
||||
enum PlaceResult {
|
||||
/**
|
||||
* This element either exists already, or does not yet have an implementation for survivalPlaceBlock, or
|
||||
* some other unforeseen situations.
|
||||
* TODO this definition doesn't seem right. Should we separate SKIP from EXISTS, or SKIP from ERROR?
|
||||
* This element either exists already, or does not yet have an implementation for survivalPlaceBlock, or some
|
||||
* other unforeseen situations. TODO this definition doesn't seem right. Should we separate SKIP from EXISTS, or
|
||||
* SKIP from ERROR?
|
||||
*/
|
||||
SKIP,
|
||||
/**
|
||||
* This element's space is occupied by other stuff and require player attention, or player missing required resource,
|
||||
* or the block cannot be placed due to obscure mechanisms, or some other unforeseen situations.
|
||||
* This element's space is occupied by other stuff and require player attention, or player missing required
|
||||
* resource, or the block cannot be placed due to obscure mechanisms, or some other unforeseen situations.
|
||||
*/
|
||||
REJECT,
|
||||
/**
|
||||
* Autoplace cannot proceed within this tick. To proceed further would require stopping the placement and wait for next round.
|
||||
* Autoplace cannot proceed within this tick. To proceed further would require stopping the placement and wait
|
||||
* for next round.
|
||||
*/
|
||||
STOP,
|
||||
/**
|
||||
@@ -224,6 +250,7 @@ public interface IStructureElement<T> {
|
||||
}
|
||||
|
||||
final class BlocksToPlace {
|
||||
|
||||
public static final BlocksToPlace errored = createEmpty();
|
||||
private final Predicate<ItemStack> predicate;
|
||||
private final Iterable<ItemStack> stacks;
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Use StructureUtility to instantiate
|
||||
*/
|
||||
public interface IStructureElementChain<T> extends IStructureElement<T> {
|
||||
|
||||
IStructureElement<T>[] fallbacks();
|
||||
|
||||
@Override
|
||||
@@ -49,8 +53,8 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
default BlocksToPlace getBlocksToPlace(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default BlocksToPlace getBlocksToPlace(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
Predicate<ItemStack> predicate = null;
|
||||
List<Iterable<ItemStack>> is = new ArrayList<>();
|
||||
for (IStructureElement<T> fallback : fallbacks()) {
|
||||
@@ -65,16 +69,8 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
boolean haveSkip = false;
|
||||
List<IChatComponent> bufferedNoise = new ArrayList<>();
|
||||
for (IStructureElement<T> fallback : fallbacks()) {
|
||||
@@ -96,13 +92,13 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
boolean haveSkip = false;
|
||||
List<IChatComponent> bufferedNoise = new ArrayList<>();
|
||||
for (IStructureElement<T> fallback : fallbacks()) {
|
||||
PlaceResult result =
|
||||
fallback.survivalPlaceBlock(t, world, x, y, z, trigger, env.withChatter(bufferedNoise::add));
|
||||
PlaceResult result = fallback
|
||||
.survivalPlaceBlock(t, world, x, y, z, trigger, env.withChatter(bufferedNoise::add));
|
||||
switch (result) {
|
||||
case REJECT:
|
||||
break;
|
||||
|
||||
+6
-12
@@ -1,12 +1,14 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IStructureElementCheckOnly<T> extends IStructureElement<T> {
|
||||
|
||||
@Override
|
||||
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
return false;
|
||||
@@ -18,22 +20,14 @@ public interface IStructureElementCheckOnly<T> extends IStructureElement<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -3,4 +3,5 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
/**
|
||||
* Use StructureUtility to instantiate
|
||||
*/
|
||||
public interface IStructureElementDeferred<T> extends IStructureElement<T> {}
|
||||
public interface IStructureElementDeferred<T> extends IStructureElement<T> {
|
||||
}
|
||||
+6
-12
@@ -1,34 +1,28 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IStructureElementNoPlacement<T> extends IStructureElement<T> {
|
||||
|
||||
@Override
|
||||
default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
@@ -10,6 +11,7 @@ import net.minecraft.world.World;
|
||||
* Use StructureUtility to instantiate
|
||||
*/
|
||||
interface IStructureNavigate<T> extends IStructureElement<T> {
|
||||
|
||||
@Override
|
||||
default boolean check(T t, World world, int x, int y, int z) {
|
||||
return true;
|
||||
@@ -26,22 +28,14 @@ interface IStructureNavigate<T> extends IStructureElement<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,23 +3,25 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
interface IStructureWalker<T> {
|
||||
|
||||
boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c);
|
||||
|
||||
default boolean blockNotLoaded(
|
||||
IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
|
||||
default boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z, int a, int b,
|
||||
int c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static <T> IStructureWalker<T> ignoreBlockUnloaded(IStructureWalker<T> walker) {
|
||||
return new IStructureWalker<T>() {
|
||||
|
||||
@Override
|
||||
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
|
||||
return walker.visit(element, world, x, y, z, a, b, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blockNotLoaded(
|
||||
IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
|
||||
public boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z, int a, int b,
|
||||
int c) {
|
||||
return walker.visit(element, world, x, y, z, a, b, c);
|
||||
}
|
||||
};
|
||||
@@ -27,14 +29,15 @@ interface IStructureWalker<T> {
|
||||
|
||||
static <T> IStructureWalker<T> skipBlockUnloaded(IStructureWalker<T> walker) {
|
||||
return new IStructureWalker<T>() {
|
||||
|
||||
@Override
|
||||
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
|
||||
return walker.visit(element, world, x, y, z, a, b, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blockNotLoaded(
|
||||
IStructureElement<T> element, World world, int x, int y, int z, int a, int b, int c) {
|
||||
public boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z, int a, int b,
|
||||
int c) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
+11
-5
@@ -1,25 +1,31 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
|
||||
/*
|
||||
* Architecture notes: this should never get any callback from survival build. All structure significant code belongs
|
||||
* within the IStructureElement. This will make the user easier to maintain the IStructureDefinition.
|
||||
* Structure Element knows the most about what this structure element should do, not the caller.
|
||||
* within the IStructureElement. This will make the user easier to maintain the IStructureDefinition. Structure Element
|
||||
* knows the most about what this structure element should do, not the caller.
|
||||
*/
|
||||
public interface ISurvivalBuildEnvironment {
|
||||
|
||||
/**
|
||||
* Get the source of the items. This will be invoked exactly once per structure element build.
|
||||
* <p>
|
||||
* If the call chain ever got into the old API, this will be called at least once per {@link IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, ISurvivalBuildEnvironment, boolean)} call.
|
||||
* If the call chain ever got into the old API, this will be called at least once per
|
||||
* {@link IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, ISurvivalBuildEnvironment, boolean)}
|
||||
* call.
|
||||
*/
|
||||
IItemSource getSource();
|
||||
|
||||
/**
|
||||
* Get the origin of action. This will be invoked at least once per {@link IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, ISurvivalBuildEnvironment, boolean)} call.
|
||||
* Get the origin of action. This will be invoked at least once per
|
||||
* {@link IStructureDefinition#survivalBuild(Object, ItemStack, String, World, ExtendedFacing, int, int, int, int, int, int, int, ISurvivalBuildEnvironment, boolean)}
|
||||
* call.
|
||||
*/
|
||||
EntityPlayer getActor();
|
||||
|
||||
|
||||
@@ -9,5 +9,6 @@ import net.minecraft.block.Block;
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ITierConverter<TIER> {
|
||||
|
||||
TIER convert(Block block, int meta);
|
||||
}
|
||||
@@ -11,5 +11,6 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
* @param <CTX> the temporary state context
|
||||
*/
|
||||
public interface IWithExtendedContext<CTX> {
|
||||
|
||||
CTX getCurrentContext();
|
||||
}
|
||||
@@ -2,13 +2,16 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
class LazyStructureElement<T> implements IStructureElementDeferred<T> {
|
||||
|
||||
private Function<T, IStructureElement<T>> to;
|
||||
private IStructureElement<T> elem;
|
||||
|
||||
@@ -41,28 +44,20 @@ class LazyStructureElement<T> implements IStructureElementDeferred<T> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlocksToPlace getBlocksToPlace(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
public BlocksToPlace getBlocksToPlace(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return get(t).getBlocksToPlace(t, world, x, y, z, trigger, env);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
return get(t).survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
return get(t).survivalPlaceBlock(t, world, x, y, z, trigger, env);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,13 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
|
||||
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
|
||||
public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
|
||||
private final Map<Character, IStructureElement<T>> elements;
|
||||
private final Map<String, String> shapes;
|
||||
private final Map<String, IStructureElement<T>[]> structures;
|
||||
@@ -16,11 +18,8 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
private StructureDefinition(
|
||||
Map<Character, IStructureElement<T>> elements,
|
||||
Map<String, String> shapes,
|
||||
Map<String, IStructureElement<T>[]> structures,
|
||||
Map<String, Set<Vec3Impl>> occupiedSpaces) {
|
||||
private StructureDefinition(Map<Character, IStructureElement<T>> elements, Map<String, String> shapes,
|
||||
Map<String, IStructureElement<T>[]> structures, Map<String, Set<Vec3Impl>> occupiedSpaces) {
|
||||
this.elements = elements;
|
||||
this.shapes = shapes;
|
||||
this.structures = structures;
|
||||
@@ -28,6 +27,7 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
}
|
||||
|
||||
public static class Builder<T> {
|
||||
|
||||
private static final char A = '\uA000';
|
||||
private static final char B = '\uB000';
|
||||
private static final char C = '\uC000';
|
||||
@@ -54,11 +54,10 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
|
||||
/**
|
||||
* Adds shape. Shape is a two-dimensional string array. Each <b>character</b> inside any of these strings will
|
||||
* be later mapped to a particular type of {@link IStructureElement} as indicated by {@link #addElement(Character, IStructureElement)}.
|
||||
* be later mapped to a particular type of {@link IStructureElement} as indicated by
|
||||
* {@link #addElement(Character, IStructureElement)}.
|
||||
* <p>
|
||||
* next char is next block(a)
|
||||
* next string is next line(b)
|
||||
* next string[] is next slice(c)
|
||||
* next char is next block(a) next string is next line(b) next string[] is next slice(c)
|
||||
* <p>
|
||||
* There are a few special reserved characters that are pre-mapped to some common structure elements
|
||||
* <ul>
|
||||
@@ -71,7 +70,8 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
* <p>
|
||||
*
|
||||
* @param name unlocalized/code name
|
||||
* @param structurePiece generated or written struct - DO NOT STORE IT ANYWHERE, or at least set them to null afterwards
|
||||
* @param structurePiece generated or written struct - DO NOT STORE IT ANYWHERE, or at least set them to null
|
||||
* afterwards
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder<T> addShape(String name, String[][] structurePiece) {
|
||||
@@ -170,22 +170,25 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
public IStructureDefinition<T> build() {
|
||||
Map<String, IStructureElement<T>[]> structures = compileStructureMap();
|
||||
return new StructureDefinition<>(
|
||||
new HashMap<>(elements), new HashMap<>(shapes), structures, occupiedSpaces);
|
||||
new HashMap<>(elements),
|
||||
new HashMap<>(shapes),
|
||||
structures,
|
||||
occupiedSpaces);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, IStructureElement<T>[]> compileElementSetMap() {
|
||||
Set<Integer> missing = findMissing();
|
||||
if (missing.isEmpty()) {
|
||||
return shapes.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
|
||||
.chars()
|
||||
.mapToObj(c -> (char) c)
|
||||
.distinct()
|
||||
.map(elements::get)
|
||||
.toArray(IStructureElement[]::new)));
|
||||
return shapes.entrySet().stream().collect(
|
||||
Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
e -> e.getValue().chars().mapToObj(c -> (char) c).distinct().map(elements::get)
|
||||
.toArray(IStructureElement[]::new)));
|
||||
} else {
|
||||
throw new RuntimeException("Missing Structure Element bindings for (chars as integers): "
|
||||
+ Arrays.toString(missing.toArray()));
|
||||
throw new RuntimeException(
|
||||
"Missing Structure Element bindings for (chars as integers): "
|
||||
+ Arrays.toString(missing.toArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,22 +196,21 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
private Map<String, IStructureElement<T>[]> compileStructureMap() {
|
||||
Set<Integer> missing = findMissing();
|
||||
if (missing.isEmpty()) {
|
||||
return shapes.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
|
||||
.chars()
|
||||
.mapToObj(c -> elements.get((char) c))
|
||||
.toArray(IStructureElement[]::new)));
|
||||
return shapes.entrySet().stream().collect(
|
||||
Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
e -> e.getValue().chars().mapToObj(c -> elements.get((char) c))
|
||||
.toArray(IStructureElement[]::new)));
|
||||
} else {
|
||||
throw new RuntimeException("Missing Structure Element bindings for (chars as integers): "
|
||||
+ Arrays.toString(missing.toArray()));
|
||||
throw new RuntimeException(
|
||||
"Missing Structure Element bindings for (chars as integers): "
|
||||
+ Arrays.toString(missing.toArray()));
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Integer> findMissing() {
|
||||
return shapes.values().stream()
|
||||
.flatMapToInt(CharSequence::chars)
|
||||
.filter(i -> !elements.containsKey((char) i))
|
||||
.boxed()
|
||||
.collect(Collectors.toSet());
|
||||
return shapes.values().stream().flatMapToInt(CharSequence::chars)
|
||||
.filter(i -> !elements.containsKey((char) i)).boxed().collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
@@ -10,23 +11,16 @@ import net.minecraft.world.World;
|
||||
* Internal bridge class for easing implementation
|
||||
*/
|
||||
abstract class StructureElement_Bridge<T> implements IStructureElement<T> {
|
||||
|
||||
// seal the deprecated method to prevent accidental overrides
|
||||
@Deprecated
|
||||
@Override
|
||||
public final PlaceResult survivalPlaceBlock(
|
||||
T t,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
ItemStack trigger,
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
public final PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s,
|
||||
EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
return survivalPlaceBlock(t, world, x, y, z, trigger, AutoPlaceEnvironment.fromLegacy(s, actor, chatter));
|
||||
}
|
||||
|
||||
// clear the default implementation. we don't need that.
|
||||
public abstract PlaceResult survivalPlaceBlock(
|
||||
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env);
|
||||
public abstract PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
+7
-12
@@ -1,12 +1,14 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.IStructureElement.PlaceResult;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
class SurvivalBuildStructureWalker<T> implements IStructureWalker<T> {
|
||||
|
||||
final T object;
|
||||
final ItemStack trigger;
|
||||
private final int elementBudget;
|
||||
@@ -16,16 +18,9 @@ class SurvivalBuildStructureWalker<T> implements IStructureWalker<T> {
|
||||
|
||||
private final AutoPlaceEnvironment env;
|
||||
|
||||
public SurvivalBuildStructureWalker(
|
||||
T object,
|
||||
ItemStack trigger,
|
||||
int elementBudget,
|
||||
ISurvivalBuildEnvironment params,
|
||||
IStructureDefinition<?> definition,
|
||||
String piece,
|
||||
ExtendedFacing facing,
|
||||
int[] baseOffsetABC,
|
||||
boolean check) {
|
||||
public SurvivalBuildStructureWalker(T object, ItemStack trigger, int elementBudget,
|
||||
ISurvivalBuildEnvironment params, IStructureDefinition<?> definition, String piece, ExtendedFacing facing,
|
||||
int[] baseOffsetABC, boolean check) {
|
||||
this.object = object;
|
||||
this.trigger = trigger;
|
||||
this.elementBudget = elementBudget;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.structure.adders;
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
public interface IBlockAdder<T> {
|
||||
|
||||
/**
|
||||
* Callback on block added, needs to check if block is valid (and add it)
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.structure.adders;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
public interface ITileAdder<T> {
|
||||
|
||||
/**
|
||||
* Callback to add hatch, needs to check if tile is valid (and add it)
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* This package provide support for multiblock structure checking.
|
||||
* <p>
|
||||
* All public stuff in this package and its subpackages are considered part of the public API.
|
||||
* Backwards compatibility is maintained to the maximum extend possible.
|
||||
* All public stuff in this package and its subpackages are considered part of the public API. Backwards compatibility
|
||||
* is maintained to the maximum extend possible.
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
@@ -2,10 +2,12 @@ package com.gtnewhorizon.structurelib.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class InventoryIterable<Inv extends IInventory> implements Iterable<ItemStack> {
|
||||
|
||||
private final Inv inv;
|
||||
private final int maxSlot;
|
||||
|
||||
@@ -25,6 +27,7 @@ public class InventoryIterable<Inv extends IInventory> implements Iterable<ItemS
|
||||
@Override
|
||||
public Iterator<ItemStack> iterator() {
|
||||
return new Iterator<ItemStack>() {
|
||||
|
||||
private int ptr = 0;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,32 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2022, glee8e
|
||||
* This file is part of StructureLib.
|
||||
* Copyright (c) 2022, glee8e This file is part of StructureLib.
|
||||
* <p>
|
||||
* StructureLib is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* StructureLib is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
|
||||
* later version.
|
||||
* <p>
|
||||
* StructureLib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* StructureLib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Foobar; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License along with Foobar; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.util;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
|
||||
import com.gtnewhorizon.structurelib.util.InventoryUtility.ItemStackExtractor.APIType;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
@@ -34,10 +29,15 @@ import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.inventory.InventoryEnderChest;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
|
||||
import com.gtnewhorizon.structurelib.util.InventoryUtility.ItemStackExtractor.APIType;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
|
||||
/**
|
||||
* This class is part of API, but is not stable. Use at your own risk.
|
||||
*/
|
||||
public class InventoryUtility {
|
||||
|
||||
private static final SortedRegistry<ItemStackExtractor> stackExtractors = new SortedRegistry<>();
|
||||
private static final List<Predicate<? super EntityPlayerMP>> enableEnder = new CopyOnWriteArrayList<>();
|
||||
/**
|
||||
@@ -47,6 +47,7 @@ public class InventoryUtility {
|
||||
|
||||
static {
|
||||
inventoryProviders.register("5000-main-inventory", new InventoryProvider<InventoryIterable<InventoryPlayer>>() {
|
||||
|
||||
@Override
|
||||
public InventoryIterable<InventoryPlayer> getInventory(EntityPlayerMP player) {
|
||||
return new InventoryIterable<>(player.inventory, player.inventory.mainInventory.length);
|
||||
@@ -59,8 +60,9 @@ public class InventoryUtility {
|
||||
inv.getInventory().player.inventoryContainer.detectAndSendChanges();
|
||||
}
|
||||
});
|
||||
inventoryProviders.register(
|
||||
"7000-ender-inventory", new InventoryProvider<InventoryIterable<InventoryEnderChest>>() {
|
||||
inventoryProviders
|
||||
.register("7000-ender-inventory", new InventoryProvider<InventoryIterable<InventoryEnderChest>>() {
|
||||
|
||||
@Override
|
||||
public InventoryIterable<InventoryEnderChest> getInventory(EntityPlayerMP player) {
|
||||
if (enableEnder.stream().anyMatch(p -> p.test(player)))
|
||||
@@ -86,8 +88,8 @@ public class InventoryUtility {
|
||||
stackExtractors.register(key, val);
|
||||
}
|
||||
|
||||
public static <Inv extends IInventory> void registerStackExtractor(
|
||||
String key, Function<ItemStack, ? extends Inv> extractor) {
|
||||
public static <Inv extends IInventory> void registerStackExtractor(String key,
|
||||
Function<ItemStack, ? extends Inv> extractor) {
|
||||
registerStackExtractor(key, newItemStackProvider(extractor));
|
||||
}
|
||||
|
||||
@@ -95,8 +97,8 @@ public class InventoryUtility {
|
||||
inventoryProviders.register(key, val);
|
||||
}
|
||||
|
||||
public static <Inv extends IInventory> void registerInventoryProvider(
|
||||
String key, Function<EntityPlayerMP, ? extends Inv> extractor) {
|
||||
public static <Inv extends IInventory> void registerInventoryProvider(String key,
|
||||
Function<EntityPlayerMP, ? extends Inv> extractor) {
|
||||
registerInventoryProvider(key, newInventoryProvider(extractor));
|
||||
}
|
||||
|
||||
@@ -107,6 +109,7 @@ public class InventoryUtility {
|
||||
public static <Inv extends IInventory> InventoryProvider<InventoryIterable<Inv>> newInventoryProvider(
|
||||
Function<EntityPlayerMP, ? extends Inv> extractor) {
|
||||
return new InventoryProvider<InventoryIterable<Inv>>() {
|
||||
|
||||
@Override
|
||||
public InventoryIterable<Inv> getInventory(EntityPlayerMP player) {
|
||||
Inv inv = extractor.apply(player);
|
||||
@@ -122,24 +125,26 @@ public class InventoryUtility {
|
||||
|
||||
public static ItemStackExtractor newItemStackProvider(Function<ItemStack, ? extends IInventory> extractor) {
|
||||
return new ItemStackExtractor() {
|
||||
|
||||
@Override
|
||||
public boolean isAPIImplemented(APIType type) {
|
||||
return type == APIType.MAIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int takeFromStack(
|
||||
Predicate<ItemStack> predicate,
|
||||
boolean simulate,
|
||||
int count,
|
||||
ItemStackCounter store,
|
||||
ItemStack stack,
|
||||
ItemStack filter,
|
||||
EntityPlayerMP player) {
|
||||
public int takeFromStack(Predicate<ItemStack> predicate, boolean simulate, int count,
|
||||
ItemStackCounter store, ItemStack stack, ItemStack filter, EntityPlayerMP player) {
|
||||
IInventory inv = extractor.apply(stack);
|
||||
if (inv == null) return 0;
|
||||
int found = takeFromInventory(
|
||||
new InventoryIterable<>(inv), predicate, simulate, count, store, filter, player, false);
|
||||
new InventoryIterable<>(inv),
|
||||
predicate,
|
||||
simulate,
|
||||
count,
|
||||
store,
|
||||
filter,
|
||||
player,
|
||||
false);
|
||||
if (found > 0) inv.markDirty();
|
||||
return found;
|
||||
}
|
||||
@@ -147,8 +152,8 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
/**
|
||||
* take count amount of stacks that matches given filter. might take partial amount of stuff, so simulation is suggested
|
||||
* if you ever need to take more than one.
|
||||
* take count amount of stacks that matches given filter. might take partial amount of stuff, so simulation is
|
||||
* suggested if you ever need to take more than one.
|
||||
*
|
||||
* @param player source of stacks
|
||||
* @param predicate item stack filter
|
||||
@@ -156,8 +161,8 @@ public class InventoryUtility {
|
||||
* @param count let's hope int size is enough...
|
||||
* @return amount taken. never negative nor bigger than count...
|
||||
*/
|
||||
public static Map<ItemStack, Integer> takeFromInventory(
|
||||
EntityPlayerMP player, Predicate<ItemStack> predicate, boolean simulate, int count) {
|
||||
public static Map<ItemStack, Integer> takeFromInventory(EntityPlayerMP player, Predicate<ItemStack> predicate,
|
||||
boolean simulate, int count) {
|
||||
ItemStackCounterImpl store = new ItemStackCounterImpl();
|
||||
int sum = 0;
|
||||
for (InventoryProvider<?> provider : inventoryProviders) {
|
||||
@@ -168,8 +173,8 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
/**
|
||||
* take count amount of stacks that matches given filter. might take partial amount of stuff, so simulation is suggested
|
||||
* if you ever need to take more than one.
|
||||
* take count amount of stacks that matches given filter. might take partial amount of stuff, so simulation is
|
||||
* suggested if you ever need to take more than one.
|
||||
*
|
||||
* @param player source of stacks
|
||||
* @param filter the precise type of item to extract. stackSize matters
|
||||
@@ -189,14 +194,9 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
// workaround java generics issue
|
||||
private static <R extends Iterable<ItemStack>> int takeFromPlayer(
|
||||
EntityPlayerMP player,
|
||||
Predicate<ItemStack> predicate,
|
||||
boolean simulate,
|
||||
int count,
|
||||
ItemStackCounterImpl store,
|
||||
InventoryProvider<R> provider,
|
||||
ItemStack filter) {
|
||||
private static <R extends Iterable<ItemStack>> int takeFromPlayer(EntityPlayerMP player,
|
||||
Predicate<ItemStack> predicate, boolean simulate, int count, ItemStackCounterImpl store,
|
||||
InventoryProvider<R> provider, ItemStack filter) {
|
||||
R inv = provider.getInventory(player);
|
||||
if (inv == null) return 0;
|
||||
int taken = takeFromInventory(inv, predicate, simulate, count, store, filter, player, true);
|
||||
@@ -215,29 +215,23 @@ public class InventoryUtility {
|
||||
* @param recursive do recursive lookup using {@link #getStackExtractors() stack extractors}
|
||||
* @return amount taken. never negative nor bigger than count...
|
||||
*/
|
||||
public static Map<ItemStack, Integer> takeFromInventory(
|
||||
Iterable<ItemStack> inv, Predicate<ItemStack> predicate, boolean simulate, int count, boolean recursive) {
|
||||
public static Map<ItemStack, Integer> takeFromInventory(Iterable<ItemStack> inv, Predicate<ItemStack> predicate,
|
||||
boolean simulate, int count, boolean recursive) {
|
||||
ItemStackCounterImpl store = new ItemStackCounterImpl();
|
||||
takeFromInventory(inv, predicate, simulate, count, store, null, null, recursive);
|
||||
return store.getStore();
|
||||
}
|
||||
|
||||
private static int takeFromInventory(
|
||||
@Nonnull Iterable<ItemStack> inv,
|
||||
@Nonnull Predicate<ItemStack> predicate,
|
||||
boolean simulate,
|
||||
int count,
|
||||
@Nonnull ItemStackCounter store,
|
||||
@Nullable ItemStack filter,
|
||||
@Nullable EntityPlayerMP player,
|
||||
boolean recursive) {
|
||||
private static int takeFromInventory(@Nonnull Iterable<ItemStack> inv, @Nonnull Predicate<ItemStack> predicate,
|
||||
boolean simulate, int count, @Nonnull ItemStackCounter store, @Nullable ItemStack filter,
|
||||
@Nullable EntityPlayerMP player, boolean recursive) {
|
||||
int found = 0;
|
||||
ItemStack copiedFilter = null;
|
||||
if (filter != null) {
|
||||
copiedFilter = new ItemStack(filter.getItem(), filter.stackSize, Items.feather.getDamage(filter));
|
||||
copiedFilter.setTagCompound(filter.stackTagCompound);
|
||||
}
|
||||
for (Iterator<ItemStack> iterator = inv.iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<ItemStack> iterator = inv.iterator(); iterator.hasNext();) {
|
||||
ItemStack stack = iterator.next();
|
||||
// invalid stack
|
||||
if (stack == null || stack.getItem() == null || stack.stackSize <= 0) continue;
|
||||
@@ -272,9 +266,10 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
public interface OptimizedExtractor {
|
||||
|
||||
/**
|
||||
* Extract a particular type of item. The extractor can choose to not return all items contained within this item
|
||||
* as long as it makes sense, but the author should inform the player of this.
|
||||
* Extract a particular type of item. The extractor can choose to not return all items contained within this
|
||||
* item as long as it makes sense, but the author should inform the player of this.
|
||||
* <p>
|
||||
* Whether optimized extractor do recursive extraction is at the discretion of implementor.
|
||||
*
|
||||
@@ -288,12 +283,14 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
public interface InventoryProvider<R extends Iterable<ItemStack>> {
|
||||
|
||||
R getInventory(EntityPlayerMP player);
|
||||
|
||||
void markDirty(R inv);
|
||||
}
|
||||
|
||||
public interface ItemStackExtractor {
|
||||
|
||||
enum APIType {
|
||||
MAIN,
|
||||
EXTRACT_ONE_STACK,
|
||||
@@ -302,13 +299,13 @@ public class InventoryUtility {
|
||||
boolean isAPIImplemented(APIType type);
|
||||
|
||||
/**
|
||||
* Extract a particular type of item. The extractor can choose to not return all items contained within this item
|
||||
* as long as it makes sense, but the author should inform the player of this.
|
||||
* Extract a particular type of item. The extractor can choose to not return all items contained within this
|
||||
* item as long as it makes sense, but the author should inform the player of this.
|
||||
* <p>
|
||||
* Whether this method does recursive extraction is at the discretion of implementor.
|
||||
*
|
||||
* @param predicate the main filtering predicate. never null. It's assumed predicate always returns true on filter,
|
||||
* if that is not null
|
||||
* @param predicate the main filtering predicate. never null. It's assumed predicate always returns true on
|
||||
* filter, if that is not null
|
||||
* @param store where to store extracted items. Should increment the
|
||||
* @param source from where an extraction should be attempted
|
||||
* @param filter stack to extract. should not be mutated! match the NBT tag using EXACT mode. might be null.
|
||||
@@ -316,18 +313,12 @@ public class InventoryUtility {
|
||||
* @param player executor of extraction, or null if from a machine
|
||||
* @return amount extracted, or -1 if this is not implemented
|
||||
*/
|
||||
int takeFromStack(
|
||||
Predicate<ItemStack> predicate,
|
||||
boolean simulate,
|
||||
int count,
|
||||
ItemStackCounter store,
|
||||
ItemStack source,
|
||||
ItemStack filter,
|
||||
EntityPlayerMP player);
|
||||
int takeFromStack(Predicate<ItemStack> predicate, boolean simulate, int count, ItemStackCounter store,
|
||||
ItemStack source, ItemStack filter, EntityPlayerMP player);
|
||||
|
||||
/**
|
||||
* Extract a particular type of item. The extractor can choose to not return all items contained within this item
|
||||
* as long as it makes sense, but the author should inform the player of this.
|
||||
* Extract a particular type of item. The extractor can choose to not return all items contained within this
|
||||
* item as long as it makes sense, but the author should inform the player of this.
|
||||
* <p>
|
||||
* Whether this method does recursive extraction is at the discretion of implementor.
|
||||
*
|
||||
@@ -343,20 +334,15 @@ public class InventoryUtility {
|
||||
|
||||
static ItemStackExtractor createOnlyOptimized(@Nonnull OptimizedExtractor optimizedExtractor) {
|
||||
return new ItemStackExtractor() {
|
||||
|
||||
@Override
|
||||
public boolean isAPIImplemented(APIType type) {
|
||||
return type == APIType.EXTRACT_ONE_STACK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int takeFromStack(
|
||||
Predicate<ItemStack> predicate,
|
||||
boolean simulate,
|
||||
int count,
|
||||
ItemStackCounter store,
|
||||
ItemStack stack,
|
||||
ItemStack filter,
|
||||
EntityPlayerMP player) {
|
||||
public int takeFromStack(Predicate<ItemStack> predicate, boolean simulate, int count,
|
||||
ItemStackCounter store, ItemStack stack, ItemStack filter, EntityPlayerMP player) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,6 +355,7 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
public interface ItemStackCounter {
|
||||
|
||||
/**
|
||||
* Add some amount of stack. Note stackSize is used instead of stack.stackSize.
|
||||
*/
|
||||
@@ -376,6 +363,7 @@ public class InventoryUtility {
|
||||
}
|
||||
|
||||
private static class ItemStackCounterImpl implements ItemStackCounter {
|
||||
|
||||
private final Map<ItemStack, Integer> store = new ItemStackMap<>(true);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.gtnewhorizon.structurelib.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class ItemStackArrayIterable implements Iterable<ItemStack> {
|
||||
|
||||
private final ItemStack[] stacks;
|
||||
|
||||
public ItemStackArrayIterable(ItemStack[] stacks) {
|
||||
@@ -17,6 +19,7 @@ public class ItemStackArrayIterable implements Iterable<ItemStack> {
|
||||
@Override
|
||||
public Iterator<ItemStack> iterator() {
|
||||
return new Iterator<ItemStack>() {
|
||||
|
||||
private int ptr = 0;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib.util;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
@@ -11,6 +12,7 @@ import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
public final class ItemStackPredicate implements Predicate<ItemStack> {
|
||||
|
||||
public static ItemStackPredicate from(Item item) {
|
||||
return new ItemStackPredicate(item);
|
||||
}
|
||||
@@ -20,8 +22,7 @@ public final class ItemStackPredicate implements Predicate<ItemStack> {
|
||||
}
|
||||
|
||||
public static ItemStackPredicate from(ItemStack itemStack, NBTMode mode) {
|
||||
return new ItemStackPredicate(itemStack.getItem())
|
||||
.setMeta(Items.feather.getDamage(itemStack))
|
||||
return new ItemStackPredicate(itemStack.getItem()).setMeta(Items.feather.getDamage(itemStack))
|
||||
.setTag(mode, itemStack.stackTagCompound);
|
||||
}
|
||||
|
||||
@@ -63,13 +64,16 @@ public final class ItemStackPredicate implements Predicate<ItemStack> {
|
||||
}
|
||||
|
||||
public enum NBTMode implements BiPredicate<NBTTagCompound, NBTTagCompound> {
|
||||
|
||||
IGNORE {
|
||||
|
||||
@Override
|
||||
public boolean test(NBTTagCompound lhs, NBTTagCompound rhs) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
IN {
|
||||
|
||||
@Override
|
||||
public boolean test(NBTTagCompound lhs, NBTTagCompound rhs) {
|
||||
if (lhs == null || lhs.hasNoTags()) return true;
|
||||
@@ -87,6 +91,7 @@ public final class ItemStackPredicate implements Predicate<ItemStack> {
|
||||
}
|
||||
},
|
||||
EXACT {
|
||||
|
||||
@Override
|
||||
public boolean test(NBTTagCompound lhs, NBTTagCompound rhs) {
|
||||
if (lhs != null && lhs.hasNoTags()) lhs = null;
|
||||
@@ -95,6 +100,7 @@ public final class ItemStackPredicate implements Predicate<ItemStack> {
|
||||
}
|
||||
},
|
||||
IGNORE_KNOWN_INSIGNIFICANT_TAGS {
|
||||
|
||||
@Override
|
||||
public boolean test(NBTTagCompound lhs, NBTTagCompound rhs) {
|
||||
// fast path for empty tags
|
||||
@@ -105,8 +111,8 @@ public final class ItemStackPredicate implements Predicate<ItemStack> {
|
||||
return EXACT.test(lhs, rhs);
|
||||
}
|
||||
};
|
||||
private static final String[] KNOWN_INSIGNIFICANT_TAGS = {
|
||||
"display", // TODO expand/refine this
|
||||
|
||||
private static final String[] KNOWN_INSIGNIFICANT_TAGS = { "display", // TODO expand/refine this
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.gtnewhorizon.structurelib.util;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* not related to a certain mod!
|
||||
*/
|
||||
public class MiscUtils {
|
||||
|
||||
private MiscUtils() {}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SortedRegistry<V> implements Iterable<V> {
|
||||
|
||||
private final NavigableMap<String, V> store = new TreeMap<>();
|
||||
/**
|
||||
* Store stuff in an array for faster iteration access than a red black tree
|
||||
|
||||
@@ -3,10 +3,12 @@ package com.gtnewhorizon.structurelib.util;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.dispenser.IPosition;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public class Vec3Impl implements Comparable<Vec3Impl> {
|
||||
|
||||
public static final Vec3Impl NULL_VECTOR = new Vec3Impl(0, 0, 0);
|
||||
private static final Map<Vec3Impl, Vec3Impl> pool = new HashMap<>();
|
||||
private final int val0;
|
||||
@@ -69,8 +71,7 @@ public class Vec3Impl implements Comparable<Vec3Impl> {
|
||||
}
|
||||
|
||||
public Vec3Impl offset(ForgeDirection facing, int n) {
|
||||
return n == 0
|
||||
? this
|
||||
return n == 0 ? this
|
||||
: new Vec3Impl(val0 + facing.offsetX * n, val1 + facing.offsetY * n, val2 + facing.offsetZ * n);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +1,20 @@
|
||||
package com.gtnewhorizon.structurelib.util;
|
||||
/*
|
||||
A subclass of java.util.random that implements the Xorshift random number
|
||||
generator
|
||||
<p>
|
||||
- it is 30% faster than the generator from Java's library - it produces
|
||||
random sequences of higher quality than java.util.Random - this class also
|
||||
provides a clone() function
|
||||
<p>
|
||||
Usage: XSRandom rand = new XSRandom(); //Instantiation x = rand.nextInt();
|
||||
//pull a random number
|
||||
<p>
|
||||
To use the class in legacy code, you may also instantiate an XSRandom object
|
||||
and assign it to a java.util.Random object: java.util.Random rand = new
|
||||
XSRandom();
|
||||
<p>
|
||||
for an explanation of the algorithm, see
|
||||
http://demesos.blogspot.com/2011/09/pseudo-random-number-generators.html
|
||||
|
||||
@author Wilfried Elmenreich University of Klagenfurt/Lakeside Labs
|
||||
* http://www.elmenreich.tk
|
||||
* <p>
|
||||
* This code is released under the GNU Lesser General Public License Version 3
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
* A subclass of java.util.random that implements the Xorshift random number generator <p> - it is 30% faster than the
|
||||
* generator from Java's library - it produces random sequences of higher quality than java.util.Random - this class
|
||||
* also provides a clone() function <p> Usage: XSRandom rand = new XSRandom(); //Instantiation x = rand.nextInt();
|
||||
* //pull a random number <p> To use the class in legacy code, you may also instantiate an XSRandom object and assign it
|
||||
* to a java.util.Random object: java.util.Random rand = new XSRandom(); <p> for an explanation of the algorithm, see
|
||||
* http://demesos.blogspot.com/2011/09/pseudo-random-number-generators.html
|
||||
* @author Wilfried Elmenreich University of Klagenfurt/Lakeside Labs http://www.elmenreich.tk <p> This code is released
|
||||
* under the GNU Lesser General Public License Version 3 http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* XSTR - Xorshift ThermiteRandom
|
||||
* Modified by Bogdan-G
|
||||
* 03.06.2016
|
||||
* version 0.0.4
|
||||
* XSTR - Xorshift ThermiteRandom Modified by Bogdan-G 03.06.2016 version 0.0.4
|
||||
*/
|
||||
public class XSTR extends Random {
|
||||
|
||||
@@ -40,10 +23,11 @@ public class XSTR extends Random {
|
||||
private static final long GAMMA = 0x9e3779b97f4a7c15L;
|
||||
private static final int PROBE_INCREMENT = 0x9e3779b9;
|
||||
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
|
||||
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
|
||||
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
|
||||
private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
|
||||
private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);
|
||||
public static final XSTR XSTR_INSTANCE = new XSTR() {
|
||||
|
||||
@Override
|
||||
public synchronized void setSeed(long seed) {
|
||||
if (!Thread.currentThread().getStackTrace()[2].getClassName().equals(Random.class.getName())) {
|
||||
@@ -53,13 +37,11 @@ public class XSTR extends Random {
|
||||
};
|
||||
|
||||
/*
|
||||
MODIFIED BY: Robotia
|
||||
Modification: Implemented Random class seed generator
|
||||
*/
|
||||
* MODIFIED BY: Robotia Modification: Implemented Random class seed generator
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new pseudo random number generator. The seed is initialized to
|
||||
* the current time, as if by
|
||||
* Creates a new pseudo random number generator. The seed is initialized to the current time, as if by
|
||||
* <code>setSeed(System.currentTimeMillis());</code>.
|
||||
*/
|
||||
public XSTR() {
|
||||
@@ -79,8 +61,8 @@ public class XSTR extends Random {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pseudo random number generator, starting with the specified
|
||||
* seed, using <code>setSeed(seed);</code>.
|
||||
* Creates a new pseudo random number generator, starting with the specified seed, using
|
||||
* <code>setSeed(seed);</code>.
|
||||
*
|
||||
* @param seed the initial seed
|
||||
*/
|
||||
@@ -108,9 +90,8 @@ public class XSTR extends Random {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the seed for this pseudo random number generator. As described
|
||||
* above, two instances of the same random class, starting with the same
|
||||
* seed, produce the same results, if the same methods are called.
|
||||
* Sets the seed for this pseudo random number generator. As described above, two instances of the same random
|
||||
* class, starting with the same seed, produce the same results, if the same methods are called.
|
||||
*
|
||||
* @param seed the new seed
|
||||
*/
|
||||
@@ -128,9 +109,8 @@ public class XSTR extends Random {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of George Marsaglia's elegant Xorshift random generator
|
||||
* 30% faster and better quality than the built-in java.util.random see also
|
||||
* see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
|
||||
* Implementation of George Marsaglia's elegant Xorshift random generator 30% faster and better quality than the
|
||||
* built-in java.util.random see also see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
|
||||
*
|
||||
* @param nbits will shift nbits bits
|
||||
* @return next seed
|
||||
@@ -170,15 +150,14 @@ public class XSTR extends Random {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pseudorandom, uniformly distributed {@code int} value between 0
|
||||
* (inclusive) and the specified value (exclusive), drawn from this random
|
||||
* number generator's sequence. The general contract of {@code nextInt} is
|
||||
* that one {@code int} value in the specified range is pseudorandomly
|
||||
* generated and returned. All {@code bound} possible {@code int} values are
|
||||
* produced with (approximately) equal probability. The method
|
||||
* {@code nextInt(int bound)} is implemented by class {@code Random} as if
|
||||
* by:
|
||||
* <pre> {@code
|
||||
* Returns a pseudorandom, uniformly distributed {@code int} value between 0 (inclusive) and the specified value
|
||||
* (exclusive), drawn from this random number generator's sequence. The general contract of {@code nextInt} is that
|
||||
* one {@code int} value in the specified range is pseudorandomly generated and returned. All {@code bound} possible
|
||||
* {@code int} values are produced with (approximately) equal probability. The method {@code nextInt(int bound)} is
|
||||
* implemented by class {@code Random} as if by:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* public int nextInt(int bound) {
|
||||
* if (bound <= 0)
|
||||
* throw new IllegalArgumentException("bound must be positive");
|
||||
@@ -192,35 +171,29 @@ public class XSTR extends Random {
|
||||
* val = bits % bound;
|
||||
* } while (bits - val + (bound-1) < 0);
|
||||
* return val;
|
||||
* }}</pre>
|
||||
* }}
|
||||
* </pre>
|
||||
*
|
||||
* <p>The hedge "approx
|
||||
* imately" is used in the foregoing description only because the next
|
||||
* method is only approximately an unbiased source of independently chosen
|
||||
* bits. If it were a perfect source of randomly chosen bits, then the
|
||||
* algorithm shown would choose {@code int} values from the stated range
|
||||
* with perfect uniformity.
|
||||
* <p>
|
||||
* The algorithm is slightly tricky. It rejects values that would result in
|
||||
* an uneven distribution (due to the fact that 2^31 is not divisible by n).
|
||||
* The probability of a value being rejected depends on n. The worst case is
|
||||
* n=2^30+1, for which the probability of a reject is 1/2, and the expected
|
||||
* number of iterations before the loop terminates is 2.
|
||||
* The hedge "approx imately" is used in the foregoing description only because the next method is only
|
||||
* approximately an unbiased source of independently chosen bits. If it were a perfect source of randomly chosen
|
||||
* bits, then the algorithm shown would choose {@code int} values from the stated range with perfect uniformity.
|
||||
* <p>
|
||||
* The algorithm treats the case where n is a power of two specially: it
|
||||
* returns the correct number of high-order bits from the underlying
|
||||
* pseudo-random number generator. In the absence of special treatment, the
|
||||
* correct number of <i>low-order</i> bits would be returned. Linear
|
||||
* congruential pseudo-random number generators such as the one implemented
|
||||
* by this class are known to have short periods in the sequence of values
|
||||
* of their low-order bits. Thus, this special case greatly increases the
|
||||
* length of the sequence of values returned by successive calls to this
|
||||
* method if n is a small power of two.
|
||||
* The algorithm is slightly tricky. It rejects values that would result in an uneven distribution (due to the fact
|
||||
* that 2^31 is not divisible by n). The probability of a value being rejected depends on n. The worst case is
|
||||
* n=2^30+1, for which the probability of a reject is 1/2, and the expected number of iterations before the loop
|
||||
* terminates is 2.
|
||||
* <p>
|
||||
* The algorithm treats the case where n is a power of two specially: it returns the correct number of high-order
|
||||
* bits from the underlying pseudo-random number generator. In the absence of special treatment, the correct number
|
||||
* of <i>low-order</i> bits would be returned. Linear congruential pseudo-random number generators such as the one
|
||||
* implemented by this class are known to have short periods in the sequence of values of their low-order bits.
|
||||
* Thus, this special case greatly increases the length of the sequence of values returned by successive calls to
|
||||
* this method if n is a small power of two.
|
||||
*
|
||||
* @param bound the upper bound (exclusive). Must be positive.
|
||||
* @return the next pseudorandom, uniformly distributed {@code int} value
|
||||
* between zero (inclusive) and {@code bound} (exclusive) from this random
|
||||
* number generator's sequence
|
||||
* @return the next pseudorandom, uniformly distributed {@code int} value between zero (inclusive) and {@code bound}
|
||||
* (exclusive) from this random number generator's sequence
|
||||
* @throws IllegalArgumentException if bound is not positive
|
||||
* @since 1.2
|
||||
*/
|
||||
@@ -230,18 +203,10 @@ public class XSTR extends Random {
|
||||
// throw new RuntimeException("BadBound");
|
||||
// }
|
||||
|
||||
/*int r = next(31);
|
||||
int m = bound - 1;
|
||||
if ((bound & m) == 0) // i.e., bound is a power of 2
|
||||
{
|
||||
r = (int) ((bound * (long) r) >> 31);
|
||||
} else {
|
||||
for (int u = r;
|
||||
u - (r = u % bound) + m < 0;
|
||||
u = next(31))
|
||||
;
|
||||
}
|
||||
return r;*/
|
||||
/*
|
||||
* int r = next(31); int m = bound - 1; if ((bound & m) == 0) // i.e., bound is a power of 2 { r = (int) ((bound
|
||||
* * (long) r) >> 31); } else { for (int u = r; u - (r = u % bound) + m < 0; u = next(31)) ; } return r;
|
||||
*/
|
||||
// speedup, new nextInt ~+40%
|
||||
long last = seed ^ seed << 21;
|
||||
last ^= last >>> 35;
|
||||
@@ -269,10 +234,9 @@ public class XSTR extends Random {
|
||||
|
||||
@Override
|
||||
public void nextBytes(byte[] bytes_arr) {
|
||||
for (int iba = 0, lenba = bytes_arr.length; iba < lenba; ) {
|
||||
for (int rndba = nextInt(), nba = Math.min(lenba - iba, Integer.SIZE / Byte.SIZE);
|
||||
nba-- > 0;
|
||||
rndba >>= Byte.SIZE) {
|
||||
for (int iba = 0, lenba = bytes_arr.length; iba < lenba;) {
|
||||
for (int rndba = nextInt(), nba = Math.min(lenba - iba, Integer.SIZE / Byte.SIZE); nba--
|
||||
> 0; rndba >>= Byte.SIZE) {
|
||||
bytes_arr[iba++] = (byte) rndba;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ExtendedFacingTest {
|
||||
|
||||
Reference in new issue
Block a user