Compare commits

..
8 Commits
Author SHA1 Message Date
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
12 changed files with 308 additions and 10 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
+1 -1
View File
@@ -1,5 +1,5 @@
modGroup = com.gtnewhorizon
modVersion = 1.0.1
modVersion = 1.0.6
modBaseName = StructureLib
forgeVersion = 1.7.10-10.13.4.1614-1.7.10
@@ -3,6 +3,7 @@ package com.gtnewhorizon.structurelib;
import com.gtnewhorizon.structurelib.alignment.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;
@@ -45,6 +46,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)
@@ -58,6 +60,7 @@ public class StructureLib {
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());
}
public static void addClientSideChatMessages(String... messages) {
@@ -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;
}
}
@@ -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.StructureLib.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
}
}
@@ -41,7 +41,7 @@ public class ClientProxy extends CommonProxy {
private static IIcon[] createIIconFromBlock(Block block, int meta) {
IIcon[] ret = new IIcon[6];
for (int i = 0; i < 6; i++) {
block.getIcon(i, meta);
ret[i] = block.getIcon(i, meta);
}
return ret;
}
@@ -165,4 +165,8 @@ public interface IStructureDefinition<T> {
}
return true;
}
static <T> StructureDefinition.Builder<T> builder() {
return StructureDefinition.builder();
}
}
@@ -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,15 +5,27 @@ 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 java.util.*;
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.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -175,6 +187,98 @@ public class StructureUtility {
//region block
/**
* 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 +662,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 +764,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 +1436,5 @@ public class StructureUtility {
}
return shape;
}
}
@@ -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 Machine Blueprint (Standalone)
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
Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B