Compare commits

...
13 Commits
Author SHA1 Message Date
Glease b086a65828 Fix typo in ofBlockUnlocalizedName
also added standard way of toggling debug mode pogrammatically
2021-08-01 03:07:51 +08:00
Glease f1f6dae00f Add generalized GT5's ofCoil 2021-07-22 12:08:24 +08:00
Glease 68c5436496 Add option to related to hologram projection
Also made clear what's public api and what's not.
2021-07-21 17:26:28 +08:00
iouter c4eb372cfb Add zh_CN.lang 2021-07-21 15:57:16 +08:00
Glease 2446ad2db7 attempt to fix buildscript 2021-07-21 14:10:05 +08:00
Glease 906961b6c8 differentiate between TecTech items and our items 2021-07-19 19:30:49 +08:00
Glease 393045d4f2 Add utility method for lazy initialized structure elements 2021-07-19 17:45:18 +08:00
Glease 74baa66f52 Fix invisible hint particles 2021-07-19 14:48:33 +08:00
Glease 24928454fd Pull utility methods up from gregtech 2021-07-19 14:48:33 +08:00
Glease 34ceda8ccc Create gradle.yml 2021-06-29 02:12:56 +08:00
Glease c78c61f45e Add missing texture
forgot to check in the texture...
2021-06-25 15:03:04 +08:00
Glease fbf8cfd82c Add constructable trigger item and a few utilities 2021-06-22 23:58:19 +08:00
Glease 4c42e5f2a2 Fix toolSetXXX not properly rotating 2021-06-16 13:46:24 +08:00
29 changed files with 921 additions and 82 deletions

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Java CI with Gradle
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
+8 -1
View File
@@ -51,11 +51,18 @@ task deobfJar(type: Jar) {
classifier = 'deobf'
}
task sourceJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
artifacts {
archives deobfJar
archives jar
archives sourceJar
}
install.dependsOn reobf
idea {
module {
inheritOutputDirs = false
+1 -1
View File
@@ -1,5 +1,5 @@
modGroup = com.gtnewhorizon
modVersion = 1.0.1
modVersion = 1.0.8
modBaseName = StructureLib
forgeVersion = 1.7.10-10.13.4.1614-1.7.10
@@ -0,0 +1,68 @@
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 net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import java.io.File;
import java.util.Map;
public enum ConfigurationHandler {
INSTANCE;
private Configuration config;
private int maxCoexistingHologram;
private boolean removeCollidingHologram;
ConfigurationHandler() {
FMLCommonHandler.instance().bus().register(this);
}
void init(File f) {
config = new Configuration(f, ConfigurationVersion.latest().getVersionMarker());
ConfigurationVersion.migrateToLatest(config);
loadConfig();
setLanguageKeys();
}
private void setLanguageKeys() {
for (String categoryName : config.getCategoryNames()) {
ConfigCategory category = config.getCategory(categoryName);
category.setLanguageKey("structurelib.config." + categoryName);
for (Map.Entry<String, Property> entry : category.entrySet()) {
entry.getValue().setLanguageKey(String.format("%s.%s", category.getLanguagekey(), entry.getKey()));
}
}
}
private void loadConfig() {
maxCoexistingHologram = config.getInt("maxCoexisting", "client.hologram", 1, 1, 100, "An attempt will be made to prune old holograms when a new hologram is about to be projected");
removeCollidingHologram = config.getBoolean("removeColliding", "client.hologram", true, "An attempt will be made to remove an existing hologram if it collides with a new hologram.");
if (config.hasChanged()) {
config.save();
}
}
@SubscribeEvent
public void onConfigChange(ConfigChangedEvent.PostConfigChangedEvent e) {
if (e.modID.equals(StructureLibAPI.MOD_ID)) {
loadConfig();
}
}
public int getMaxCoexistingHologram() {
return maxCoexistingHologram;
}
public boolean isRemoveCollidingHologram() {
return removeCollidingHologram;
}
Configuration getConfig() {
return config;
}
}
@@ -0,0 +1,44 @@
package com.gtnewhorizon.structurelib;
import net.minecraftforge.common.config.Configuration;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Objects;
enum ConfigurationVersion {
V1 {
@Override
protected void step(Configuration c) {
}
};
private static final ConfigurationVersion[] VALUES = values();
private final String versionMarker;
ConfigurationVersion() {
this.versionMarker = name();
}
public static void migrateToLatest(Configuration c) {
for (int i = identify(c).ordinal() + 1; i < VALUES.length; i++) {
VALUES[i].step(c);
}
}
public static ConfigurationVersion latest() {
return VALUES[VALUES.length - 1];
}
public static ConfigurationVersion identify(Configuration c) {
return Arrays.stream(VALUES).filter(v -> Objects.equals(c.getLoadedConfigVersion(), v.getVersionMarker())).findFirst().orElse(V1);
}
@Nullable
public String getVersionMarker() {
return versionMarker;
}
protected abstract void step(Configuration c);
}
@@ -0,0 +1,28 @@
package com.gtnewhorizon.structurelib;
import cpw.mods.fml.client.IModGuiFactory;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import java.util.Set;
public class GuiFactory implements IModGuiFactory {
@Override
public void initialize(Minecraft minecraftInstance) {
}
@Override
public Class<? extends GuiScreen> mainConfigGuiClass() {
return GuiModConfig.class;
}
@Override
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
return null;
}
@Override
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) {
return null;
}
}
@@ -0,0 +1,25 @@
package com.gtnewhorizon.structurelib;
import cpw.mods.fml.client.config.GuiConfig;
import cpw.mods.fml.client.config.IConfigElement;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.common.config.Configuration;
import java.util.List;
import java.util.stream.Collectors;
public class GuiModConfig extends GuiConfig {
public GuiModConfig(GuiScreen guiScreen) {
super(guiScreen, getConfigElements(), StructureLibAPI.MOD_ID, false, false, 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());
}
}
@@ -1,8 +1,9 @@
package com.gtnewhorizon.structurelib;
import com.gtnewhorizon.structurelib.alignment.AlignmentMessage;
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
import com.gtnewhorizon.structurelib.block.BlockHint;
import com.gtnewhorizon.structurelib.item.ItemBlockHint;
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
import com.gtnewhorizon.structurelib.item.ItemFrontRotationTool;
import com.gtnewhorizon.structurelib.proxy.CommonProxy;
import com.gtnewhorizon.structurelib.util.XSTR;
@@ -25,15 +26,14 @@ import org.apache.logging.log4j.Logger;
/**
* This class does not contain a stable API. Refrain from using this class.
*/
@Mod(modid = StructureLib.MOD_ID, name = "StructureLib", version = "${version}", acceptableRemoteVersions = "*")
@Mod(modid = StructureLibAPI.MOD_ID, name = "StructureLib", version = "${version}", acceptableRemoteVersions = "*", guiFactory = "com.gtnewhorizon.structurelib.GuiFactory")
public class StructureLib {
public static boolean DEBUG_MODE = true;
public static boolean DEBUG_MODE = Boolean.getBoolean("structurelib.debug");
public static Logger LOGGER = LogManager.getLogger("StructureLib");
public static final String MOD_ID = "structurelib";
@SidedProxy(serverSide = "com.gtnewhorizon.structurelib.proxy.CommonProxy", clientSide = "com.gtnewhorizon.structurelib.proxy.ClientProxy")
static CommonProxy proxy;
static SimpleNetworkWrapper net = NetworkRegistry.INSTANCE.newSimpleChannel(MOD_ID);
static SimpleNetworkWrapper net = NetworkRegistry.INSTANCE.newSimpleChannel(StructureLibAPI.MOD_ID);
static {
net.registerMessage(AlignmentMessage.ServerHandler.class, AlignmentMessage.AlignmentQuery.class, 0, Side.SERVER);
@@ -45,6 +45,7 @@ public class StructureLib {
static Block blockHint;
static Item itemBlockHint;
static Item itemFrontRotationTool;
static Item itemConstructableTrigger;
public static final CreativeTabs creativeTab = new CreativeTabs("structurelib") {
@Override
@SideOnly(Side.CLIENT)
@@ -55,9 +56,12 @@ public class StructureLib {
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent e) {
ConfigurationHandler.INSTANCE.init(e.getSuggestedConfigurationFile());
GameRegistry.registerBlock(blockHint = new BlockHint(), ItemBlockHint.class, "blockhint");
itemBlockHint = ItemBlock.getItemFromBlock(StructureLibAPI.getBlockHint());
GameRegistry.registerItem(itemFrontRotationTool = new ItemFrontRotationTool(), itemFrontRotationTool.getUnlocalizedName());
GameRegistry.registerItem(itemConstructableTrigger = new ItemConstructableTrigger(), itemConstructableTrigger.getUnlocalizedName());
proxy.preInit(e);
}
public static void addClientSideChatMessages(String... messages) {
@@ -1,17 +1,24 @@
package com.gtnewhorizon.structurelib;
import com.gtnewhorizon.structurelib.alignment.AlignmentMessage;
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import cpw.mods.fml.common.network.NetworkRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import static com.gtnewhorizon.structurelib.StructureLib.proxy;
/**
* 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;
public static final int HINT_BLOCK_META_GENERIC_2 = 2;
@@ -28,6 +35,25 @@ public class StructureLibAPI {
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;
/**
* Start a batch of hinting. All hints particles generated during one batch will be considered to belong to one hologram.
*
* 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);
}
/**
* Start current batch of hinting. All hints particles generated during one batch will be considered to belong to one hologram.
*
* 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);
}
public static void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
proxy.hintParticleTinted(w, x, y, z, icons, RGBa);
}
@@ -44,22 +70,45 @@ public class StructureLibAPI {
proxy.hintParticle(w, x, y, z, block, meta);
}
/**
* Query the ExtendedFacing of this tile entity.
* The ExtendedFacing will later be set onto given tile entity via {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)}
* upon arrival of server reply.
* @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.
* @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.
* @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.
* @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.
* @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);
}
@@ -71,4 +120,12 @@ public class StructureLibAPI {
public static Item getItemBlockHint() {
return StructureLib.itemBlockHint;
}
public static boolean isDebugEnabled() {
return StructureLib.DEBUG_MODE;
}
public static void setDebugEnabled(boolean enabled) {
StructureLib.DEBUG_MODE = enabled;
}
}
@@ -54,7 +54,7 @@ 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++) {
if(toolSetDirection(Direction.VALUES[j%valuesLength].getForgeDirection())){
if (toolSetDirection(Direction.VALUES[(j + i) % valuesLength].getForgeDirection())) {
return true;
}
}
@@ -90,8 +90,8 @@ public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
int flips = Flip.VALUES.length;
int rotations = Rotation.VALUES.length;
for (int ii = 0,jj=getFlip().ordinal(); ii < flips; ii++) {
for (int i = 0,j=getRotation().ordinal()+1; i < rotations; i++) {
if(checkedSetExtendedFacing(ExtendedFacing.of(getDirection(),Rotation.VALUES[j%rotations],Flip.VALUES[jj%flips]))){
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]))) {
return true;
}
}
@@ -112,8 +112,8 @@ public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
default boolean toolSetFlip(Flip flip){
if(flip==null){
for (int i = 0,j=getFlip().ordinal()+1, valuesLength = Flip.VALUES.length; i < valuesLength; i++) {
if(toolSetFlip(Flip.VALUES[j%valuesLength])){
for (int i = 1, j = getFlip().ordinal(), valuesLength = Flip.VALUES.length; i < valuesLength; i++) {
if (checkedSetFlip(Flip.VALUES[(j + i) % valuesLength])) {
return true;
}
}
@@ -134,7 +134,7 @@ 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++) {
if(toolSetExtendedFacing(ExtendedFacing.VALUES[j%valuesLength])){
if (checkedSetExtendedFacing(ExtendedFacing.VALUES[(j + i)%valuesLength])){
return true;
}
}
@@ -1,6 +1,7 @@
package com.gtnewhorizon.structurelib.alignment.constructable;
import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.StructureLibAPI;
import com.gtnewhorizon.structurelib.alignment.IAlignment;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import net.minecraft.entity.player.EntityPlayer;
@@ -17,6 +18,13 @@ public class ConstructableUtility {
}
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) {
TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
if (tTileEntity == null || aPlayer instanceof FakePlayer) {
return aPlayer instanceof EntityPlayerMP;
@@ -14,6 +14,10 @@ import java.util.HashMap;
public interface IMultiblockInfoContainer<T> {
HashMap<String, IMultiblockInfoContainer<?>> MULTIBLOCK_MAP = new HashMap<>();
/**
* There is no specific loading phase restriction, but you should generally not call it before the tile entity is
* properly registered.
*/
static <T extends TileEntity> void registerTileClass(Class<T> clazz, IMultiblockInfoContainer<?> info) {
MULTIBLOCK_MAP.put(clazz.getCanonicalName(), info);
}
@@ -0,0 +1,5 @@
/**
* 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,6 +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 net.minecraft.block.Block;
@@ -26,22 +27,22 @@ public class BlockHint extends Block {
@Override
public void registerBlockIcons(IIconRegister aIconRegister) {
//super.registerBlockIcons(aIconRegister);
hint[0] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_0");
hint[1] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_1");
hint[2] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_2");
hint[3] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_3");
hint[4] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_4");
hint[5] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_5");
hint[6] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_6");
hint[7] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_7");
hint[8] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_8");
hint[9] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_9");
hint[10] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_10");
hint[11] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_11");
hint[12] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_DEFAULT");
hint[13] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_AIR");
hint[14] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_NOAIR");
hint[15] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_ERROR");
hint[0] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_0");
hint[1] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_1");
hint[2] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_2");
hint[3] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_3");
hint[4] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_4");
hint[5] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_5");
hint[6] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_6");
hint[7] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_7");
hint[8] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_8");
hint[9] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_9");
hint[10] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_10");
hint[11] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_11");
hint[12] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_DEFAULT");
hint[13] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_AIR");
hint[14] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_NOAIR");
hint[15] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_ERROR");
}
@Override
@@ -1,6 +1,7 @@
package com.gtnewhorizon.structurelib.entity.fx;
import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.proxy.ClientProxy;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
@@ -12,11 +13,11 @@ import net.minecraft.world.World;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class BlockHint extends EntityFX {
public class EntityFXBlockHint extends EntityFX {
private IIcon[] icons;
private short[] mRGBa = {255,255,255,0};
public BlockHint(World world){
public EntityFXBlockHint(World world){
this(world,0,0,0, Blocks.stone,0);
}
@@ -28,7 +29,7 @@ public class BlockHint extends EntityFX {
* @param z
* @param icons DOWN, UP, NORTH, SOUTH, WEST, EAST
*/
public BlockHint(World world, int x, int y, int z, IIcon[] icons) {
public EntityFXBlockHint(World world, int x, int y, int z, IIcon[] icons) {
super(world, x + .25, y + .5, z + .25);
particleGravity = 0;
prevPosX = posX;
@@ -39,7 +40,7 @@ public class BlockHint extends EntityFX {
this.icons=icons;
}
public BlockHint(World world, int x, int y, int z, Block block, int meta) {
public EntityFXBlockHint(World world, int x, int y, int z, Block block, int meta) {
super(world, x+.25, y+.5, z+.25);
particleGravity = 0;
prevPosX = posX;
@@ -53,7 +54,7 @@ public class BlockHint extends EntityFX {
}
}
public BlockHint withColorTint(short[] coloure){
public EntityFXBlockHint withColorTint(short[] coloure){
this.mRGBa =coloure;
return this;
}
@@ -130,4 +131,10 @@ public class BlockHint extends EntityFX {
public boolean shouldRenderInPass(int pass) {
return pass==2;
}
@Override
public void setDead() {
super.setDead();
ClientProxy.onHintDead(this);
}
}
@@ -0,0 +1,37 @@
package com.gtnewhorizon.structurelib.item;
import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import java.util.List;
import static com.gtnewhorizon.structurelib.StructureLibAPI.MOD_ID;
import static net.minecraft.util.EnumChatFormatting.BLUE;
import static net.minecraft.util.StatCollector.translateToLocal;
public class ItemConstructableTrigger extends Item {
public ItemConstructableTrigger() {
setUnlocalizedName("structurelib.constructableTrigger");
setTextureName(MOD_ID + ":itemConstructableTrigger");
setCreativeTab(StructureLib.creativeTab);
}
@Override
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);
}
@SuppressWarnings("unchecked")
@Override
public void addInformation(ItemStack aStack, EntityPlayer ep, List aList, boolean boo) {
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
}
}
@@ -12,7 +12,7 @@ import net.minecraft.world.World;
import java.util.List;
import static com.gtnewhorizon.structurelib.StructureLib.MOD_ID;
import static com.gtnewhorizon.structurelib.StructureLibAPI.MOD_ID;
import static net.minecraft.util.StatCollector.translateToLocal;
public class ItemFrontRotationTool extends Item {
@@ -1,6 +1,8 @@
package com.gtnewhorizon.structurelib.alignment;
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;
@@ -1,7 +1,12 @@
package com.gtnewhorizon.structurelib.proxy;
import com.gtnewhorizon.structurelib.entity.fx.BlockHint;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.gtnewhorizon.structurelib.ConfigurationHandler;
import com.gtnewhorizon.structurelib.entity.fx.EntityFXBlockHint;
import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiNewChat;
@@ -10,57 +15,173 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.WorldEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static com.gtnewhorizon.structurelib.StructureLib.RANDOM;
public class ClientProxy extends CommonProxy {
@Override
public void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
Minecraft.getMinecraft().effectRenderer.addEffect(new BlockHint(w, x, y, z, icons).withColorTint(RGBa));
@Override
public void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
EntityFXBlockHint hint = new EntityFXBlockHint(w, x, y, z, icons).withColorTint(RGBa);
Minecraft.getMinecraft().effectRenderer.addEffect(hint);
ensureHinting();
if (ConfigurationHandler.INSTANCE.isRemoveCollidingHologram()) {
HintParticleInfo info = new HintParticleInfo(x, y, z, currentHints);
EntityFXBlockHint dupe = allHints.inverse().get(info);
if (dupe != null) {
List<EntityFXBlockHint> owner = allHints.get(dupe).owner;
// in case someone forget to call endHinting
if (owner != currentHints) {
hintOwners.remove(owner);
owner.forEach(EntityFXBlockHint::setDead);
owner.clear();
}
}
allHints.forcePut(hint, info);
}
currentHints.add(hint);
EntityFX particle = new WeightlessParticleFX(w, x + RANDOM.nextFloat() * 0.5F, y + RANDOM.nextFloat() * 0.5F, z + RANDOM.nextFloat() * 0.5F, 0, 0, 0);
particle.setRBGColorF(0, 0.6F * RANDOM.nextFloat(), 0.8f);
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
}
EntityFX particle = new WeightlessParticleFX(w, x + RANDOM.nextFloat() * 0.5F, y + RANDOM.nextFloat() * 0.5F, z + RANDOM.nextFloat() * 0.5F, 0, 0, 0);
particle.setRBGColorF(0, 0.6F * RANDOM.nextFloat(), 0.8f);
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
}
@Override
public void hintParticleTinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), RGBa);
}
@Override
public void hintParticleTinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), RGBa);
}
@Override
public void hintParticle(World w, int x, int y, int z, IIcon[] icons) {
hintParticleTinted(w, x, y, z, icons, new short[]{255, 255, 255, 0});
}
@Override
public void hintParticle(World w, int x, int y, int z, IIcon[] icons) {
hintParticleTinted(w, x, y, z, icons, new short[]{255, 255, 255, 0});
}
@Override
public void hintParticle(World w, int x, int y, int z, Block block, int meta) {
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), new short[]{255, 255, 255, 0});
}
@Override
public void hintParticle(World w, int x, int y, int z, Block block, int meta) {
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), new short[]{255, 255, 255, 0});
}
private static IIcon[] createIIconFromBlock(Block block, int meta) {
IIcon[] ret = new IIcon[6];
for (int i = 0; i < 6; i++) {
block.getIcon(i, meta);
}
return ret;
}
private static IIcon[] createIIconFromBlock(Block block, int meta) {
IIcon[] ret = new IIcon[6];
for (int i = 0; i < 6; i++) {
ret[i] = block.getIcon(i, meta);
}
return ret;
}
@Override
public void addClientSideChatMessages(String... messages) {
GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
for (String s : messages) {
chat.printChatMessage(new ChatComponentText(s));
}
}
@Override
public void addClientSideChatMessages(String... messages) {
GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
for (String s : messages) {
chat.printChatMessage(new ChatComponentText(s));
}
}
@Override
public EntityPlayer getCurrentPlayer() {
return Minecraft.getMinecraft().thePlayer;
}
@Override
public EntityPlayer getCurrentPlayer() {
return Minecraft.getMinecraft().thePlayer;
}
@Override
public boolean isCurrentPlayer(EntityPlayer player) {
return player == Minecraft.getMinecraft().thePlayer;
}
@Override
public boolean isCurrentPlayer(EntityPlayer player) {
return player == Minecraft.getMinecraft().thePlayer;
}
private static final BiMap<EntityFXBlockHint, HintParticleInfo> allHints = HashBiMap.create();
private static final List<List<EntityFXBlockHint>> hintOwners = new ArrayList<>();
private static List<EntityFXBlockHint> currentHints;
public static void onHintDead(EntityFXBlockHint fx) {
if (ConfigurationHandler.INSTANCE.isRemoveCollidingHologram())
allHints.remove(fx);
for (Iterator<List<EntityFXBlockHint>> iterator = hintOwners.iterator(); iterator.hasNext(); ) {
List<EntityFXBlockHint> list = iterator.next();
if (list.remove(fx)) {
if (list.isEmpty())
iterator.remove();
break;
}
}
}
@Override
public void startHinting(World w) {
if (!w.isRemote)
return;
if (currentHints != null)
hintOwners.add(currentHints);
currentHints = new LinkedList<>();
}
private void ensureHinting() {
if (currentHints == null)
currentHints = new LinkedList<>();
}
@Override
public void endHinting(World w) {
if (!w.isRemote)
return;
while (!hintOwners.isEmpty() && hintOwners.size() >= ConfigurationHandler.INSTANCE.getMaxCoexistingHologram()) {
List<EntityFXBlockHint> list = hintOwners.remove(0);
list.forEach(EntityFXBlockHint::setDead);
list.clear();
}
if (!currentHints.isEmpty())
hintOwners.add(currentHints);
currentHints = null;
}
@Override
public void preInit(FMLPreInitializationEvent e) {
MinecraftForge.EVENT_BUS.register(new ForgeEventHandler());
}
private static class HintParticleInfo {
private final int x, y, z;
private final List<EntityFXBlockHint> owner;
public HintParticleInfo(int x, int y, int z, List<EntityFXBlockHint> owner) {
this.x = x;
this.y = y;
this.z = z;
this.owner = owner;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HintParticleInfo that = (HintParticleInfo) o;
if (x != that.x) return false;
if (y != that.y) return false;
return z == that.z;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
result = 31 * result + z;
return result;
}
}
public static class ForgeEventHandler {
@SubscribeEvent
public void onWorldLoad(WorldEvent.Load e) {
if (e.world.isRemote) {
allHints.clear();
hintOwners.clear();
}
}
}
}
@@ -1,5 +1,6 @@
package com.gtnewhorizon.structurelib.proxy;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.IIcon;
@@ -18,4 +19,8 @@ public class CommonProxy {
}
public void addClientSideChatMessages(String... messages){
}
public void startHinting(World w) {}
public void endHinting(World w) {}
public void preInit(FMLPreInitializationEvent e) {}
}
@@ -165,4 +165,8 @@ public interface IStructureDefinition<T> {
}
return true;
}
static <T> StructureDefinition.Builder<T> builder() {
return StructureDefinition.builder();
}
}
@@ -0,0 +1,12 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.block.Block;
/**
* a function to extract tier info from a block.
* @param <TIER>
*/
@FunctionalInterface
public interface ITierConverter<TIER> {
TIER convert(Block block, int meta);
}
@@ -0,0 +1,14 @@
package com.gtnewhorizon.structurelib.structure;
/**
* Implement this and use {@link StructureUtility#withContext(IStructureElement)} in case you need to record some
* temporary states that don't need to live in your main context, which would usually live for the whole lifetime of the
* structure than just during structure check. Usually just save some few bytes, but becomes non trivial if you need to
* record too much stuff.
*
* You will have to reset the context yourself though. The API can't guess when the old context becomes invalid.
* @param <CTX> the temporary state context
*/
public interface IWithExtendedContext<CTX> {
CTX getCurrentContext();
}
@@ -0,0 +1,38 @@
package com.gtnewhorizon.structurelib.structure;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import java.util.function.Function;
class LazyStructureElement<T> implements IStructureElementDeferred<T> {
private Function<T, IStructureElement<T>> to;
private IStructureElement<T> elem;
public LazyStructureElement(Function<T, IStructureElement<T>> to) {
this.to = to;
}
private IStructureElement<T> get(T t) {
if (to != null) {
elem = to.apply(t);
to = null;
}
return elem;
}
@Override
public boolean check(T t, World world, int x, int y, int z) {
return get(t).check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return get(t).placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return get(t).spawnHint(t, world, x, y, z, trigger);
}
}
@@ -5,17 +5,34 @@ import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.structure.adders.IBlockAdder;
import com.gtnewhorizon.structurelib.structure.adders.ITileAdder;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
import javax.annotation.Nullable;
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.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.IntBinaryOperator;
import java.util.function.Supplier;
import static java.lang.Integer.MIN_VALUE;
@@ -175,6 +192,173 @@ public class StructureUtility {
//region block
/**
* A more primitive variant of {@link #ofBlocksTiered(ITierConverter, List, Object, BiConsumer, Function)}
* Main difference is this one is check only.
* @see #ofBlocksTiered(ITierConverter, Object, BiConsumer, Function)
*/
public static <T, TIER> IStructureElementCheckOnly<T> ofBlocksTiered(ITierConverter<TIER> tierExtractor, @Nullable TIER notSet, BiConsumer<T, TIER> setter, Function<T, TIER> getter) {
if (tierExtractor == null) throw new IllegalArgumentException();
if (setter == null) throw new IllegalArgumentException();
if (getter == null) throw new IllegalArgumentException();
return (t, world, x, y, z) -> {
Block block = world.getBlock(x, y, z);
int meta = world.getBlockMetadata(x, y, z);
TIER tier = tierExtractor.convert(block, meta);
TIER current = getter.apply(t);
if (Objects.equals(notSet, current)) {
setter.accept(t, tier);
return true;
}
return Objects.equals(current, tier);
};
}
/**
* Element representing a component with different tiers. Player can use more blueprint to get hints denoting more
* advanced components.
*
* There is yet no TileEntity counter part of this utility. Feel free to submit a PR to add it.
* @param allKnownTiers All known tiers as of calling. Can be empty or null. No hint will be spawned if empty or null. Cannot have null elements.
* First element denotes the most primitive tier. Last element denotes the most advanced tier.
* If not all tiers are available at definition construction time, use {@link #lazy(Supplier)} or its overloads to delay a little bit.
* @param notSet The value returned from {@code getter} when there were no tier info found in T yet. Can be null.
* @param getter a function to retrieve the current tier from T
* @param setter a function to set the current tier into T
* @param tierExtractor a function to extract tier info from a block.
*/
public static <T, TIER> IStructureElement<T> ofBlocksTiered(ITierConverter<TIER> tierExtractor, @Nullable List<Pair<Block, Integer>> allKnownTiers, @Nullable TIER notSet, BiConsumer<T, TIER> setter, Function<T, TIER> getter) {
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 IStructureElement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return check.check(t, world, x, y, z);
}
private Pair<Block, Integer> getHint(ItemStack trigger) {
return hints.get(Math.min(Math.max(trigger.stackSize, 1), hints.size()));
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
Pair<Block, Integer> hint = getHint(trigger);
if (hint == null)
return false;
StructureLibAPI.hintParticle(world, x, y, z, hint.getKey(), hint.getValue());
return true;
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
Pair<Block, Integer> hint = getHint(trigger);
if (hint == null)
return false;
if (hint.getKey() instanceof ICustomBlockSetting) {
ICustomBlockSetting block = (ICustomBlockSetting) hint.getKey();
block.setBlock(world, x, y, z, hint.getValue());
} else {
world.setBlock(x, y, z, hint.getKey(), hint.getValue(), 2);
}
return true;
}
};
}
/**
* Denote a block using unlocalized names. This can be useful to get around mod loading order issues.
* <p>
* While no immediate error will be thrown, client code should ensure said mod is loaded and
* said mod is present, otherwise bad things will happen later!
*/
public static <T> IStructureElement<T> ofBlockUnlocalizedName(String modid, String unlocalizedName, int meta) {
if (StringUtils.isBlank(unlocalizedName)) throw new IllegalArgumentException();
if (meta < 0) throw new IllegalArgumentException();
if (meta > 15) throw new IllegalArgumentException();
if (StringUtils.isBlank(modid)) throw new IllegalArgumentException();
return new IStructureElement<T>() {
private Block block;
private Block getBlock() {
if (block == null)
block = GameRegistry.findBlock(modid, unlocalizedName);
return block;
}
@Override
public boolean check(T t, World world, int x, int y, int z) {
return world.getBlock(x, y, z) == getBlock() && world.getBlockMetadata(x, y, z) == meta;
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
StructureLibAPI.hintParticle(world, x, y, z, getBlock(), meta);
return true;
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
world.setBlock(x, y, z, getBlock(), meta, 2);
return true;
}
};
}
/**
* Similiar to the other overload, but allows client code to specify a fallback in case said block was not found later
* when the element got called.
*
* This is slightly different to using the other overload and another element in a {@link #ofChain(IStructureElement[])},
* as that combination would cause crash, where this won't.
*/
public static <T> IStructureElement<T> ofBlockUnlocalizedName(String modid, String unlocalizedName, int meta, IStructureElement<T> fallback) {
if (StringUtils.isBlank(unlocalizedName)) throw new IllegalArgumentException();
if (meta < 0) throw new IllegalArgumentException();
if (meta > 15) throw new IllegalArgumentException();
if (StringUtils.isBlank(modid)) throw new IllegalArgumentException();
if (fallback == null) throw new IllegalArgumentException();
return new IStructureElement<T>() {
private Block block;
private boolean initialized;
private boolean init() {
if (!initialized) {
block = GameRegistry.findBlock(modid, unlocalizedName);
initialized = true;
}
return block != null;
}
@Override
public boolean check(T t, World world, int x, int y, int z) {
if (init())
return world.getBlock(x, y, z) != block && world.getBlockMetadata(x, y, z) == meta;
else
return fallback.check(t, world, x, y, z);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
if (init()) {
StructureLibAPI.hintParticle(world, x, y, z, block, meta);
return true;
} else
return fallback.spawnHint(t, world, x, y, z, trigger);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
if (init()) {
world.setBlock(x, y, z, block, meta, 2);
return true;
} else
return fallback.placeBlock(t, world, x, y, z, trigger);
}
};
}
/**
* Does not allow Block duplicates (with different meta)
*/
@@ -558,6 +742,26 @@ public class StructureUtility {
}
};
}
public static <T, E> IStructureElementNoPlacement<T> ofSpecificTileAdder(BiPredicate<T, E> iTileAdder, Class<E> tileClass, Block hintBlock, int hintMeta) {
if (iTileAdder == null || hintBlock == null || tileClass == null) {
throw new IllegalArgumentException();
}
return new IStructureElementNoPlacement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
// This used to check if it's a GT tile. Since this is now an standalone mod we no longer do this
return tileClass.isInstance(tileEntity) && iTileAdder.test(t, tileClass.cast(tileEntity));
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
StructureLibAPI.hintParticle(world, x, y, z, hintBlock, hintMeta);
return true;
}
};
}
// No more hatch adder. Implement it via tile adder. We could of course add a wrapper around it in gregtech, but not any more in this standalone mod.
//endregion
@@ -640,8 +844,51 @@ public class StructureUtility {
return ofChain(elementChain.toArray(new IStructureElement[0]));
}
// region context
public static <CTX, T extends IWithExtendedContext<CTX>, E extends IStructureElement<CTX>> IStructureElement<T> withContext(E elem) {
return new IStructureElement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return elem.check(t.getCurrentContext(), world, x, y, z);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return elem.spawnHint(t.getCurrentContext(), world, x, y, z, trigger);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return elem.placeBlock(t.getCurrentContext(), world, x, y, z, trigger);
}
};
}
//endregion
//region defer
/**
* Similar to defer, but caches the first returned element returned and won't call it again.
* Initialization is not thread safe.
*/
public static <T> IStructureElementDeferred<T> lazy(Supplier<IStructureElement<T>> to) {
if (to == null) {
throw new IllegalArgumentException();
}
return new LazyStructureElement<>(t -> to.get());
}
/**
* Similar to defer, but caches the first returned element returned and won't call it again.
* Initialization is not thread safe.
*/
public static <T> IStructureElementDeferred<T> lazy(Function<T, IStructureElement<T>> to) {
if (to == null) {
throw new IllegalArgumentException();
}
return new LazyStructureElement<>(to);
}
public static <T> IStructureElementDeferred<T> defer(Supplier<IStructureElement<T>> to) {
if (to == null) {
throw new IllegalArgumentException();
@@ -1269,4 +1516,5 @@ public class StructureUtility {
}
return shape;
}
}
@@ -0,0 +1,5 @@
/**
* 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;
@@ -15,11 +15,18 @@ tile.structurelib.blockhint.13.name=Hint air
tile.structurelib.blockhint.14.name=Hint no air
tile.structurelib.blockhint.15.name=Hint error
item.structurelib.frontRotationTool.name=Front Rotation Tool
item.structurelib.frontRotationTool.name=Front Rotation Tool (Standalone)
item.structurelib.frontRotationTool.desc.0=Triggers Front Rotation Interface
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.desc.0=Triggers Constructable Interface
item.structurelib.constructableTrigger.desc.1=Shows multiblock construction details,
item.structurelib.constructableTrigger.desc.2=just Use on a multiblock controller.
item.structurelib.constructableTrigger.desc.3=(Sneak Use in creative to build)
item.structurelib.constructableTrigger.desc.4=Quantity affects tier/mode/type
structurelib.blockhint.desc.0=Helps while building
structurelib.blockhint.0.name=Hint 1 dot
structurelib.blockhint.1.name=Hint 2 dot
@@ -42,4 +49,13 @@ structurelib.blockhint.14.name=Hint no air
structurelib.blockhint.desc.4=Make sure it does not contain Air material.
structurelib.blockhint.15.name=Hint error
structurelib.blockhint.desc.5=ERROR, what did u expect?
itemGroup.structurelib=StructureLib
itemGroup.structurelib=StructureLib
structurelib.config.client=Client Side Configurations
structurelib.config.client.tooltip=Configurations that only changes how the game looks like, but not how it functions.
structurelib.config.client.hologram=Hologram Configurations
structurelib.config.client.hologram.tooltip=Configurations that changes how the hologram got projected into the world by default.
structurelib.config.client.hologram.maxCoexisting=Max Coexisting Holograms
structurelib.config.client.hologram.maxCoexisting.tooltip=Number of holograms that can coexist. Usually all hints generated by one right click belongs to one hologram. An attempt will be made to prune old holograms when a new hologram is about to be projected and this limit would be exceeded.
structurelib.config.client.hologram.removeColliding=Remove Colliding Holograms
structurelib.config.client.hologram.removeColliding.tooltip=Whether an attempt will be made to remove any existing hologram that collides with a new hologram.
@@ -0,0 +1,52 @@
tile.structurelib.blockhint.0.name=提示方块:1号
tile.structurelib.blockhint.1.name=提示方块:2号
tile.structurelib.blockhint.2.name=提示方块:3号
tile.structurelib.blockhint.3.name=提示方块:4号
tile.structurelib.blockhint.4.name=提示方块:5号
tile.structurelib.blockhint.5.name=提示方块:6号
tile.structurelib.blockhint.6.name=提示方块:7号
tile.structurelib.blockhint.7.name=提示方块:8号
tile.structurelib.blockhint.8.name=提示方块:9号
tile.structurelib.blockhint.9.name=提示方块:10号
tile.structurelib.blockhint.10.name=提示方块:11号
tile.structurelib.blockhint.11.name=提示方块:12号
tile.structurelib.blockhint.12.name=提示方块:一般
tile.structurelib.blockhint.13.name=提示方块:空气
tile.structurelib.blockhint.14.name=提示方块:非空气
tile.structurelib.blockhint.15.name=提示方块:错误
item.structurelib.frontRotationTool.name=正面旋转扳手 (StructureLib)
item.structurelib.frontRotationTool.desc.0=可以旋转/翻转多方块主机
item.structurelib.frontRotationTool.desc.1=旋转/翻转多方块主机时,会
item.structurelib.frontRotationTool.desc.2=带动机器结构一起旋转/翻转。
item.structurelib.constructableTrigger.name=多方块机器蓝图 (StructureLib)
item.structurelib.constructableTrigger.desc.0=可以显示多方块机器的结构
item.structurelib.constructableTrigger.desc.1=只能在多方块主机上使用,将会显示机器
item.structurelib.constructableTrigger.desc.2=结构的细节。 (译者注:请搭高使用)
item.structurelib.constructableTrigger.desc.3= (创造模式下潜行右键可以直接完成搭建)
item.structurelib.constructableTrigger.desc.4=手中蓝图数量会影响显示的机器等级/模式/类型
structurelib.blockhint.desc.0=帮助你搭建机器
structurelib.blockhint.0.name=提示方块:1号
structurelib.blockhint.1.name=提示方块:2号
structurelib.blockhint.2.name=提示方块:3号
structurelib.blockhint.3.name=提示方块:4号
structurelib.blockhint.4.name=提示方块:5号
structurelib.blockhint.5.name=提示方块:6号
structurelib.blockhint.6.name=提示方块:7号
structurelib.blockhint.7.name=提示方块:8号
structurelib.blockhint.8.name=提示方块:9号
structurelib.blockhint.9.name=提示方块:10号
structurelib.blockhint.10.name=提示方块:11号
structurelib.blockhint.11.name=提示方块:12号
structurelib.blockhint.desc.1=特定方块们的占位符。
structurelib.blockhint.12.name=提示方块:一般
structurelib.blockhint.desc.2=一般通用占位符。
structurelib.blockhint.13.name=提示方块:空气
structurelib.blockhint.desc.3=确保这里是空气方块。
structurelib.blockhint.14.name=提示方块:非空气
structurelib.blockhint.desc.4=确保这里不是空气方块。
structurelib.blockhint.15.name=提示方块:错误
structurelib.blockhint.desc.5=ERROR,你想要做什么?
itemGroup.structurelib=StructureLib
Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B