mirror of
https://github.com/GTNewHorizons/StructureLib.git
synced 2026-11-09 15:04:56 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b9b4fe25a | ||
|
|
ffd5570bcf | ||
|
|
2c50a0ff16 | ||
|
|
54abc5edc1 | ||
|
|
997da93033 | ||
|
|
bbcf3a8669 | ||
|
|
f1473bbb3a | ||
|
|
086b0a00ff | ||
|
|
6a4886796a | ||
|
|
e6c82d422d | ||
|
|
b4b6f4e5eb | ||
|
|
dfe910ebd3 | ||
|
|
5b0b9ba3c5 | ||
|
|
bd76be4f6f | ||
|
|
d3e258dd30 | ||
|
|
0999964f1a |
No files matched your search
+1
-2
@@ -1,7 +1,7 @@
|
||||
javadoc {
|
||||
javadocTool = javaToolchains.javadocToolFor {
|
||||
// Last version with frames, but it also has search
|
||||
languageVersion = JavaLanguageVersion.of(11)
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
vendor = JvmVendorSpec.ADOPTIUM
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ javadoc {
|
||||
overview "src/main/javadoc/overview.html"
|
||||
links 'https://docs.oracle.com/javase/8/docs/api/'
|
||||
links 'https://skmedix.github.io/ForgeJavaDocs/javadoc/forge/1.7.10-10.13.4.1614/'
|
||||
addBooleanOption("-frames", true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,12 @@ dependencies {
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.6.21:dev")
|
||||
implementation("com.github.GTNewHorizons:NotEnoughItems:2.7.40-GTNH:dev")
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:ServerUtilities:2.1.46")
|
||||
|
||||
testImplementation(platform('org.junit:junit-bom:5.9.2'))
|
||||
testImplementation('org.junit.jupiter:junit-jupiter')
|
||||
|
||||
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.261:dev") {
|
||||
// exclude group: "com.github.GTNewHorizons", module: "StructureLib"
|
||||
// }
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import com.gtnewhorizon.structurelib.net.SetChannelDataMessage;
|
||||
import cpw.mods.fml.client.config.GuiConfig;
|
||||
import cpw.mods.fml.client.event.ConfigChangedEvent;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.eventhandler.EventPriority;
|
||||
@@ -259,6 +260,11 @@ public class ClientProxy extends CommonProxy {
|
||||
MinecraftForge.EVENT_BUS.register(new ForgeEventHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FMLInitializationEvent e) {
|
||||
super.init(e);
|
||||
}
|
||||
|
||||
static void markTextureUsed(IIcon icon) {
|
||||
if (StructureLib.COMPAT instanceof IStructureCompat)
|
||||
((IStructureCompat) StructureLib.COMPAT).markTextureUsed(icon);
|
||||
|
||||
@@ -14,9 +14,12 @@ import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.keybind.SyncedKeybind;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage;
|
||||
import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage;
|
||||
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
@@ -64,6 +67,8 @@ public class CommonProxy {
|
||||
|
||||
public void preInit(FMLPreInitializationEvent e) {}
|
||||
|
||||
public void init(FMLInitializationEvent e) {}
|
||||
|
||||
public long getOverworldTime() {
|
||||
return MinecraftServer.getServer().getEntityWorld().getTotalWorldTime();
|
||||
}
|
||||
@@ -108,6 +113,16 @@ public class CommonProxy {
|
||||
}
|
||||
}
|
||||
|
||||
private static final SyncedKeybind MODE_SWAP_KEY = SyncedKeybind.createConfigurable(
|
||||
"item.structurelib.constructableTrigger.keys.cycleMode",
|
||||
"item.structurelib.constructableTrigger.keyCategory",
|
||||
0).registerGlobalListener((entityPlayerMP, syncedKeybind) -> {
|
||||
final ItemStack held = entityPlayerMP.getHeldItem();
|
||||
if (held != null && held.getItem() instanceof ItemConstructableTrigger) {
|
||||
ItemConstructableTrigger.cycleMode(held);
|
||||
}
|
||||
});
|
||||
|
||||
public void displayConfigGUI(String category) {}
|
||||
|
||||
public static class ForgeEventHandler {
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.gtnewhorizon.structurelib.util.XSTR;
|
||||
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.SidedProxy;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLInterModComms;
|
||||
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
@@ -128,6 +129,11 @@ public class StructureLib {
|
||||
DevelopHelper.onPreInit();
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void init(FMLInitializationEvent e) {
|
||||
proxy.init(e);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void loadComplete(FMLLoadCompleteEvent e) {
|
||||
proxy.loadComplete(e);
|
||||
|
||||
+8
-9
@@ -57,12 +57,12 @@ public class ConstructableUtility {
|
||||
}
|
||||
|
||||
IConstructable constructable = null;
|
||||
if (tTileEntity instanceof IConstructableProvider)
|
||||
constructable = ((IConstructableProvider) tTileEntity).getConstructable();
|
||||
else if (tTileEntity instanceof IConstructable) {
|
||||
constructable = (IConstructable) tTileEntity;
|
||||
if (tTileEntity instanceof IConstructableProvider aConstructableProvider)
|
||||
constructable = aConstructableProvider.getConstructable();
|
||||
else if (tTileEntity instanceof IConstructable aConstructable) {
|
||||
constructable = aConstructable;
|
||||
} else if (IMultiblockInfoContainer.contains(tTileEntity.getClass())) {
|
||||
ExtendedFacing facing = tTileEntity instanceof IAlignment ? ((IAlignment) tTileEntity).getExtendedFacing()
|
||||
ExtendedFacing facing = tTileEntity instanceof IAlignment alignment ? alignment.getExtendedFacing()
|
||||
: ExtendedFacing.of(ForgeDirection.getOrientation(aSide));
|
||||
constructable = IMultiblockInfoContainer.<TileEntity>get(tTileEntity.getClass())
|
||||
.toConstructable(tTileEntity, facing);
|
||||
@@ -70,14 +70,13 @@ public class ConstructableUtility {
|
||||
|
||||
if (constructable == null) return false;
|
||||
|
||||
if (aPlayer instanceof EntityPlayerMP) {
|
||||
EntityPlayerMP playerMP = (EntityPlayerMP) aPlayer;
|
||||
if (aPlayer instanceof EntityPlayerMP playerMP) {
|
||||
// server side and sneaking (already checked above)
|
||||
// do construct
|
||||
if (aPlayer.capabilities.isCreativeMode) {
|
||||
constructable.construct(aStack, false);
|
||||
} else if (constructable instanceof ISurvivalConstructable) {
|
||||
int built = ((ISurvivalConstructable) constructable).survivalConstruct(
|
||||
} else if (constructable instanceof ISurvivalConstructable aConstructable) {
|
||||
int built = aConstructable.survivalConstruct(
|
||||
aStack,
|
||||
ConfigurationHandler.INSTANCE.getAutoPlaceBudget(),
|
||||
ISurvivalBuildEnvironment.create(IItemSource.fromPlayer(playerMP), playerMP));
|
||||
|
||||
@@ -7,9 +7,14 @@ import static net.minecraft.util.StatCollector.translateToLocalFormatted;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagInt;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
@@ -20,12 +25,79 @@ import com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtilit
|
||||
|
||||
public class ItemConstructableTrigger extends Item {
|
||||
|
||||
private static final String TAG_MODE = "mode";
|
||||
|
||||
private static final IIcon[] textures = new IIcon[3];
|
||||
|
||||
public enum TriggerMode {
|
||||
BUILDING,
|
||||
UPDATING,
|
||||
REMOVING
|
||||
}
|
||||
|
||||
public ItemConstructableTrigger() {
|
||||
setUnlocalizedName("structurelib.constructableTrigger");
|
||||
setTextureName(MOD_ID + ":itemConstructableTrigger");
|
||||
setCreativeTab(StructureLib.creativeTab);
|
||||
}
|
||||
|
||||
public static void cycleMode(ItemStack held) {
|
||||
if (held.getTagCompound() == null) held.setTagCompound(new NBTTagCompound());
|
||||
if (!held.getTagCompound().hasKey(TAG_MODE)) held.getTagCompound().setTag(TAG_MODE, new NBTTagInt(0));
|
||||
held.getTagCompound().setInteger(TAG_MODE, (held.getTagCompound().getInteger(TAG_MODE) + 1) % 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIcons(IIconRegister register) {
|
||||
textures[0] = register.registerIcon(MOD_ID + ":constructableTrigger/BUILDING");
|
||||
textures[1] = register.registerIcon(MOD_ID + ":constructableTrigger/UPDATING");
|
||||
textures[2] = register.registerIcon(MOD_ID + ":constructableTrigger/REMOVING");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIcon getIcon(ItemStack stack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining) {
|
||||
return getIcon(stack, renderPass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIcon getIcon(ItemStack stack, int pass) {
|
||||
if (!stack.hasTagCompound() || !stack.getTagCompound().hasKey(TAG_MODE)) {
|
||||
return textures[0];
|
||||
}
|
||||
return textures[stack.getTagCompound().getInteger(TAG_MODE)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemStackDisplayName(ItemStack stack) {
|
||||
if (!stack.hasTagCompound() || !stack.getTagCompound().hasKey(TAG_MODE)) {
|
||||
return getDisplayName(0);
|
||||
}
|
||||
return getDisplayName(stack.getTagCompound().getInteger(TAG_MODE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIcon getIconIndex(ItemStack stack) {
|
||||
return getIcon(stack, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIcon getIconFromDamage(int damage) {
|
||||
return textures[damage];
|
||||
}
|
||||
|
||||
private String getDisplayName(int mode) {
|
||||
return StatCollector.translateToLocal("item.structurelib.constructableTrigger.name") + " - "
|
||||
+ StatCollector.translateToLocal("item.structurelib.constructableTrigger.modes." + mode);
|
||||
}
|
||||
|
||||
public static TriggerMode getMode(ItemStack held) {
|
||||
if (held == null || !held.hasTagCompound() || !held.getTagCompound().hasKey(TAG_MODE)) {
|
||||
// default behavior
|
||||
return TriggerMode.BUILDING;
|
||||
}
|
||||
// get user-defined mode
|
||||
return TriggerMode.values()[held.getTagCompound().getInteger(TAG_MODE)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) {
|
||||
if (!world.isRemote && getMovingObjectPositionFromPlayer(world, player, true) == null) {
|
||||
|
||||
@@ -348,77 +348,47 @@ public interface IStructureDefinition<T> {
|
||||
}
|
||||
|
||||
if (checkBlocksIfNotNullForceCheckAllIfTrue != null) {
|
||||
boolean success;
|
||||
if (checkBlocksIfNotNullForceCheckAllIfTrue) {
|
||||
success = StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
(e, w, x, y, z, a, b, c) -> e.check(object, w, x, y, z),
|
||||
"check");
|
||||
} else {
|
||||
success = StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
skipBlockUnloaded((e, w, x, y, z, a, b, c) -> e.check(object, w, x, y, z)),
|
||||
"check force");
|
||||
}
|
||||
boolean success = StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
checkBlocksIfNotNullForceCheckAllIfTrue ? (e, w, x, y, z, a, b, c) -> e.check(object, w, x, y, z)
|
||||
: skipBlockUnloaded((e, w, x, y, z, a, b, c) -> e.check(object, w, x, y, z)),
|
||||
checkBlocksIfNotNullForceCheckAllIfTrue ? "check" : "check force");
|
||||
if (StructureLibAPI.isDebugEnabled() && success) {
|
||||
StructureLib.LOGGER
|
||||
.info("Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] pass");
|
||||
}
|
||||
return success;
|
||||
} else {
|
||||
if (hintsOnly) {
|
||||
StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
ignoreBlockUnloaded((e, w, x, y, z, a, b, c) -> {
|
||||
e.spawnHint(object, world, x, y, z, trigger);
|
||||
if (ChannelDataAccessor.hasSubChannel(trigger, StructureLibAPI.CHANNEL_SHOW_ERROR)
|
||||
&& !e.couldBeValid(object, world, x, y, z, trigger)) {
|
||||
StructureLibAPI.markHintParticleError(StructureLib.getCurrentPlayer(), world, x, y, z);
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
"spawnHint");
|
||||
} else {
|
||||
StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
ignoreBlockUnloaded((e, w, x, y, z, a, b, c) -> {
|
||||
e.placeBlock(object, world, x, y, z, trigger);
|
||||
return true;
|
||||
}),
|
||||
"placeBlock");
|
||||
}
|
||||
StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
hintsOnly ? ignoreBlockUnloaded((e, w, x, y, z, a, b, c) -> {
|
||||
e.spawnHint(object, world, x, y, z, trigger);
|
||||
if (ChannelDataAccessor.hasSubChannel(trigger, "show_error")
|
||||
&& !e.couldBeValid(object, world, x, y, z, trigger)) {
|
||||
StructureLibAPI.markHintParticleError(StructureLib.getCurrentPlayer(), world, x, y, z);
|
||||
}
|
||||
return true;
|
||||
}) : ignoreBlockUnloaded((e, w, x, y, z, a, b, c) -> {
|
||||
e.placeBlock(object, world, x, y, z, trigger);
|
||||
return true;
|
||||
}),
|
||||
hintsOnly ? "spawnHint" : "placeBlock");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.LOGGER;
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.PANIC_MODE;
|
||||
import static com.gtnewhorizon.structurelib.item.ItemConstructableTrigger.TriggerMode.REMOVING;
|
||||
import static com.gtnewhorizon.structurelib.structure.StructureUtility.checkForRemoving;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -21,6 +23,7 @@ import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
|
||||
@@ -137,12 +140,14 @@ public interface IStructureElement<T> {
|
||||
*/
|
||||
default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
BlocksToPlace e = getBlocksToPlace(t, world, x, y, z, trigger, env);
|
||||
IItemSource source = env.getSource();
|
||||
EntityPlayer actor = env.getActor();
|
||||
Consumer<IChatComponent> chatter = env.getChatter();
|
||||
if (e != null) {
|
||||
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
|
||||
PlaceResult skipOrRejectBasedOnCheck = checkForRemoving(mode, check(t, world, x, y, z), world, x, y, z);
|
||||
if (skipOrRejectBasedOnCheck != PlaceResult.ACCEPT) return skipOrRejectBasedOnCheck;
|
||||
if (e.getStacks() == null) {
|
||||
ItemStack taken = source.takeOne(e.getPredicate(), true);
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
@@ -159,7 +164,7 @@ public interface IStructureElement<T> {
|
||||
chatter);
|
||||
}
|
||||
for (ItemStack stack : e.getStacks()) {
|
||||
if (!source.takeOne(stack, true)) continue;
|
||||
if (mode != REMOVING && !source.takeOne(stack, true)) continue;
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
stack,
|
||||
NBTMode.EXACT,
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.LOGGER;
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.PANIC_MODE;
|
||||
import static com.gtnewhorizon.structurelib.item.ItemConstructableTrigger.TriggerMode.BUILDING;
|
||||
import static com.gtnewhorizon.structurelib.item.ItemConstructableTrigger.TriggerMode.REMOVING;
|
||||
import static com.gtnewhorizon.structurelib.item.ItemConstructableTrigger.TriggerMode.UPDATING;
|
||||
import static java.lang.Integer.MIN_VALUE;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -28,6 +31,7 @@ import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -51,13 +55,16 @@ import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
import com.gtnewhorizon.structurelib.structure.IStructureElement.PlaceResult;
|
||||
import com.gtnewhorizon.structurelib.structure.adders.IBlockAdder;
|
||||
import com.gtnewhorizon.structurelib.structure.adders.ITileAdder;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
import com.gtnewhorizon.structurelib.xmod.ServerUtilitiesCompat;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
/**
|
||||
@@ -146,6 +153,8 @@ public class StructureUtility {
|
||||
|
||||
private static final String NICE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz=|!@#$%&()[]{};:<>/?_,.*^'`";
|
||||
|
||||
private static final boolean isSULoaded = Loader.isModLoaded("serverutilities");
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final Map<Vec3Impl, IStructureNavigate> STEP = new HashMap<>();
|
||||
|
||||
@@ -206,7 +215,11 @@ public class StructureUtility {
|
||||
|
||||
@Override
|
||||
public boolean placeBlock(Object o, World world, int x, int y, int z, ItemStack trigger) {
|
||||
world.setBlock(x, y, z, StructureLibAPI.getBlockHint(), 14, 2);
|
||||
placeRemoveOrUpdate(
|
||||
trigger,
|
||||
() -> world.setBlock(x, y, z, StructureLibAPI.getBlockHint(), 14, 2),
|
||||
() -> world.setBlock(x, y, z, StructureLibAPI.getBlockHint(), 14, 2),
|
||||
() -> world.setBlock(x, y, z, Blocks.air, 0, 2));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -219,11 +232,16 @@ public class StructureUtility {
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(Object o, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
if (check(o, world, x, y, z)) return PlaceResult.SKIP;
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
if (mode != REMOVING && check(o, world, x, y, z)) return PlaceResult.SKIP;
|
||||
// user should place anything here.
|
||||
// maybe make this configurable, but for now we try to take some cobble from user
|
||||
if (env.getSource().takeOne(new ItemStack(Blocks.cobblestone), false)) {
|
||||
world.setBlock(x, y, z, Blocks.cobblestone, 0, 2);
|
||||
placeRemoveOrUpdate(
|
||||
trigger,
|
||||
() -> world.setBlock(x, y, z, Blocks.cobblestone, 0, 2),
|
||||
() -> world.setBlock(x, y, z, Blocks.cobblestone, 0, 2),
|
||||
() -> world.setBlock(x, y, z, Blocks.air, 0, 2));
|
||||
}
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
@@ -330,29 +348,84 @@ public class StructureUtility {
|
||||
public static PlaceResult survivalPlaceBlock(Block block, int meta, World world, int x, int y, int z, IItemSource s,
|
||||
EntityPlayer actor, Consumer<IChatComponent> chatter) {
|
||||
if (block == null) throw new NullPointerException();
|
||||
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT;
|
||||
ItemConstructableTrigger.TriggerMode mode = BUILDING;
|
||||
if (actor.getHeldItem() != null && actor.getHeldItem().getItem() instanceof ItemConstructableTrigger) {
|
||||
// best effort lookup if the item in the player's hand is a trigger, and if it is, get the mode from the
|
||||
// ...trigger instead of assuming default behavior
|
||||
mode = ItemConstructableTrigger.getMode(actor.getHeldItem());
|
||||
}
|
||||
if (mode == BUILDING && !StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor))
|
||||
return PlaceResult.REJECT;
|
||||
if (mode == UPDATING) {
|
||||
if (!world.isAirBlock(x, y, z)) {
|
||||
if (world.getTileEntity(x, y, z) instanceof TileEntity) {
|
||||
// We're in updating mode and the block we're looking at might be important, so let's just leave it
|
||||
// alone
|
||||
// since it's probably not something we want to replace with something else
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
Block blockInWorld = world.getBlock(x, y, z);
|
||||
if (blockInWorld.isAssociatedBlock(block) && blockInWorld.getDamageValue(world, x, y, z) == meta) {
|
||||
// This is the block we are looking for, move along
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
Item itemBlock = Item.getItemFromBlock(block);
|
||||
int itemMeta = itemBlock instanceof ISpecialItemBlock
|
||||
? ((ISpecialItemBlock) itemBlock).getItemMetaFromBlockMeta(block, meta)
|
||||
: meta;
|
||||
ItemStack stack = new ItemStack(itemBlock, 1, itemMeta);
|
||||
if (!s.takeOne(stack, true)) {
|
||||
if (chatter != null) chatter.accept(
|
||||
new ChatComponentTranslation(
|
||||
"structurelib.autoplace.error.no_simple_block",
|
||||
stack.func_151000_E()));
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
if (block instanceof ICustomBlockSetting) {
|
||||
ICustomBlockSetting blockCustom = (ICustomBlockSetting) block;
|
||||
blockCustom.setBlock(world, x, y, z, meta);
|
||||
} else if (!stack.copy()
|
||||
.tryPlaceItemIntoWorld(actor, world, x, y, z, ForgeDirection.UP.ordinal(), 0.5f, 0.5f, 0.5f)) {
|
||||
if (mode != REMOVING) {
|
||||
if (!s.takeOne(stack, true)) {
|
||||
if (chatter != null) chatter.accept(
|
||||
new ChatComponentTranslation(
|
||||
"structurelib.autoplace.error.no_simple_block",
|
||||
stack.func_151000_E()));
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
if (block instanceof ICustomBlockSetting) {
|
||||
ICustomBlockSetting blockCustom = (ICustomBlockSetting) block;
|
||||
blockCustom.setBlock(world, x, y, z, meta);
|
||||
} else {
|
||||
if (mode == UPDATING && !world.isAirBlock(x, y, z) && checkPermission(world, actor, x, y, z)) {
|
||||
// We're in updating mode and there's a block in our way (grr), so let's remove whatever is there
|
||||
// ...and drop it to the player
|
||||
ItemStack toGive = new ItemStack(world.getBlock(x, y, z));
|
||||
toGive.setItemDamage(world.getBlock(x, y, z).getDamageValue(world, x, y, z));
|
||||
if (!world.setBlock(x, y, z, Blocks.air, 0, 4) || !tryGiveOrDropItem(world, actor, toGive)) {
|
||||
// We either weren't able to give the player the block that was there, or we weren't able to
|
||||
// remove
|
||||
// the block, either way, we need to reject the update. Also, since we hid the block update from
|
||||
// the client in an effort to make the exchange as seamless as possible, we need to now notify
|
||||
// the client if we did successfully remove the block.
|
||||
if (world.isAirBlock(x, y, z)) world.notifyBlockChange(x, y, z, Blocks.air);
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
}
|
||||
if (!stack.copy()
|
||||
.tryPlaceItemIntoWorld(actor, world, x, y, z, ForgeDirection.UP.ordinal(), 0.5f, 0.5f, 0.5f)) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
if (!s.takeOne(stack, false)) {
|
||||
// rollback
|
||||
}
|
||||
}
|
||||
if (mode == REMOVING || !s.takeOne(stack, false)) {
|
||||
// If we're in removing mode, or if the user didn't have the block in their inventory, and we're in some
|
||||
// other mode, let's check some stuff
|
||||
if (world.isAirBlock(x, y, z)) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
ItemStack toGive = new ItemStack(world.getBlock(x, y, z));
|
||||
toGive.setItemDamage(world.getBlock(x, y, z).getDamageValue(world, x, y, z));
|
||||
if (mode == REMOVING && !checkPermission(world, actor, x, y, z)) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
world.setBlockToAir(x, y, z);
|
||||
if (mode == REMOVING && !tryGiveOrDropItem(world, actor, toGive)) {
|
||||
// We're in removing mode and something went wrong while trying to give the player the block we removed,
|
||||
// let's just fail for now
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
}
|
||||
return PlaceResult.ACCEPT;
|
||||
}
|
||||
@@ -444,24 +517,82 @@ public class StructureUtility {
|
||||
if (stack == null) throw new NullPointerException();
|
||||
if (stack.stackSize != 1) throw new IllegalArgumentException();
|
||||
if (!(stack.getItem() instanceof ItemBlock)) throw new IllegalArgumentException();
|
||||
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT;
|
||||
if (!assumeStackPresent && !s.takeOne(stack, true)) {
|
||||
if (chatter != null) chatter.accept(
|
||||
new ChatComponentTranslation("structurelib.autoplace.error.no_item_stack", stack.func_151000_E()));
|
||||
return PlaceResult.REJECT;
|
||||
ItemConstructableTrigger.TriggerMode mode = BUILDING;
|
||||
if (actor.getHeldItem() != null && actor.getHeldItem().getItem() instanceof ItemConstructableTrigger) {
|
||||
// best effort lookup if the item in the player's hand is a trigger, and if it is, get the mode from the
|
||||
// ...trigger instead of assuming default behavior
|
||||
mode = ItemConstructableTrigger.getMode(actor.getHeldItem());
|
||||
}
|
||||
if (!stack.copy().tryPlaceItemIntoWorld(actor, world, x, y, z, ForgeDirection.UP.ordinal(), 0.5f, 0.5f, 0.5f))
|
||||
return PlaceResult.REJECT;
|
||||
if (!s.takeOne(stack, false))
|
||||
// this is bad! probably an exploit somehow. Let's nullify the block we just placed instead
|
||||
if (mode != REMOVING) {
|
||||
if (mode == BUILDING) {
|
||||
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
}
|
||||
if (mode == UPDATING) {
|
||||
if (!world.isAirBlock(x, y, z)) {
|
||||
if (world.getTileEntity(x, y, z) instanceof TileEntity) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
Block blockInWorld = world.getBlock(x, y, z);
|
||||
ItemStack blockInWorldItem = new ItemStack(blockInWorld);
|
||||
blockInWorldItem.setItemDamage(blockInWorld.getDamageValue(world, x, y, z));
|
||||
if (blockInWorldItem.isItemEqual(stack)) {
|
||||
// This is the block we are looking for, move along
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!assumeStackPresent && !s.takeOne(stack, true)) {
|
||||
if (chatter != null) chatter.accept(
|
||||
new ChatComponentTranslation(
|
||||
"structurelib.autoplace.error.no_item_stack",
|
||||
stack.func_151000_E()));
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
if (mode == UPDATING && !world.isAirBlock(x, y, z) && checkPermission(world, actor, x, y, z)) {
|
||||
// We're in updating mode and there's a block in our way (grr), so let's remove whatever is there
|
||||
// ...and drop it to the player
|
||||
ItemStack toGive = new ItemStack(world.getBlock(x, y, z));
|
||||
toGive.setItemDamage(world.getBlock(x, y, z).getDamageValue(world, x, y, z));
|
||||
if (!world.setBlock(x, y, z, Blocks.air, 0, 4) || !tryGiveOrDropItem(world, actor, toGive)) {
|
||||
// We either weren't able to give the player the block that was there, or we weren't able to remove
|
||||
// the block, either way, we need to reject the update. Also, since we hid the block update from
|
||||
// the client in an effort to make the exchange as seamless as possible, we need to now notify
|
||||
// the client if we did successfully remove the block.
|
||||
if (world.isAirBlock(x, y, z)) world.notifyBlockChange(x, y, z, Blocks.air);
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
}
|
||||
if (!stack.copy()
|
||||
.tryPlaceItemIntoWorld(actor, world, x, y, z, ForgeDirection.UP.ordinal(), 0.5f, 0.5f, 0.5f)) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
}
|
||||
if (mode == REMOVING || !s.takeOne(stack, false)) {
|
||||
if (world.isAirBlock(x, y, z)) {
|
||||
return PlaceResult.SKIP;
|
||||
}
|
||||
// If the user didn't have the item in their inventory, or we're in removing mode, we set it to air
|
||||
ItemStack toGive = new ItemStack(world.getBlock(x, y, z));
|
||||
toGive.setItemDamage(world.getBlock(x, y, z).getDamageValue(world, x, y, z));
|
||||
if (mode == REMOVING && !checkPermission(world, actor, x, y, z)) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
world.setBlockToAir(x, y, z);
|
||||
if (mode == REMOVING && !tryGiveOrDropItem(world, actor, toGive)) {
|
||||
// We were in removing mode and something went wrong while trying to give the player the block we
|
||||
// ...removed, let's just fail for now
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
}
|
||||
return PlaceResult.ACCEPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a structure element that only allow air (or air equivalents, like Railcraft hidden blocks). You usually
|
||||
* don't need to call this yourselves. Use {@code -} in shape to automatically use this. Provided nontheless in case
|
||||
* you want this as a fallback to something else.
|
||||
* don't need to call this yourselves. Use {@code -} in shape to automatically use this. Provided nonetheless in
|
||||
* case you want this as a fallback to something else.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> IStructureElement<T> isAir() {
|
||||
@@ -470,8 +601,8 @@ public class StructureUtility {
|
||||
|
||||
/**
|
||||
* Return a structure element that allow anything but air (or air equivalents, like Railcraft hidden blocks). You
|
||||
* usually don't need to call this yourselves. Use {@code +} in shape to automatically use this. Provided nontheless
|
||||
* in case you want this as a fallback to something else.
|
||||
* usually don't need to call this yourselves. Use {@code +} in shape to automatically use this. Provided
|
||||
* nonetheless in case you want this as a fallback to something else.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> IStructureElement<T> notAir() {
|
||||
@@ -637,7 +768,7 @@ public class StructureUtility {
|
||||
* given tier, then player will be allowed to use multiple kinds of blocks, but their tier is guaranteed to be the
|
||||
* same.
|
||||
* <p>
|
||||
* <h3>WARNING</h3> <b>You SHOULD NOT return notSet from your tierExtractor.</b> If you do so, we will have this
|
||||
* <h4>WARNING</h4> <b>You SHOULD NOT return notSet from your tierExtractor.</b> If you do so, we will have this
|
||||
* chain of events:
|
||||
* <ul>
|
||||
* <li>at check start, tier is reset to notSet
|
||||
@@ -650,7 +781,7 @@ public class StructureUtility {
|
||||
* doing its business
|
||||
* <li>Player enjoy a (probably) hilariously shaped multi and (probably) reduced build cost.
|
||||
* </ul>
|
||||
* <h3>Example Implementation</h3>
|
||||
* <h4>Example Implementation</h4>
|
||||
* <p>
|
||||
* Assume you have 16 tier, each map to one particular block's 16 different meta. You will usually want something
|
||||
* like this
|
||||
@@ -709,7 +840,7 @@ public class StructureUtility {
|
||||
List<Pair<Block, Integer>> hints = allKnownTiers == null ? Collections.emptyList() : allKnownTiers;
|
||||
if (hints.stream().anyMatch(Objects::isNull)) throw new IllegalArgumentException();
|
||||
IStructureElementCheckOnly<T> check = ofBlocksTiered(tierExtractor, notSet, setter, getter);
|
||||
return new StructureElement_Bridge<T>() {
|
||||
return new StructureElement_Bridge<>() {
|
||||
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
@@ -734,6 +865,11 @@ public class StructureUtility {
|
||||
return Objects.equals(hintTier, worldTier);
|
||||
}
|
||||
|
||||
private boolean isInAllKnownTiers(Block b) {
|
||||
return allKnownTiers != null
|
||||
&& allKnownTiers.stream().anyMatch(pair -> pair.getLeft().isAssociatedBlock(b));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
Pair<Block, Integer> hint = getHint(trigger);
|
||||
@@ -766,13 +902,17 @@ public class StructureUtility {
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
Pair<Block, Integer> hint = getHint(trigger);
|
||||
if (hint == null) return PlaceResult.REJECT; // TODO or SKIP?
|
||||
Block block = world.getBlock(x, y, z);
|
||||
int meta = world.getBlockMetadata(x, y, z);
|
||||
TIER tier = tierExtractor.convert(block, meta);
|
||||
if (Objects.equals(tier, tierExtractor.convert(hint.getKey(), hint.getValue())))
|
||||
if (mode != REMOVING && (Objects.equals(tier, tierExtractor.convert(hint.getKey(), hint.getValue()))))
|
||||
return PlaceResult.SKIP;
|
||||
if (mode == REMOVING && (!isInAllKnownTiers(block) && !world.isAirBlock(x, y, z))) {
|
||||
return PlaceResult.REJECT;
|
||||
}
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
hint.getKey(),
|
||||
hint.getValue(),
|
||||
@@ -861,7 +1001,9 @@ public class StructureUtility {
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
PlaceResult skipOrRejectBasedOnCheck = checkForRemoving(mode, check(t, world, x, y, z), world, x, y, z);
|
||||
if (skipOrRejectBasedOnCheck != PlaceResult.ACCEPT) return skipOrRejectBasedOnCheck;
|
||||
if (getBlock() == null) return PlaceResult.REJECT;
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
getBlock(),
|
||||
@@ -948,7 +1090,9 @@ public class StructureUtility {
|
||||
@Deprecated
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
IItemSource s, EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
PlaceResult skipOrRejectBasedOnCheck = checkForRemoving(mode, check(t, world, x, y, z), world, x, y, z);
|
||||
if (skipOrRejectBasedOnCheck != PlaceResult.ACCEPT) return skipOrRejectBasedOnCheck;
|
||||
if (init()) return StructureUtility.survivalPlaceBlock(block, meta, world, x, y, z, s, actor, chatter);
|
||||
return fallback.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
|
||||
}
|
||||
@@ -956,7 +1100,9 @@ public class StructureUtility {
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
PlaceResult skipOrRejectBasedOnCheck = checkForRemoving(mode, check(t, world, x, y, z), world, x, y, z);
|
||||
if (skipOrRejectBasedOnCheck != PlaceResult.ACCEPT) return skipOrRejectBasedOnCheck;
|
||||
if (init()) return StructureUtility.survivalPlaceBlock(
|
||||
block,
|
||||
meta,
|
||||
@@ -1584,8 +1730,15 @@ public class StructureUtility {
|
||||
@Deprecated
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
if (world.getBlock(x, y, z) == defaultBlock && world.getBlockMetadata(x, y, z) == defaultMeta)
|
||||
return PlaceResult.SKIP;
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
PlaceResult skipOrRejectBasedOnCheck = checkForRemoving(
|
||||
mode,
|
||||
world.getBlock(x, y, z) == defaultBlock && world.getBlockMetadata(x, y, z) == defaultMeta,
|
||||
world,
|
||||
x,
|
||||
y,
|
||||
z);
|
||||
if (skipOrRejectBasedOnCheck != PlaceResult.ACCEPT) return skipOrRejectBasedOnCheck;
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
defaultBlock,
|
||||
defaultMeta,
|
||||
@@ -1630,8 +1783,15 @@ public class StructureUtility {
|
||||
@Deprecated
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
if (world.getBlock(x, y, z) == defaultBlock && world.getBlockMetadata(x, y, z) == defaultMeta)
|
||||
return PlaceResult.SKIP;
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
PlaceResult skipOrRejectBasedOnCheck = checkForRemoving(
|
||||
mode,
|
||||
world.getBlock(x, y, z) == defaultBlock && world.getBlockMetadata(x, y, z) == defaultMeta,
|
||||
world,
|
||||
x,
|
||||
y,
|
||||
z);
|
||||
if (skipOrRejectBasedOnCheck != PlaceResult.ACCEPT) return skipOrRejectBasedOnCheck;
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
defaultBlock,
|
||||
defaultMeta,
|
||||
@@ -1890,6 +2050,7 @@ public class StructureUtility {
|
||||
@Deprecated
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
IItemSource s, EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
if (predicate.test(t))
|
||||
return downstream.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
|
||||
return placeResultWhenDisabled;
|
||||
@@ -1898,6 +2059,7 @@ public class StructureUtility {
|
||||
@Override
|
||||
public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
|
||||
AutoPlaceEnvironment env) {
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
if (predicate.test(t)) return downstream.survivalPlaceBlock(t, world, x, y, z, trigger, env);
|
||||
return placeResultWhenDisabled;
|
||||
}
|
||||
@@ -3265,4 +3427,57 @@ public class StructureUtility {
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a creation, removal, or update operation at the given position
|
||||
*
|
||||
* @param trigger ItemStack for the trigger item
|
||||
* @param onCreate Operation to be performed when the mode of the trigger is set to building mode
|
||||
* @param onUpdate Operation to be performed when the mode of the trigger is set to updating mode
|
||||
* @param onRemove Operation to be performed when the mode of the trigger is set to removing mode
|
||||
*/
|
||||
public static void placeRemoveOrUpdate(ItemStack trigger, Runnable onCreate, Runnable onUpdate, Runnable onRemove) {
|
||||
ItemConstructableTrigger.TriggerMode mode = ItemConstructableTrigger.getMode(trigger);
|
||||
switch (mode) {
|
||||
case BUILDING:
|
||||
onCreate.run();
|
||||
break;
|
||||
case UPDATING:
|
||||
onUpdate.run();
|
||||
break;
|
||||
case REMOVING:
|
||||
onRemove.run();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean tryGiveOrDropItem(World world, EntityPlayer actor, ItemStack stack) {
|
||||
if (actor.inventory.addItemStackToInventory(stack)) {
|
||||
actor.inventoryContainer.detectAndSendChanges();
|
||||
return true;
|
||||
}
|
||||
EntityItem toSpawn = new EntityItem(world, actor.posX, actor.posY, actor.posZ, stack);
|
||||
// For some reason these things sometimes spawn with the velocity of an F1 car, so let's prevent that
|
||||
toSpawn.motionX = 0;
|
||||
toSpawn.motionY = 0;
|
||||
toSpawn.motionZ = 0;
|
||||
return world.spawnEntityInWorld(toSpawn);
|
||||
}
|
||||
|
||||
public static boolean checkPermission(World world, EntityPlayer actor, int x, int y, int z) {
|
||||
boolean res = true;
|
||||
if (isSULoaded) {
|
||||
res = ServerUtilitiesCompat.checkPermission(world, actor, x, z);
|
||||
}
|
||||
res = res && !world.getBlock(x, y, z).isAssociatedBlock(Blocks.bedrock);
|
||||
// maybe check mining level who knows :shrug:
|
||||
return res;
|
||||
}
|
||||
|
||||
public static PlaceResult checkForRemoving(ItemConstructableTrigger.TriggerMode mode, boolean checkResult,
|
||||
World world, int x, int y, int z) {
|
||||
if (mode != REMOVING && checkResult) return PlaceResult.SKIP;
|
||||
else if (mode != BUILDING && !checkResult && !world.isAirBlock(x, y, z)) return PlaceResult.REJECT;
|
||||
return PlaceResult.ACCEPT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.gtnewhorizon.structurelib.xmod;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import serverutils.data.ClaimedChunks;
|
||||
import serverutils.lib.data.ForgePlayer;
|
||||
import serverutils.lib.data.ForgeTeam;
|
||||
import serverutils.lib.data.Universe;
|
||||
import serverutils.lib.math.ChunkDimPos;
|
||||
|
||||
public class ServerUtilitiesCompat {
|
||||
|
||||
@Optional.Method(modid = "serverutilities")
|
||||
public static boolean checkPermission(World world, EntityPlayer actor, int x, int z) {
|
||||
final ForgeTeam owningTeam = ClaimedChunks.instance
|
||||
.getChunkTeam(new ChunkDimPos(x >> 4, z >> 4, world.provider.dimensionId));
|
||||
if (owningTeam == null) {
|
||||
return true;
|
||||
}
|
||||
final ForgePlayer currentPlayer = new ForgePlayer(
|
||||
Universe.get(),
|
||||
actor.getUniqueID(),
|
||||
actor.getCommandSenderName());
|
||||
return owningTeam.isAlly(currentPlayer) || owningTeam.isMember(currentPlayer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,9 @@ item.structurelib.frontRotationTool.desc.1=Rotates only the front panel,
|
||||
item.structurelib.frontRotationTool.desc.2=which allows structure rotation.
|
||||
|
||||
item.structurelib.constructableTrigger.name=Multiblock Structure Hologram Projector
|
||||
item.structurelib.constructableTrigger.modes.0=Building Mode
|
||||
item.structurelib.constructableTrigger.modes.1=Updating Mode
|
||||
item.structurelib.constructableTrigger.modes.2=Removing Mode
|
||||
item.structurelib.constructableTrigger.desc.0=Triggers Constructable Interface
|
||||
item.structurelib.constructableTrigger.desc.1=Shows multiblock construction schematic,
|
||||
item.structurelib.constructableTrigger.desc.2=use on the multiblock controller.
|
||||
@@ -37,6 +40,12 @@ item.structurelib.constructableTrigger.gui.add=Add
|
||||
item.structurelib.constructableTrigger.gui.set=Set
|
||||
item.structurelib.constructableTrigger.gui.unset=Unset
|
||||
item.structurelib.constructableTrigger.gui.wipe=§4Wipe
|
||||
item.structurelib.constructableTrigger.gui.error.show=Show Errors
|
||||
item.structurelib.constructableTrigger.gui.error.hide=Hide Errors
|
||||
item.structurelib.constructableTrigger.gui.gt_no_hatch.enable=No Hatch
|
||||
item.structurelib.constructableTrigger.gui.gt_no_hatch.disable=Hatches
|
||||
item.structurelib.constructableTrigger.keyCategory=Multiblock Structure Hologram Projector Keys
|
||||
item.structurelib.constructableTrigger.keys.cycleMode=Cycle Projector Mode
|
||||
item.structurelib.constructableTrigger.gui.channels.from=§rMod: §9§o%s
|
||||
item.structurelib.constructableTrigger.gui.info=Many multiblocks support some degree of variation in its structure and use sub channels to indicate which variant to use.\n Sub channels are has a sequence of lower case characters as key and a positive integer as value. Most known sub channels should be available as typeahead completions.\nYou can also drag and drop items from NEI to set the corresponding sub channel value. These items all have a tooltip of §oIndicates value X for sub channel Y§r.
|
||||
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 386 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 392 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 365 B |
Binary file not shown.
|
Before Width: | Height: | Size: 667 B |
Reference in new issue
Block a user