Files
StructureLib/src/main/java/com/gtnewhorizon/structurelib/StructureLibAPI.java
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

388 lines
17 KiB
Java
Raw Normal View History

2021-05-29 19:05:50 +08:00
package com.gtnewhorizon.structurelib;
2022-08-08 17:40:12 +08:00
import static com.gtnewhorizon.structurelib.StructureLib.proxy;
2021-05-29 19:05:50 +08:00
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
2021-05-29 19:05:50 +08:00
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
2022-09-02 15:45:13 +08:00
import net.minecraft.util.IChatComponent;
2021-05-29 19:05:50 +08:00
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
2025-04-08 14:34:32 +08:00
import com.gtnewhorizon.gtnhlib.util.AnimatedTooltipHandler;
2022-08-30 23:27:18 +08:00
import com.gtnewhorizon.structurelib.alignment.IAlignment;
2021-05-29 19:05:50 +08:00
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
2022-08-08 17:40:12 +08:00
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
2022-09-11 02:54:11 +08:00
import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
2022-09-15 15:58:17 +08:00
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
2024-01-09 03:42:10 +00:00
2021-05-29 19:05:50 +08:00
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.
*/
2021-05-29 19:05:50 +08:00
public class StructureLibAPI {
2022-07-08 17:14:18 +08:00
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;
public static final int HINT_BLOCK_META_GENERIC_2 = 2;
public static final int HINT_BLOCK_META_GENERIC_3 = 3;
public static final int HINT_BLOCK_META_GENERIC_4 = 4;
public static final int HINT_BLOCK_META_GENERIC_5 = 5;
public static final int HINT_BLOCK_META_GENERIC_6 = 6;
public static final int HINT_BLOCK_META_GENERIC_7 = 7;
public static final int HINT_BLOCK_META_GENERIC_8 = 8;
public static final int HINT_BLOCK_META_GENERIC_9 = 9;
public static final int HINT_BLOCK_META_GENERIC_10 = 10;
public static final int HINT_BLOCK_META_GENERIC_11 = 11;
public static final int HINT_BLOCK_META_DEFAULT = 12;
public static final int HINT_BLOCK_META_AIR = 13;
public static final int HINT_BLOCK_META_NOT_AIR = 14;
public static final int HINT_BLOCK_META_ERROR = 15;
2025-04-08 14:32:10 +08:00
public static final String CHANNEL_SHOW_ERROR = "show_error";
2022-09-15 15:58:17 +08:00
static final ThreadLocal<Object> instrument = new ThreadLocal<>();
/**
* Start instrumenting <b>for the current thread only</b>. When instrumentation is enabled,
* {@link IStructureDefinition}'s builtin iteration methods will send {@link StructureEvent} and its subclasses when
* 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
* <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>
* </ul>
* <p>
* It's an API abuse for normal {@link IStructureDefinition} users to depend on this feature. They have full control
* and full knowledge of the {@link IStructureDefinition} they are using. Using events to instrument the structure
* check/autoplace is completely unnecessary and does nothing but add overhead.
* <p>
* Instruments are required to call {@link #disableInstrument()} whenever it is done with its business, as there can
* be only one instrument for any given thread.
*
* @param identifier an identifier sent along the actual event.
* @throws IllegalStateException if instrument has already been enabled.
*/
public static void enableInstrument(Object identifier) {
if (isInstrumentEnabled()) throw new IllegalStateException();
instrument.set(identifier);
2022-09-15 15:58:17 +08:00
}
/**
* Stop instrumenting.
*
* @throws IllegalStateException if instrumenting hasn't been enabled.
*/
public static void disableInstrument() {
if (!isInstrumentEnabled()) throw new IllegalStateException();
instrument.set(null);
}
/**
* Check if instrumenting is enabled.
2023-02-11 01:25:16 +08:00
*
2022-09-15 15:58:17 +08:00
* @return true if enabled, false otherwise
*/
public static boolean isInstrumentEnabled() {
return instrument.get() != null;
}
2022-07-08 17:14:18 +08:00
/**
* 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)}
*/
public static void startHinting(World w) {
proxy.startHinting(w);
}
/**
2022-08-08 17:40:12 +08:00
* End current batch of hinting. All hints particles generated during one batch will be considered to belong to one
* hologram.
2022-07-08 17:14:18 +08:00
* <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)}
*/
public static void endHinting(World w) {
proxy.endHinting(w);
}
2022-08-30 23:27:18 +08:00
/**
* Generate a new hint particle on client side at given location using given textures with a tint.
2022-09-15 15:58:17 +08:00
*
* @param w World to spawn. Usually the client world.
* @param x x coord
* @param y y coord
* @param z z coord
2022-08-30 23:27:18 +08:00
* @param icons 6 texture. in forge direction order.
2022-09-15 15:58:17 +08:00
* @param RGBa a 4 short array. tint in rgba form. currently alpha channel is ignored, but we might change this
* later on.
2022-08-30 23:27:18 +08:00
*/
2022-07-08 17:14:18 +08:00
public static void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
proxy.hintParticleTinted(w, x, y, z, icons, RGBa);
}
2022-08-30 23:27:18 +08:00
/**
* Generate a new hint particle on client side at given location using textures from given block with a tint.
2022-09-15 15:58:17 +08:00
*
* @param w World to spawn. Usually the client world.
* @param x x coord
* @param y y coord
* @param z z coord
2022-08-30 23:27:18 +08:00
* @param block block to take texture from
2022-09-15 15:58:17 +08:00
* @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.
2022-08-30 23:27:18 +08:00
*/
2022-07-08 17:14:18 +08:00
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);
}
2022-08-30 23:27:18 +08:00
/**
* Generate a new hint particle on client side at given location using given textures.
2022-09-15 15:58:17 +08:00
*
* @param w World to spawn. Usually the client world.
* @param x x coord
* @param y y coord
* @param z z coord
2022-08-30 23:27:18 +08:00
* @param icons 6 texture. in forge direction order.
*/
2022-07-08 17:14:18 +08:00
public static void hintParticle(World w, int x, int y, int z, IIcon[] icons) {
proxy.hintParticle(w, x, y, z, icons);
}
2022-08-30 23:27:18 +08:00
/**
* Generate a new hint particle on client side at given location using textures from given block.
2022-09-15 15:58:17 +08:00
*
* @param w World to spawn. Usually the client world.
* @param x x coord
* @param y y coord
* @param z z coord
2022-08-30 23:27:18 +08:00
* @param block block to take texture from
2022-09-15 15:58:17 +08:00
* @param meta the meta of block to take texture from
2022-08-30 23:27:18 +08:00
*/
2022-07-08 17:14:18 +08:00
public static void hintParticle(World w, int x, int y, int z, Block block, int meta) {
proxy.hintParticle(w, x, y, z, block, meta);
}
2022-08-24 11:28:26 +08:00
/**
* Update the tint of given hint particle. Do nothing if particle not found.
2022-09-15 15:58:17 +08:00
* <p>
2022-08-30 23:27:18 +08:00
* 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.
2022-08-24 11:28:26 +08:00
*/
public static boolean markHintParticleError(EntityPlayer player, World w, int x, int y, int z) {
return proxy.markHintParticleError(player, w, x, y, z);
}
2022-08-08 17:40:12 +08:00
/**
* Update the tint of given hint particle. Do nothing if particle not found.
2022-08-30 23:27:18 +08:00
*
2022-08-08 17:40:12 +08:00
* @return false if nothing updated. true if updated.
*/
public static boolean updateHintParticleTint(EntityPlayer player, World w, int x, int y, int z, short[] RGBa) {
return proxy.updateHintParticleTint(player, w, x, y, z, RGBa);
}
2022-07-08 17:14:18 +08:00
/**
2022-08-30 23:27:18 +08:00
* Query the ExtendedFacing of this tile entity from client side. Can be sent only on client side. The
2022-07-08 17:14:18 +08:00
* ExtendedFacing will later be set onto given tile entity via
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} upon arrival of
* server reply.
2022-08-30 23:27:18 +08:00
* <p>
* The server side will query the {@link ExtendedFacing} of this provider using
* {@link IAlignment#getExtendedFacing()}
2022-07-08 17:14:18 +08:00
*
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
*/
public static void queryAlignment(IAlignmentProvider provider) {
StructureLib.net.sendToServer(new AlignmentMessage.AlignmentQuery(provider));
}
/**
* Send the ExtendedFacing of this Tile Entity to all players. Can be called on server side only.
2022-08-30 23:27:18 +08:00
* <p>
* The receiving tile entity will receive the {@link ExtendedFacing} via its
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
2022-07-08 17:14:18 +08:00
*
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
*/
public static void sendAlignment(IAlignmentProvider provider) {
StructureLib.net.sendToAll(new AlignmentMessage.AlignmentData(provider));
}
/**
* Send the ExtendedFacing of this Tile Entity to given player. Can be called on server side only.
2022-08-30 23:27:18 +08:00
* <p>
* The receiving tile entity will receive the {@link ExtendedFacing} via its
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
2022-07-08 17:14:18 +08:00
*
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
*/
public static void sendAlignment(IAlignmentProvider provider, EntityPlayerMP player) {
StructureLib.net.sendTo(new AlignmentMessage.AlignmentData(provider), player);
}
/**
* Send the ExtendedFacing of this Tile Entity to all players around target point. Can be called on server side
* only.
2022-08-30 23:27:18 +08:00
* <p>
* The receiving tile entity will receive the {@link ExtendedFacing} via its
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
2022-07-08 17:14:18 +08:00
*
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
*/
public static void sendAlignment(IAlignmentProvider provider, NetworkRegistry.TargetPoint targetPoint) {
StructureLib.net.sendToAllAround(new AlignmentMessage.AlignmentData(provider), targetPoint);
}
/**
* Send the ExtendedFacing of this Tile Entity to all players in that dimension. Can be called on server side only.
2022-08-30 23:27:18 +08:00
* <p>
* The receiving tile entity will receive the {@link ExtendedFacing} via its
* {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)} method.
2022-07-08 17:14:18 +08:00
*
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
*/
public static void sendAlignment(IAlignmentProvider provider, World dimension) {
StructureLib.net.sendToDimension(new AlignmentMessage.AlignmentData(provider), dimension.provider.dimensionId);
}
2022-08-30 23:27:18 +08:00
/**
* Get the Block for StructureLib supplied hint block.
*/
2022-07-08 17:14:18 +08:00
public static Block getBlockHint() {
return StructureLib.blockHint;
}
2022-08-30 23:27:18 +08:00
/**
* Get the ItemBlock for StructureLib supplied hint block.
*/
2022-07-08 17:14:18 +08:00
public static Item getItemBlockHint() {
return StructureLib.itemBlockHint;
}
2023-02-11 01:25:16 +08:00
/**
* Get the hologram item.
*/
public static Item getDefaultHologramItem() {
return StructureLib.itemConstructableTrigger;
}
2022-08-30 23:27:18 +08:00
/**
* Check if structure debug mode is on.
*
* @return true if debug mode is on
*/
2022-07-08 17:14:18 +08:00
public static boolean isDebugEnabled() {
return StructureLib.DEBUG_MODE;
}
public static void setDebugEnabled(boolean enabled) {
StructureLib.DEBUG_MODE = enabled;
}
2022-08-08 17:40:12 +08:00
/**
* 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.
2022-08-30 23:27:18 +08:00
* <p>
2022-09-11 02:54:11 +08:00
* Use this in your
* {@link com.gtnewhorizon.structurelib.structure.IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
2022-08-08 17:40:12 +08:00
*/
2022-09-11 02:54:11 +08:00
@Deprecated
2022-08-08 17:40:12 +08:00
public static boolean isBlockTriviallyReplaceable(World w, int x, int y, int z, EntityPlayerMP actor) {
2022-09-11 02:54:11 +08:00
return isBlockTriviallyReplaceable(w, x, y, z, (EntityPlayer) actor);
}
/**
* 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)}
*/
public static boolean isBlockTriviallyReplaceable(World w, int x, int y, int z, EntityPlayer actor) {
2022-08-08 17:40:12 +08:00
// TODO extend this function a bit
2022-08-30 23:27:18 +08:00
Block block = w.getBlock(x, y, z);
return block.isAir(w, x, y, z) || block.isReplaceable(w, x, y, z);
2022-08-08 17:40:12 +08:00
}
2022-09-02 15:45:13 +08:00
/**
* Send chat to player, but throttled.
2022-09-15 15:58:17 +08:00
*
* @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
2022-09-02 15:45:13 +08:00
* @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) {
addThrottledChat(throttleKey, player, text, intervalRequired, false);
}
/**
* Send chat to player, but throttled.
2022-09-15 15:58:17 +08:00
*
* @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
2022-09-02 15:45:13 +08:00
* @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) {
proxy.addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend);
}
2025-04-08 14:32:10 +08:00
/**
* Register a channel description here. The description should describe how a channel will be used inside your mod.
*
* @param channel channel key
* @param modid your modid
* @param description localization key for your description
*/
public static void registerChannelDescription(final String channel, final String modid, final String description) {
ChannelDescription.set(channel, modid, description);
}
/**
* Register an item stack as an indicator for a (channel, value) pair.
*
* @param channel channel key
* @param modid your modid
* @param channelValue value
* @param stack item stack. having a metadata of
* {@link net.minecraftforge.oredict.OreDictionary#WILDCARD_VALUE} will match without comparing
* NBT or metadata value. having a tag with {@code tag.getBoolean("*") == true} will match
* without comparing NBT.
*/
public static void registerChannelItem(final String channel, final String modid, final int channelValue,
final ItemStack stack) {
ChannelDescription.item(channel, channelValue, stack);
2025-04-08 14:34:32 +08:00
AnimatedTooltipHandler.addItemTooltip(
stack,
2025-04-11 17:11:00 +08:00
AnimatedTooltipHandler.translatedText("structurelib.tooltip.channelvalue", channelValue, channel));
AnimatedTooltipHandler.addItemTooltip(
stack,
AnimatedTooltipHandler.translatedText("structurelib.tooltip.indicator_dnd", channelValue, channel));
2025-04-08 14:32:10 +08:00
}
2021-05-29 19:05:50 +08:00
}