Compare commits

..
10 Commits
Author SHA1 Message Date
Martin Robertz 3cbd6cf581 update 2025-04-12 23:09:52 +02:00
Martin Robertz 9d06da9b3b fix 2025-04-12 11:22:49 +02:00
Martin Robertz 88d5991161 update 2025-04-12 11:17:31 +02:00
Martin Robertz cce7372675 Merge remote-tracking branch 'origin/feature/channel-desc' into dev
# Conflicts:
#	dependencies.gradle
#	src/main/java/com/gtnewhorizon/structurelib/StructureLib.java
#	src/main/java/com/gtnewhorizon/structurelib/StructureLibAPI.java
#	src/main/java/com/gtnewhorizon/structurelib/gui/GuiScreenConfigureChannels.java
#	src/main/java/com/gtnewhorizon/structurelib/structure/IStructureDefinition.java
#	src/main/resources/assets/structurelib/lang/en_US.lang
#	src/main/resources/assets/structurelib/lang/zh_CN.lang
#	src/main/resources/assets/structurelib/textures/gui/channels.png
2025-04-12 11:16:46 +02:00
Glease 24403a82ce spotless
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
2025-04-11 17:15:54 +08:00
Glease b775c1068d add gui tutorial and remove debug code
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
2025-04-11 17:11:00 +08:00
Glease 6a557c9aa0 bruh
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
2025-04-08 14:53:47 +08:00
Glease 14d7219b41 change NEI to a implementation dependency
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
2025-04-08 14:46:12 +08:00
Glease faa3e75ed1 spotless
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
2025-04-08 14:34:32 +08:00
Glease df96277bd7 add channel desc and channel indicator item
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
2025-04-08 14:32:10 +08:00
20 changed files with 220 additions and 128 deletions

No files matched your search

View File
File mode changed.
+5 -3
View File
@@ -1,13 +1,15 @@
// Add your dependencies here
dependencies {
api("com.github.GTNewHorizons:GTNHLib:0.6.31:dev")
implementation("com.github.GTNewHorizons:NotEnoughItems:2.7.56-GTNH:dev")
api("com.github.GTNewHorizons:GTNHLib:0.6.19:dev")
implementation("com.github.GTNewHorizons:NotEnoughItems:2.7.38-GTNH:dev")
compileOnly("com.github.GTNewHorizons:ServerUtilities:2.1.41-pre")
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") {
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.234:dev") {
// exclude group: "com.github.GTNewHorizons", module: "StructureLib"
// }
}
+1 -1
View File
@@ -37,7 +37,7 @@ remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/co
# Select a default username for testing your mod. You can always override this per-run by running
# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE.
developmentEnvironmentUserName = Developer
developmentEnvironmentUserName = "Developer"
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
# See https://github.com/bsideup/jabel for details on how this works.
Vendored Executable → Regular
View File
File mode changed.
-1
View File
@@ -1,5 +1,4 @@
// Add any additional repositiroes for your dependencies here
repositories {
mavenLocal()
}
@@ -20,6 +20,7 @@ import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.culling.Frustrum;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
@@ -42,17 +43,23 @@ import org.lwjgl.opengl.GL11;
import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX;
import com.gtnewhorizon.structurelib.net.RegistryOrderSyncMessage;
import com.gtnewhorizon.structurelib.net.SetChannelDataMessage;
import com.gtnewhorizon.structurelib.net.StructureProjectorCycleModeMessage;
import cpw.mods.fml.client.config.GuiConfig;
import cpw.mods.fml.client.event.ConfigChangedEvent;
import cpw.mods.fml.client.registry.ClientRegistry;
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;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent;
import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.common.network.FMLNetworkEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class ClientProxy extends CommonProxy {
@@ -259,6 +266,13 @@ public class ClientProxy extends CommonProxy {
MinecraftForge.EVENT_BUS.register(new ForgeEventHandler());
}
@Override
public void init(FMLInitializationEvent e) {
super.init(e);
MinecraftForge.EVENT_BUS.register(new KeybindHandler());
}
static void markTextureUsed(IIcon icon) {
if (StructureLib.COMPAT instanceof IStructureCompat)
((IStructureCompat) StructureLib.COMPAT).markTextureUsed(icon);
@@ -654,4 +668,30 @@ public class ClientProxy extends CommonProxy {
p.endSection();
}
}
public static class KeybindHandler {
private static final KeyBinding CYCLE_PROJECTOR_MODE = new KeyBinding(
"item.structurelib.constructableTrigger.keys.cycleMode",
0,
"item.structurelib.constructableTrigger.keyCategory");
public KeybindHandler() {
FMLCommonHandler.instance().bus().register(this);
// If somebody wants to make a UI element for this, be my guest
ClientRegistry.registerKeyBinding(CYCLE_PROJECTOR_MODE);
}
@SideOnly(Side.CLIENT)
@SubscribeEvent
public void key(InputEvent.KeyInputEvent event) {
if (CYCLE_PROJECTOR_MODE.isPressed()) {
cycleProjectorMode();
}
}
private static void cycleProjectorMode() {
StructureLib.net.sendToServer(new StructureProjectorCycleModeMessage());
}
}
}
@@ -14,11 +14,10 @@ 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;
@@ -66,6 +65,8 @@ public class CommonProxy {
public void preInit(FMLPreInitializationEvent e) {}
public void init(FMLInitializationEvent e) {}
public long getOverworldTime() {
return MinecraftServer.getServer().getEntityWorld().getTotalWorldTime();
}
@@ -110,16 +111,6 @@ 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 {
@@ -1,12 +1,8 @@
package com.gtnewhorizon.structurelib;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
public interface IStructureCompat {
void markTextureUsed(IIcon o);
boolean checkServerUtilitiesPermission(World world, EntityPlayer actor, int x, int z);
}
@@ -27,12 +27,14 @@ import com.gtnewhorizon.structurelib.net.AlignmentMessage;
import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage;
import com.gtnewhorizon.structurelib.net.RegistryOrderSyncMessage;
import com.gtnewhorizon.structurelib.net.SetChannelDataMessage;
import com.gtnewhorizon.structurelib.net.StructureProjectorCycleModeMessage;
import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage;
import com.gtnewhorizon.structurelib.util.InventoryUtility;
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;
@@ -77,6 +79,11 @@ public class StructureLib {
net.registerMessage(SetChannelDataMessage.Handler.class, SetChannelDataMessage.class, 3, Side.SERVER);
net.registerMessage(ErrorHintParticleMessage.Handler.class, ErrorHintParticleMessage.class, 4, Side.CLIENT);
net.registerMessage(RegistryOrderSyncMessage.Handler.class, RegistryOrderSyncMessage.class, 5, Side.SERVER);
net.registerMessage(
StructureProjectorCycleModeMessage.Handler.class,
StructureProjectorCycleModeMessage.class,
6,
Side.SERVER);
try {
DEBUG_MODE = Boolean.parseBoolean(System.getProperty("structurelib.debug"));
@@ -92,7 +99,7 @@ public class StructureLib {
@Mod.Instance
static StructureLib INSTANCE;
@Mod.Instance(STRUCTURECOMPAT_MODID)
public static Object COMPAT;
static Object COMPAT;
static Block blockHint;
static Item itemBlockHint;
@@ -128,6 +135,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);
@@ -9,7 +9,10 @@ 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;
@@ -20,15 +23,29 @@ import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
import com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility;
public class ItemConstructableTrigger extends ModeToggleableItem {
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");
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");
@@ -72,6 +89,15 @@ public class ItemConstructableTrigger extends ModeToggleableItem {
+ 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) {
@@ -1,32 +0,0 @@
package com.gtnewhorizon.structurelib.item;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagInt;
public class ModeToggleableItem extends Item {
public enum TriggerMode {
BUILDING,
UPDATING,
REMOVING
}
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)];
}
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);
}
protected static final String TAG_MODE = "mode";
}
@@ -0,0 +1,37 @@
package com.gtnewhorizon.structurelib.net;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
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 StructureProjectorCycleModeMessage implements IMessage {
@Override
public void fromBytes(ByteBuf buf) {
// no op
}
@Override
public void toBytes(ByteBuf buf) {
// no op
}
public static class Handler implements IMessageHandler<StructureProjectorCycleModeMessage, IMessage> {
@Override
public IMessage onMessage(StructureProjectorCycleModeMessage message, MessageContext ctx) {
EntityPlayerMP player = ctx.getServerHandler().playerEntity;
final ItemStack held = player.getHeldItem();
if (held != null && held.getItem() instanceof ItemConstructableTrigger) {
ItemConstructableTrigger.cycleMode(held);
}
return null;
}
}
}
@@ -379,7 +379,7 @@ public interface IStructureDefinition<T> {
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")
if (ChannelDataAccessor.hasSubChannel(trigger, StructureLibAPI.CHANNEL_SHOW_ERROR)
&& !e.couldBeValid(object, world, x, y, z, trigger)) {
StructureLibAPI.markHintParticleError(StructureLib.getCurrentPlayer(), world, x, y, z);
}
@@ -2,7 +2,7 @@ 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.ModeToggleableItem.TriggerMode.REMOVING;
import static com.gtnewhorizon.structurelib.item.ItemConstructableTrigger.TriggerMode.REMOVING;
import static com.gtnewhorizon.structurelib.structure.StructureUtility.checkForRemoving;
import java.util.Arrays;
@@ -2,12 +2,31 @@ 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.ModeToggleableItem.TriggerMode.*;
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.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.*;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import javax.annotation.Nullable;
@@ -31,7 +50,6 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.collect.ImmutableList;
import com.gtnewhorizon.structurelib.IStructureCompat;
import com.gtnewhorizon.structurelib.StructureEvent.StructureElementVisitedEvent;
import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.StructureLibAPI;
@@ -44,7 +62,9 @@ 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;
/**
@@ -133,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<>();
@@ -387,31 +409,23 @@ public class StructureUtility {
}
}
}
if (mode == REMOVING) {
// We're in removing mode, so 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 (!checkPermission(world, actor, x, y, z)) {
return PlaceResult.REJECT;
}
world.setBlockToAir(x, y, z);
if (!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;
}
} else if (!s.takeOne(stack, false)) {
// If the user didn't have the block in their inventory, and we're in some
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;
}
@@ -555,30 +569,22 @@ public class StructureUtility {
return PlaceResult.REJECT;
}
}
if (mode == REMOVING) {
if (mode == REMOVING || !s.takeOne(stack, false)) {
if (world.isAirBlock(x, y, z)) {
return PlaceResult.SKIP;
}
// If we're in removing mode, we set it to air
// 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 (!checkPermission(world, actor, x, y, z)) {
if (mode == REMOVING && !checkPermission(world, actor, x, y, z)) {
return PlaceResult.REJECT;
}
world.setBlockToAir(x, y, z);
if (!tryGiveOrDropItem(world, actor, toGive)) {
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;
}
} else if (!s.takeOne(stack, false)) {
if (world.isAirBlock(x, y, z)) {
return PlaceResult.SKIP;
}
// If the user didn't have the item in their inventory, 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));
world.setBlockToAir(x, y, z);
}
return PlaceResult.ACCEPT;
}
@@ -762,20 +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>
* <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
* <li>the tier extractor returns notSet for first block, so since ofBlocksTiered finds your current tier is notSet,
* and the new block's tier is the same as that, so it's accepted
* <li>at 2nd, 3rd..., same thing in 2 happens
* <li>at last occurrence, player placed a valid block with a tier not notSet. ofBlocksTiered now sets your current
* tier to this tier, and accept the block
* <li>check got notified structure is sound, and tier is not notSet. it marks the structure as complete and start
* doing its business
* <li>Player enjoy a (probably) hilariously shaped multi and (probably) reduced build cost.
* </ul>
* <h4>Example Implementation</h4>
* <b>Example Implementation:</b>
* <p>
* Assume you have 16 tier, each map to one particular block's 16 different meta. You will usually want something
* like this
@@ -802,7 +795,7 @@ public class StructureUtility {
* }
* </pre>
*
* Important bits of this example implementation:
* Important bits:
* <ul>
* <li>The supplied ITierConverter returns null for an invalid block</li>
* <li>Possible tier returned by ITierConverter is Integer object 0 to 15.</li>
@@ -811,8 +804,19 @@ public class StructureUtility {
* <li>notSet is never a tier returned by ITierConverter.</li>
* </ul>
* <p>
* As a friendly reminder, the above characteristics are only for this simply demo, not as a general restriction
* imposed by ofBlocksTiered.
* <p>
* <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
* <li>the tier extractor returns notSet for first block, so since ofBlocksTiered finds your current tier is notSet,
* and the new block's tier is the same as that, so it's accepted
* <li>at 2nd, 3rd..., same thing in 2 happens
* <li>at last occurrence, player placed a valid block with a tier not notSet. ofBlocksTiered now sets your current
* tier to this tier, and accept the block
* <li>check got notified structure is sound, and tier is not notSet. it marks the structure as complete and start
* doing its business
* <li>Player enjoy a (probably) hilariously shaped multi and (probably) reduced build cost.
* </ul>
*
* @param tierExtractor a function to extract tier info from a block. This function can return null and will never
* be passed a null block or an invalid block meta. If this function returns null, then the
@@ -902,14 +906,10 @@ public class StructureUtility {
Block block = world.getBlock(x, y, z);
int meta = world.getBlockMetadata(x, y, z);
TIER tier = tierExtractor.convert(block, meta);
if (mode == REMOVING) {
if (!isInAllKnownTiers(block) && !world.isAirBlock(x, y, z)) {
return PlaceResult.REJECT;
}
} else {
if ((Objects.equals(tier, tierExtractor.convert(hint.getKey(), hint.getValue())))) {
return PlaceResult.SKIP;
}
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(),
@@ -2048,6 +2048,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;
@@ -2056,6 +2057,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;
}
@@ -3462,8 +3464,8 @@ public class StructureUtility {
public static boolean checkPermission(World world, EntityPlayer actor, int x, int y, int z) {
boolean res = true;
if (StructureLib.COMPAT instanceof IStructureCompat isc) {
res = isc.checkServerUtilitiesPermission(world, actor, x, z);
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:
@@ -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);
}
}
-10
View File
@@ -133,16 +133,6 @@ StructureLib API documentation.
Usually there is no reason to reimplement this on your own.
</p>
<h2>{@link com.gtnewhorizon.structurelib.item.ModeToggleableItem}</h2>
<p>
This class is the base class for {@link com.gtnewhorizon.structurelib.item.ItemConstructableTrigger} that defines
the <code>TriggerMode</code>s for the {@link com.gtnewhorizon.structurelib.item.ItemConstructableTrigger}. There are
3 modes, <code>BUILDING</code>, <code>UPDATING</code>, and <code>REMOVING</code>. Each of these modes does as they
say, where building will build a new multi from scratch, updating will remove existing an existing structure and
replace it with new components (think upgrading glass on a multi, changing from a tier 1 to tier 2 of a multi, etc),
and removing will just straight up remove the multi.
</p>
<h2><a href="#channels" id="channels">Channels</a></h2>
<p>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 724 B