From b9b360b93e8db8556b357c9222302a17d73c1e63 Mon Sep 17 00:00:00 2001 From: reobf <2215595288@qq.com> Date: Tue, 6 Feb 2024 17:04:35 +0800 Subject: [PATCH] update --- .../reobf/proghatches/block/TileIOHub.java | 421 +++++++++++------- .../BufferedDualInputHatch.java | 48 +- .../reobf/proghatches/main/CommonProxy.java | 26 +- .../java/reobf/proghatches/main/Config.java | 9 +- .../java/reobf/proghatches/main/MyMod.java | 5 + ...atternEncodingCiruitSpecialTreatment2.java | 2 - .../main/registration/PHRecipes.java | 2 +- .../reobf/proghatches/oc/ItemAPICard.java | 48 +- .../proghatches/oc/ItemGTRedstoneCard.java | 12 +- .../oc/ItemWirelessPeripheralCard.java | 199 +++++++++ .../oc/TileWirelessPeripheralStation.java | 354 +++++++++++++++ .../oc/WirelessPeripheralManager.java | 38 ++ .../assets/proghatches/lang/en_US.lang | 25 +- .../assets/proghatches/lang/zh_CN.lang | 22 + .../proghatches/textures/blocks/pstation.png | Bin 0 -> 465 bytes .../textures/blocks/pstation_0.png | Bin 0 -> 536 bytes .../textures/blocks/pstation_1.png | Bin 0 -> 621 bytes .../textures/blocks/pstation_1.png.mcmeta | 4 + .../textures/items/peripheral_card.png | Bin 0 -> 425 bytes 19 files changed, 1013 insertions(+), 202 deletions(-) create mode 100644 src/main/java/reobf/proghatches/oc/ItemWirelessPeripheralCard.java create mode 100644 src/main/java/reobf/proghatches/oc/TileWirelessPeripheralStation.java create mode 100644 src/main/java/reobf/proghatches/oc/WirelessPeripheralManager.java create mode 100644 src/main/resources/assets/proghatches/textures/blocks/pstation.png create mode 100644 src/main/resources/assets/proghatches/textures/blocks/pstation_0.png create mode 100644 src/main/resources/assets/proghatches/textures/blocks/pstation_1.png create mode 100644 src/main/resources/assets/proghatches/textures/blocks/pstation_1.png.mcmeta create mode 100644 src/main/resources/assets/proghatches/textures/items/peripheral_card.png diff --git a/src/main/java/reobf/proghatches/block/TileIOHub.java b/src/main/java/reobf/proghatches/block/TileIOHub.java index 2c59d53..70e223b 100644 --- a/src/main/java/reobf/proghatches/block/TileIOHub.java +++ b/src/main/java/reobf/proghatches/block/TileIOHub.java @@ -9,6 +9,7 @@ import li.cil.oc.util.DatabaseAccess$; import li.cil.oc.util.ExtendedArguments.ExtendedArguments; import net.minecraft.item.ItemStack; +import net.minecraft.launchwrapper.LaunchClassLoader; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; @@ -58,16 +59,29 @@ import static gregtech.api.enums.GT_Values.NW; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.invoke.MethodType; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.security.CodeSource; +import java.security.SecureClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -78,10 +92,13 @@ import java.util.Optional; import java.util.Spliterators; import java.util.WeakHashMap; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.IntStream; import java.util.stream.StreamSupport; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; @@ -173,14 +190,19 @@ import li.cil.oc.api.machine.Callback; import li.cil.oc.api.machine.Context; import li.cil.oc.api.network.Component; +import li.cil.oc.api.network.Connector; import li.cil.oc.api.network.ManagedEnvironment; import li.cil.oc.api.network.Message; import li.cil.oc.api.network.Node; import li.cil.oc.api.network.Visibility; +import li.cil.oc.api.prefab.AbstractValue; import li.cil.oc.api.prefab.ItemStackArrayValue; import li.cil.oc.api.internal.Database; +import li.cil.oc.common.tileentity.Case; import li.cil.oc.common.tileentity.DiskDrive; +import li.cil.oc.common.tileentity.Robot; import li.cil.oc.common.tileentity.traits.ComponentInventory; +import li.cil.oc.common.tileentity.traits.Computer; import li.cil.oc.common.tileentity.traits.Environment; import li.cil.oc.util.BlockPosition; import li.cil.oc.util.InventorySource; @@ -211,6 +233,7 @@ public class TileIOHub extends TileEntity implements public TileIOHub(){ + } @@ -239,14 +262,16 @@ public void onDisconnect(Node node) { } boolean init; public void updateEntity() { - + dead=false; super.updateEntity(); - if(init==false){getProxy().onReady();init=true;} + if(init==false){ + getProxy().onReady();init=true; - if (node != null && node.network() == null) { + if (node != null ) { li.cil.oc.api.Network.joinOrCreateNetwork(this); - } + } + } if (node != null && node.network() != null) { subapi.values().stream().filter(s->s.node().network()==null).forEach(s->node.connect(s.node())); } @@ -269,7 +294,7 @@ public void invalidate() { @Override public boolean canUpdate() { - dead=false; + return true; } @@ -331,41 +356,36 @@ public void gridChanged() { } - - @Callback(doc = "function():string -- Returns the custom name of this IO Hub, or 'IOHub' if absent. Use quartz cutter to (re-)name.") - public Object[] getName(final Context context, final Arguments args) { - return new Object[]{this.getInventoryName()}; - } - @Callback(doc = "function():address -- Returns the address of API component provided by IO Hub(all API).") - public Object[] getAllAPI(final Context context, final Arguments args) { - return new Object[]{subapi.get("all").node().address()}; - } + + Map subapi=new HashMap<>(); - static private HashMap> cache=new HashMap<>(); - Component node;{ + static private HashMap> cache=new HashMap<>(); + Connector node;{ node=li.cil.oc.api.Network.newNode(this, Visibility.Network). - withComponent("iohub"). + withConnector(). + // withComponent("iohub"). create(); - subapi.put("all",new OCApi("iohub_all")); + subapi.put("all",new OCApi("iohub")); - subapi.put("item",(li.cil.oc.api.network.Environment) - getFilteredClass("item").apply("iohub_item")); + /* + subapi.put("item", + (li.cil.oc.api.network.Environment) getFilteredClass("item").apply("iohub_item", this)); - subapi.put("fluid",(li.cil.oc.api.network.Environment) - getFilteredClass("fluid").apply("iohub_fluid")); + subapi.put("fluid", + (li.cil.oc.api.network.Environment) getFilteredClass("fluid").apply("iohub_fluid", this)); - subapi.put("ae",(li.cil.oc.api.network.Environment) - getFilteredClass("ae").apply("iohub_ae")); - } - private Function getFilteredClass(String filter){ + subapi.put("ae", + (li.cil.oc.api.network.Environment) getFilteredClass("ae").apply("iohub_ae", this)); + */} + private static BiFunction getFilteredClass(String filter){ if(cache.containsKey(filter)){return cache.get(filter);} Class ev= filterAPI(filter); - cache.put(filter,arg-> + cache.put(filter,(arg,arg2)-> { try { - return ev.getConstructor(TileIOHub.class,String.class).newInstance(TileIOHub.this,arg); + return ev.getConstructor(TileIOHub.class,String.class).newInstance(arg2,arg); } catch (Exception e) { e.printStackTrace(); return null; @@ -381,41 +401,69 @@ private Function getFilteredClass(String filter){ @Retention(value=RetentionPolicy.RUNTIME) public static @interface APIType{String[] value(); } - Function> loader=null; + //Function> loader=null; - private Class load(byte b[]){ - - if(loader==null)//use unsafe to load class + private static Class load(byte b[],String ent,String clz){ + + LaunchClassLoader cl=(LaunchClassLoader) TileIOHub.class.getClassLoader(); + try { - Field f=Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe"); - f.setAccessible(true); - Object un=f.get(null); - Method m=un.getClass().getDeclaredMethod("defineAnonymousClass", Class.class,byte[].class, Object[].class); - loader=by->{try { - return(Class)m.invoke(un,OCApi.class,by,null); - } catch (Exception e) { - e.printStackTrace(); - return null; - }}; - } catch (Exception e) {e.printStackTrace(); + URLStreamHandler handler=new URLStreamHandler() { + /* + * NEI will try converting this to URI, return something of legal URI format + */ + @Override + protected String toExternalForm(URL u) { + return "file:/nonexist";//no real file anyway, just to make NEI happy + } + + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new URLConnection(u) { + @Override + public void connect() {} + @Override + public InputStream getInputStream() throws IOException { + + + //System.err.println(u.getPath().substring(u.getPath().indexOf('/')+1)); + if(!u.getPath().substring(u.getPath().indexOf('/')+1).equals(ent)) + throw new IOException(); + + // System.err.println(u.getPath()); + return new ByteArrayInputStream(b); + } + }; + } + }; + cl.addURL(new URL("dyngenclassproghatch", null, -1, Math.abs(ent.hashCode())+"/",handler)); + } catch (MalformedURLException e) { + e.printStackTrace(); } - - if(loader==null)//fall back to normal classloader - loader =new ClassLoader(this.getClass().getClassLoader()) { - public Class load(byte[] clazz){ - return defineClass(null, clazz, 0, clazz.length); - }}::load; - - return loader.apply(b); + try { + return cl.findClass(clz); + } catch (ClassNotFoundException e) { + e.printStackTrace();return null; + } + } - private Class filterAPI(String filter){ + private static Class filterAPI(String filter){ ClassReader cr=null; try { cr=new ClassReader(OCApi.class.getResourceAsStream("/"+OCApi.class.getName().replace('.', '/')+".class")); } catch (IOException e) {throw new RuntimeException("failed to read .class that's not normal",e);} - ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_MAXS|ClassWriter.COMPUTE_FRAMES); + ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_MAXS|ClassWriter.COMPUTE_FRAMES){ + @Override + public int newUTF8(String value) { + value=value.replace("reobf/proghatches/block/TileIOHub$OCApi", + "reobf/proghatches/block/TileIOHub$OCApi"+filter + ); + return super.newUTF8(value); + } + + }; ClassNode cn=new ClassNode(); cr.accept(cn, 0); @@ -430,84 +478,101 @@ private Class filterAPI(String filter){ return b; } ).count(); - if(l>0){ + /* if(l>0){ System.out.println("remove "+s.name); - } + }*/ return l>0; } return false; }); - - // cn.signature=cn.signature.substring(0, cn.signature.length()-1)+"$filtered$"+filter+";"; cn.accept(cw); - return load(cw.toByteArray()); + return load(cw.toByteArray(), + "reobf/proghatches/block/TileIOHub$OCApi"+filter+".class", + "reobf.proghatches.block.TileIOHub$OCApi"+filter + + ); } + // //begin of oc - public class OCApi implements li.cil.oc.api.network.Environment, - WorldInventoryAnalytics,WorldTankAnalytics, + public class OCApi implements + li.cil.oc.api.network.Environment, WorldInventoryAnalytics,WorldTankAnalytics, WorldFluidContainerAnalytics, TankInventoryControl, InventoryAnalytics, MultiTank, InventoryTransfer, FluidContainerTransfer, InventoryControl, TankControl, ItemInventoryControl, InventoryWorldControlMk2, NetworkControl -{ - @Callback(doc = "function(tankSide:number, inventorySide:number, inventorySlot:number [, count:number [, sourceTank:number [, outputSide:number[, outputSlot:number]]]]):boolean, number -- Transfer some fluid from the tank to the container. Returns operation result and filled amount") +{ + @Callback(doc = "function():string -- Returns the custom name of this IO Hub, or 'IOHub' if absent. Use quartz cutter to (re-)name.") + public Object[] getCustomName(final Context context, final Arguments args) { + return new Object[]{TileIOHub.this.getInventoryName()}; + } + @Callback(doc = "function(address:string):boolean -- Swap the inventory between this IO Hub and another IO Hub. Return whether operation successes.") + public Object[] swap(final Context context, final Arguments args) { + + + throw new UnsupportedOperationException("NYI"); + } + + + + @APIType({"fluid"}) + @Callback(doc = "function(tankSide:number, inventorySide:number, inventorySlot:number [, count:number [, sourceTank:number [, outputSide:number[, outputSlot:number]]]]):boolean, number -- Transfer some fluid from the tank to the container. Returns operation result and filled amount") public Object[] transferFluidFromTankToContainer(final Context context, final Arguments args) { return FluidContainerTransfer$class.transferFluidFromTankToContainer(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(inventorySide:number, inventorySlot:number, tankSide:number [, count:number [, outputSide:number[, outputSlot:number]]]):boolean, number -- Transfer some fluid from the container to the tank. Returns operation result and filled amount") public Object[] transferFluidFromContainerToTank(final Context context, final Arguments args) { return FluidContainerTransfer$class.transferFluidFromContainerToTank(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(sourceSide:number, sourceSlot:number, sinkSide:number, sinkSlot:number[, count:number [, sourceOutputSide:number[, sinkOutputSide:number[, sourceOutputSlot:number[, sinkOutputSlot:number]]]]]):boolean, number -- Transfer some fluid from a container to another container. Returns operation result and filled amount") public Object[] transferFluidBetweenContainers(final Context context, final Arguments args) { return FluidContainerTransfer$class.transferFluidBetweenContainers(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(sourceSide:number, sinkSide:number[, count:number[, sourceSlot:number[, sinkSlot:number]]]):number -- Transfer some items between two inventories.") public Object[] transferItem(final Context context, final Arguments args) { return InventoryTransfer$class.transferItem(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(sourceSide:number, sinkSide:number[, count:number [, sourceTank:number]]):boolean, number -- Transfer some fluid between two tanks. Returns operation result and filled amount") public Object[] transferFluid(final Context context, final Arguments args) { return InventoryTransfer$class.transferFluid(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number, slot:number):number -- Get the capacity of the fluid container in the specified slot of the inventory on the specified side of the device.") public Object[] getContainerCapacityInSlot(final Context context, final Arguments args) { return WorldFluidContainerAnalytics$class.getContainerCapacityInSlot(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number, slot:number):number -- Get the capacity the fluid container in the specified slot of the inventory on the specified side of the device.") public Object[] getContainerLevelInSlot(final Context context, final Arguments args) { return WorldFluidContainerAnalytics$class.getContainerLevelInSlot(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number, slot:number):table -- Get a description of the fluid in the fluid container in the specified slot of the inventory on the specified side of the device.") public Object[] getFluidInContainerInSlot(final Context context, final Arguments args) { return WorldFluidContainerAnalytics$class.getFluidInContainerInSlot(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number [, tank:number]):number -- Get the amount of fluid in the specified tank on the specified side.") public Object[] getTankLevel(final Context context, final Arguments args) { return WorldTankAnalytics$class.getTankLevel(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number [, tank:number]):number -- Get the capacity of the specified tank on the specified side.") public Object[] getTankCapacity(final Context context, final Arguments args) { return WorldTankAnalytics$class.getTankCapacity(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number [, tank:number]):table -- Get a description of the fluid in the the specified tank on the specified side.") public Object[] getFluidInTank(final Context context, final Arguments args) { return WorldTankAnalytics$class.getFluidInTank(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(side:number):number -- Get the number of tanks available on the specified side.") public Object[] getTankCount(final Context context, final Arguments args) { return WorldTankAnalytics$class.getTankCount(this, context, args); @@ -590,57 +655,64 @@ public ForgeDirection checkSideForAction(Arguments arg0, int arg1) { - + @APIType({"item"}) @Callback(doc = "function(side:number):number -- Get the number of slots in the inventory on the specified side of the device.") public Object[] getInventorySize(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.getInventorySize(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slot:number):number -- Get number of items in the specified slot of the inventory on the specified side of the device.") public Object[] getSlotStackSize(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.getSlotStackSize(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slot:number):number -- Get the maximum number of items in the specified slot of the inventory on the specified side of the device.") public Object[] getSlotMaxStackSize(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.getSlotMaxStackSize(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slotA:number, slotB:number[, checkNBT:boolean=false]):boolean -- Get whether the items in the two specified slots of the inventory on the specified side of the device are of the same type.") public Object[] compareStacks(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.compareStacks(this, context, args); - } + }@APIType({"item"}) @Callback(doc = "function(side:number, slot:number, dbAddress:string, dbSlot:number[, checkNBT:boolean=false]):boolean -- Compare an item in the specified slot in the inventory on the specified side with one in the database with the specified address.") public Object[] compareStackToDatabase(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.compareStackToDatabase(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slotA:number, slotB:number):boolean -- Get whether the items in the two specified slots of the inventory on the specified side of the device are equivalent (have shared OreDictionary IDs).") public Object[] areStacksEquivalent(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.areStacksEquivalent(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slot:number, label:string):boolean -- Change the display name of the stack in the inventory on the specified side of the device.") public Object[] setStackDisplayName(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.setStackDisplayName(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slot:number):table -- Get a description of the stack in the inventory on the specified side of the device.") public Object[] getStackInSlot(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.getStackInSlot(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number):userdata -- Get a description of all stacks in the inventory on the specified side of the device.") public Object[] getAllStacks(final Context context, final Arguments args) { - return WorldInventoryAnalytics$class.getAllStacks(this, context, args); + try{return WorldInventoryAnalytics$class.getAllStacks(this, context, args);} + catch(Exception e){ + e.printStackTrace(); + throw e; + + } + + } - + @Callback(doc = "function(side:number):string -- Get the the name of the inventory on the specified side of the device.") public Object[] getInventoryName(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.getInventoryName(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(side:number, slot:number, dbAddress:string, dbSlot:number):boolean -- Store an item stack description in the specified slot of the database with the specified address.") public Object[] store(final Context context, final Arguments args) { return WorldInventoryAnalytics$class.store(this, context, args); @@ -648,51 +720,51 @@ public Object[] store(final Context context, final Arguments args) { - + @APIType({"fluid"}) @Callback(doc = "function([slot:number]):number -- Get the amount of fluid in the tank item in the specified slot or the selected slot.") public Object[] getTankLevelInSlot(final Context context, final Arguments args) { return TankInventoryControl$class.getTankLevelInSlot(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function([slot:number]):number -- Get the capacity of the tank item in the specified slot of the robot or the selected slot.") public Object[] getTankCapacityInSlot(final Context context, final Arguments args) { return TankInventoryControl$class.getTankCapacityInSlot(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function([slot:number]):table -- Get a description of the fluid in the tank item in the specified slot or the selected slot.") public Object[] getFluidInTankInSlot(final Context context, final Arguments args) { return TankInventoryControl$class.getFluidInTankInSlot(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function([tank:number]):table -- Get a description of the fluid in the tank in the specified slot or the selected slot.") public Object[] getFluidInInternalTank(final Context context, final Arguments args) { return TankInventoryControl$class.getFluidInInternalTank(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function([amount:number]):boolean -- Transfers fluid from a tank in the selected inventory slot to the selected tank.") public Object[] drain(final Context context, final Arguments args) { return TankInventoryControl$class.drain(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function([amount:number]):boolean -- Transfers fluid from the selected tank to a tank in the selected inventory slot.") public Object[] fill(final Context context, final Arguments args) { return TankInventoryControl$class.fill(this, context, args); - } + }@APIType({"item"}) @Callback(doc = "function([slot:number]):table -- Get a description of the stack in the specified slot or the selected slot.") public Object[] getStackInInternalSlot(final Context context, final Arguments args) { return InventoryAnalytics$class.getStackInInternalSlot(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(otherSlot:number):boolean -- Get whether the stack in the selected slot is equivalent to the item in the specified slot (have shared OreDictionary IDs).") public Object[] isEquivalentTo(final Context context, final Arguments args) { return InventoryAnalytics$class.isEquivalentTo(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(slot:number, dbAddress:string, dbSlot:number):boolean -- an item stack description in the specified slot of the database with the specified address.") public Object[] storeInternal(final Context context, final Arguments args) { return InventoryAnalytics$class.storeInternal(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(slot:number, dbAddress:string, dbSlot:number[, checkNBT:boolean=false]):boolean -- Compare an item in the specified slot with one in the database with the specified address.") public Object[] compareToDatabase(final Context context, final Arguments args) { return InventoryAnalytics$class.compareToDatabase(this, context, args); @@ -822,94 +894,96 @@ public IFluidTank getFluidTank(int index) { ///robot - + @APIType({"fluid"}) @Callback(doc = "function():number -- The number of tanks installed in the device.") public Object[] tankCount(final Context context, final Arguments args) { return TankControl$class.tankCount(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function([index:number]):number -- Select a tank and/or get the number of the currently selected tank.") public Object[] selectTank(final Context context, final Arguments args) { int i=args.checkInteger(0); this.selectedTank_$eq(i); return new Object[]{i}; } - + @APIType({"fluid"}) @Callback(direct = true, doc = "function([index:number]):number -- Get the fluid amount in the specified or selected tank.") public Object[] tankLevel(final Context context, final Arguments args) { return TankControl$class.tankLevel(this, context, args); } - + @APIType({"fluid"}) @Callback(direct = true, doc = "function([index:number]):number -- Get the remaining fluid capacity in the specified or selected tank.") public Object[] tankSpace(final Context context, final Arguments args) { return TankControl$class.tankSpace(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(index:number):boolean -- Compares the fluids in the selected and the specified tank. Returns true if equal.") public Object[] compareFluidTo(final Context context, final Arguments args) { return TankControl$class.compareFluidTo(this, context, args); } - + @APIType({"fluid"}) @Callback(doc = "function(index:number[, count:number=1000]):boolean -- Move the specified amount of fluid from the selected tank into the specified tank.") public Object[] transferFluidTo(final Context context, final Arguments args) { return TankControl$class.transferFluidTo(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function([slot:number]):number -- Get the currently selected slot; set the selected slot if specified.") public Object[] select(final Context context, final Arguments args) { int i=args.checkInteger(0); this.selectedSlot_$eq(i); return new Object[]{i}; } - + @APIType({"item"}) @Callback(direct = true, doc = "function([slot:number]):number -- Get the number of items in the specified slot, otherwise in the selected slot.") public Object[] count(final Context context, final Arguments args) { return InventoryControl$class.count(this, context, args); } - + @APIType({"item"}) @Callback(direct = true, doc = "function([slot:number]):number -- Get the remaining space in the specified slot, otherwise in the selected slot.") public Object[] space(final Context context, final Arguments args) { - return InventoryControl$class.space(this, context, args); + + System.out.println(this.inventory().getInventoryStackLimit()); + return InventoryControl$class.space(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(otherSlot:number[, checkNBT:boolean=false]):boolean -- Compare the contents of the selected slot to the contents of the specified slot.") public Object[] compareTo(final Context context, final Arguments args) { return InventoryControl$class.compareTo(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(toSlot:number[, amount:number]):boolean -- Move up to the specified amount of items from the selected slot into the specified slot.") public Object[] transferTo(final Context context, final Arguments args) { return InventoryControl$class.transferTo(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function():number -- The size of this device's internal inventory.") public Object[] inventorySize(final Context context, final Arguments args) { return InventoryControl$class.inventorySize(this, context, args); - } + }@APIType({"item"}) @Callback(doc = "function(slot:number):number -- The size of an item inventory in the specified slot.") public Object[] getItemInventorySize(final Context context, final Arguments args) { return ItemInventoryControl$class.getItemInventorySize(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(inventorySlot:number, slot:number[, count:number=64]):number -- Drops an item into the specified slot in the item inventory.") public Object[] dropIntoItemInventory(final Context context, final Arguments args) { return ItemInventoryControl$class.dropIntoItemInventory(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(inventorySlot:number, slot:number[, count:number=64]):number -- Sucks an item out of the specified slot in the item inventory.") public Object[] suckFromItemInventory(final Context context, final Arguments args) { return ItemInventoryControl$class.suckFromItemInventory(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(facing:number, slot:number[, count:number[, fromSide:number]]):boolean -- Drops the selected item stack into the specified slot of an inventory.") public Object[] dropIntoSlot(final Context context, final Arguments args) { return InventoryWorldControlMk2$class.dropIntoSlot(this, context, args); } - + @APIType({"item"}) @Callback(doc = "function(facing:number, slot:number[, count:number[, fromSide:number]]):boolean -- Sucks items from the specified slot of an inventory.") public Object[] suckFromSlot(final Context context, final Arguments args) { return InventoryWorldControlMk2$class.suckFromSlot(this, context, args); @@ -918,56 +992,63 @@ public Object[] suckFromSlot(final Context context, final Arguments args) { //AE COMPAT + @APIType({"ae"}) + @Callback(doc="function():boolean -- Always return true since it needs no Security Terminal.") + public Object[] isLinked(final Context context, final Arguments args) { + return new Object[]{true}; + } + + @APIType({"ae"}) @Callback(doc = "function():table -- Get a list of tables representing the available CPUs in the network.") public Object[] getCpus(final Context context, final Arguments args) { return NetworkControl$class.getCpus(this, context, args); } - + @APIType({"ae"}) @Callback(doc = "function([filter:table]):table -- Get a list of known item recipes. These can be used to issue crafting requests.") public Object[] getCraftables(final Context context, final Arguments args) { return NetworkControl$class.getCraftables(this, context, args); } - + @APIType({"item","ae"}) @Callback(doc = "function([filter:table]):table -- Get a list of the stored items in the network.") public Object[] getItemsInNetwork(final Context context, final Arguments args) { return NetworkControl$class.getItemsInNetwork(this, context, args); } - @APIType("item") + @APIType({"item","ae"}) @Callback(doc = "function():userdata -- Get an iterator object for the list of the items in the network.") public Object[] allItems(final Context context, final Arguments args) { return NetworkControl$class.allItems(this, context, args); } - + @APIType({"item","ae"}) @Callback(doc = "function(filter:table, dbAddress:string[, startSlot:number[, count:number]]): Boolean -- Store items in the network matching the specified filter in the database with the specified address.") public Object[] storeAE(final Context context, final Arguments args) { return NetworkControl$class.store(this, context, args); } - + @APIType({"fluid","ae"}) @Callback(doc = "function():table -- Get a list of the stored fluids in the network.") public Object[] getFluidsInNetwork(final Context context, final Arguments args) { return NetworkControl$class.getFluidsInNetwork(this, context, args); } - + @APIType({"ae"}) @Callback(doc = "function():number -- Get the average power injection into the network.") public Object[] getAvgPowerInjection(final Context context, final Arguments args) { return NetworkControl$class.getAvgPowerInjection(this, context, args); } - + @APIType({"ae"}) @Callback(doc = "function():number -- Get the average power usage of the network.") public Object[] getAvgPowerUsage(final Context context, final Arguments args) { return NetworkControl$class.getAvgPowerUsage(this, context, args); } - + @APIType({"ae"}) @Callback(doc = "function():number -- Get the idle power usage of the network.") public Object[] getIdlePowerUsage(final Context context, final Arguments args) { return NetworkControl$class.getIdlePowerUsage(this, context, args); } - + @APIType({"ae"}) @Callback(doc = "function():number -- Get the maximum stored power in the network.") public Object[] getMaxStoredPower(final Context context, final Arguments args) { return NetworkControl$class.getMaxStoredPower(this, context, args); } - + @APIType({"ae"}) @Callback(doc = "function():number -- Get the stored power in the network. ") public Object[] getStoredPower(final Context context, final Arguments args) { return NetworkControl$class.getStoredPower(this, context, args); @@ -1001,7 +1082,7 @@ public IMEMonitor getItemInventory() { } return (IMEMonitor)storage.getItemInventory(); } - + @APIType({"item","ae"}) @Callback(doc = "function([number:amount]):number -- Transfer selected items to your ae system.") public Object[] sendItems(final Context context, final Arguments args) { @@ -1041,7 +1122,7 @@ public Object[] sendItems(final Context context, final Arguments args) { } return array; } - + @APIType({"item","ae"}) @Callback(doc = "function(database:address, entry:number[, number:amount]):number -- Get items from your ae system.") public Object[] requestItems(final Context context, final Arguments args) { final String address = args.checkString(0); @@ -1115,7 +1196,7 @@ public IMEMonitor getFluidInventory() { return null; } return (IMEMonitor)storage.getFluidInventory(); - } + }@APIType({"fluid","ae"}) @Callback(doc = "function([number:amount]):number -- Transfer selected fluid to your ae system.") public Object[] sendFluids(final Context context, final Arguments args) { final int selected =selectedTank(); @@ -1147,7 +1228,7 @@ public Object[] sendFluids(final Context context, final Arguments args) { - + @APIType({"fluid","ae"}) @Callback(doc = "function(database:address, entry:number[, number:amount]):number -- Get fluid from your ae system.") public Object[] requestFluids(final Context context, final Arguments args) { final String address = args.checkString(0); @@ -1188,48 +1269,48 @@ public Object[] requestFluids(final Context context, final Arguments args) { } return new Object[] {tank.fill(extracted.getFluidStack(), true)}; } + public OCApi(String s) { + + name=s; + node=li.cil.oc.api.Network.newNode(this, Visibility.Network). + withComponent(name). + + create(); + + }final String name; @Override public Node node() { return node; } - public OCApi(String s) { - name=s; - node=li.cil.oc.api.Network.newNode(this, Visibility.Network). - withComponent(name). - create(); - }final String name; - Component node - ; - /*@Override - public Node node() { - - return TileIOHub.this.node(); - }*/ - - @Override - public void onConnect(Node node) { - - - } - - @Override - public void onDisconnect(Node node) { - - - } - - @Override - public void onMessage(Message message) { - - - } + + + Component node; + + @Override + public void onConnect(Node node) { + // TODO Auto-generated method stub + + } + @Override + public void onDisconnect(Node node) { + // TODO Auto-generated method stub + + } + @Override + public void onMessage(Message message) { + // TODO Auto-generated method stub + + } + + + //end of oc +} + - } -//end of oc @@ -1425,10 +1506,10 @@ public void readFromNBT(NBTTagCompound compound) { getProxy().readFromNBT(compound); NBTTagCompound nd=(NBTTagCompound) compound.getTag("mainNode"); - if(nd!=null)node.load(nd); + if(nd!=null&&node!=null)node.load(nd); for( Entry ent:subapi.entrySet()){ nd=(NBTTagCompound) compound.getTag(ent.getKey()); - if(nd!=null) + if(nd!=null&&ent.getValue().node()!=null) ent.getValue().node().load(nd); } super.readFromNBT(compound); @@ -1447,14 +1528,20 @@ public void writeToNBT(NBTTagCompound compound) { compound.setInteger("tankselected", tankselected); getProxy().writeToNBT(compound); - NBTTagCompound nd=new NBTTagCompound(); + + + final NBTTagCompound nd=new NBTTagCompound(); compound.setTag("mainNode", nd); - node.save(nd); + + Optional.ofNullable(node).ifPresent(s->s.save(nd)); + for( Entry ent:subapi.entrySet()){ - nd=new NBTTagCompound(); - compound.setTag(ent.getKey(), nd); - ent.getValue().node().save(nd); + final NBTTagCompound nd0=new NBTTagCompound(); + compound.setTag(ent.getKey(), nd0); + Optional.ofNullable(ent.getValue().node()).ifPresent(s->s.save(nd0)); } + + super.writeToNBT(compound); } diff --git a/src/main/java/reobf/proghatches/gt/metatileentity/BufferedDualInputHatch.java b/src/main/java/reobf/proghatches/gt/metatileentity/BufferedDualInputHatch.java index a293511..d7ddc3c 100644 --- a/src/main/java/reobf/proghatches/gt/metatileentity/BufferedDualInputHatch.java +++ b/src/main/java/reobf/proghatches/gt/metatileentity/BufferedDualInputHatch.java @@ -28,6 +28,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; @@ -45,6 +46,7 @@ import com.gtnewhorizons.modularui.api.screen.ModularWindow; import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; import com.gtnewhorizons.modularui.api.widget.Widget; import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot; import com.gtnewhorizons.modularui.common.widget.ButtonWidget; @@ -58,10 +60,13 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.enums.SoundResource; import gregtech.api.gui.modularui.GT_UITextures; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.interfaces.tileentity.IMachineProgress; import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_OutputBus; import gregtech.api.util.GT_TooltipDataCache.TooltipData; import gregtech.api.util.GT_Utility; import gregtech.api.util.extensions.ArrayExt; @@ -608,16 +613,18 @@ public static class CallerCheck { public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { super.onPostTick(aBaseMetaTileEntity, aTick); if (aBaseMetaTileEntity.getWorld().isRemote) return; + + if(this.getBaseMetaTileEntity().isAllowedToWork()) for (DualInvBuffer inv0 : this.sortByEmpty()) { if (inv0.full() == false) { inv0.recordRecipeOrCalssify(this.mStoredFluid, mInventory); inv0.classify(this.mStoredFluid, mInventory); } } + // BaseMetaTileEntity h; // h.add4by4Slots(builder, background); - - } + } @Override public ItemStack getStackInSlot(int aIndex) { @@ -814,7 +821,7 @@ private Widget createButtonBuffer(int id) { protected ModularWindow createWindow(final EntityPlayer player, int index) { DualInvBuffer inv0 = this.inv0.get(index); - final int WIDTH = 18 * 6 + 6; + final int WIDTH = 18 * 6 + 6; final int HEIGHT = 18 * 4 + 6; final int PARENT_WIDTH = getGUIWidth(); final int PARENT_HEIGHT = getGUIHeight(); @@ -956,7 +963,37 @@ private NBTTagCompound cv(String s) { return new NBTTagCompound(); } } - + ButtonWidget createPowerSwitchButton(IWidgetBuilder builder) {IGregTechTileEntity thiz=this.getBaseMetaTileEntity(); + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + + if (thiz.isAllowedToWork()) { + thiz.disableWorking(); + } else { + thiz.enableWorking(); + } + }) + .setPlayClickSoundResource( () -> thiz.isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation + : SoundResource.GUI_BUTTON_DOWN.resourceLocation + ) + .setBackground(() -> { + if (thiz.isAllowedToWork()) { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED, + GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON }; + } else { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, + GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF }; + } + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(thiz::isAllowedToWork, val -> { + if (val) thiz.enableWorking(); + else thiz.disableWorking(); + }), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(new Pos2d(getGUIWidth()-18-6,3)) + .setSize(16, 16); + return (ButtonWidget) button; + } @Override public void addUIWidgets(Builder builder, UIBuildContext buildContext) { @@ -966,6 +1003,9 @@ public void addUIWidgets(Builder builder, UIBuildContext buildContext) { builder.widget(createButtonBuffer(i)); } + + builder.widget(createPowerSwitchButton(builder)); + super.addUIWidgets(builder, buildContext); // builder.widget(widget); diff --git a/src/main/java/reobf/proghatches/main/CommonProxy.java b/src/main/java/reobf/proghatches/main/CommonProxy.java index aefcb0a..367d68e 100644 --- a/src/main/java/reobf/proghatches/main/CommonProxy.java +++ b/src/main/java/reobf/proghatches/main/CommonProxy.java @@ -8,11 +8,13 @@ import com.google.common.base.Optional; import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLInterModComms; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.registry.GameRegistry; import gregtech.api.util.GT_ModHandler; +import mcp.mobius.waila.api.IWailaRegistrar; import reobf.proghatches.Tags; import reobf.proghatches.block.BlockIOHub; import reobf.proghatches.block.ItemBlockIOHub; @@ -27,6 +29,8 @@ import reobf.proghatches.main.registration.Registration; import reobf.proghatches.oc.ItemAPICard; import reobf.proghatches.oc.ItemGTRedstoneCard; +import reobf.proghatches.oc.ItemWirelessPeripheralCard; +import reobf.proghatches.oc.TileWirelessPeripheralStation; public class CommonProxy { @@ -40,7 +44,7 @@ public void preInit(FMLPreInitializationEvent event) { MyMod.LOG.info("I am " + Tags.MODNAME + " at version " + Tags.VERSION); GameRegistry.registerTileEntity(TileIOHub.class, "proghatches.iohub"); - + GameRegistry.registerTileEntity(TileWirelessPeripheralStation.class, "proghatches.peripheral_station"); GameRegistry.registerItem( MyMod.progcircuit = new ItemProgrammingCircuit().setUnlocalizedName("prog_circuit") .setTextureName("?"), @@ -71,15 +75,22 @@ public void preInit(FMLPreInitializationEvent event) { .setUnlocalizedName("proghatches.oc.api") .setTextureName("proghatches:APIcard"), "proghatches.oc.api"); - + GameRegistry.registerItem( + MyMod.pitem = new ItemWirelessPeripheralCard().setMaxStackSize(1) + .setUnlocalizedName("proghatches.oc.peripheral_card") + .setTextureName("proghatches:peripheral_card"), + "proghatches.oc.peripheral_card"); MyMod.iohub =GameRegistry.registerBlock( new BlockIOHub(),ItemBlockIOHub.class,"proghatches.iohub"); - + MyMod.pstation =GameRegistry.registerBlock( + new TileWirelessPeripheralStation.Block(),TileWirelessPeripheralStation.ItemBlock.class,"proghatches.peripheral_station"); li.cil.oc.server.driver.Registry.add((li.cil.oc.api.driver.Item) MyMod.oc_redstone); li.cil.oc.server.driver.Registry.add((li.cil.oc.api.driver.Item) MyMod.oc_api); - // li.cil.oc.server.driver.Registry.add((li.cil.oc.api.driver.Block)MyMod.iohub); + li.cil.oc.server.driver.Registry.add((li.cil.oc.api.driver.Item) MyMod.pitem); GT_ModHandler.addToRecyclerBlackList(new ItemStack(MyMod.progcircuit)); + FMLInterModComms.sendMessage("Waila", "register", "reobf.proghatches.main.CommonProxy.callbackRegister"); + } public static ProgHatchCreativeTab tab; @@ -95,9 +106,12 @@ public void init(FMLInitializationEvent event) { public void postInit(FMLPostInitializationEvent event) { new PHRecipes().run(); - + + } + public static void callbackRegister(IWailaRegistrar registrar) { + registrar.registerBodyProvider(TileWirelessPeripheralStation.provider, MyMod.pstation.getClass()); + registrar.registerNBTProvider(TileWirelessPeripheralStation.provider, MyMod.pstation.getClass()); } - // register server commands in this event handler (Remove if not needed) public void serverStarting(FMLServerStartingEvent event) {} } diff --git a/src/main/java/reobf/proghatches/main/Config.java b/src/main/java/reobf/proghatches/main/Config.java index 4060231..dcfcde1 100644 --- a/src/main/java/reobf/proghatches/main/Config.java +++ b/src/main/java/reobf/proghatches/main/Config.java @@ -10,12 +10,15 @@ public class Config { public static String greeting = "Hello World"; public static int metaTileEntityOffset = 22000; - + public static boolean skipRecipeAdding; public static void synchronizeConfiguration(File configFile) { Configuration configuration = new Configuration(configFile); - greeting = configuration.getString("greeting", Configuration.CATEGORY_GENERAL, greeting, "How shall I greet?"); - + // greeting = configuration.getString("greeting", Configuration.CATEGORY_GENERAL, greeting, "How shall I greet?"); + metaTileEntityOffset= configuration.getInt("MetaTEOffset", "ID", metaTileEntityOffset, 14301, 29999, "The GT MetaTE ID used by this mod, will use range:[offset,offset+200], make sure it's in [14301,14999] or [17000,29999]"); + configuration.addCustomCategoryComment("ID", "Configurable ID settings, DO NOT change it until necessary."); + skipRecipeAdding= configuration.getBoolean("skipRecipeAddition", Configuration.CATEGORY_GENERAL, skipRecipeAdding, "If true, this mod will not add any recipe."); + if (configuration.hasChanged()) { configuration.save(); } diff --git a/src/main/java/reobf/proghatches/main/MyMod.java b/src/main/java/reobf/proghatches/main/MyMod.java index a49eee3..3825c4f 100644 --- a/src/main/java/reobf/proghatches/main/MyMod.java +++ b/src/main/java/reobf/proghatches/main/MyMod.java @@ -23,6 +23,7 @@ import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; import reobf.proghatches.Tags; import reobf.proghatches.block.TileIOHub.OCApi; +import reobf.proghatches.oc.WirelessPeripheralManager; import reobf.proghatches.util.ProghatchesUtil; @Mod(modid = Tags.MODID, version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.7.10]" @@ -45,6 +46,8 @@ public class MyMod { public static Item oc_redstone; public static Item oc_api; public static Block iohub; + public static Block pstation; + public static Item pitem; @Mod.EventHandler // preInit "Run before anything else. Read your config, create blocks, items, etc, and register them with the @@ -92,6 +95,8 @@ public void postInit(FMLPostInitializationEvent event) { // register server commands in this event handler (Remove if not needed) public void serverStarting(FMLServerStartingEvent event) { proxy.serverStarting(event); + WirelessPeripheralManager.stations.clear(); + WirelessPeripheralManager.cards.clear(); } public static ItemStack tutorial() { diff --git a/src/main/java/reobf/proghatches/main/mixin/mixins/MixinPatternEncodingCiruitSpecialTreatment2.java b/src/main/java/reobf/proghatches/main/mixin/mixins/MixinPatternEncodingCiruitSpecialTreatment2.java index fb6d198..08717a6 100644 --- a/src/main/java/reobf/proghatches/main/mixin/mixins/MixinPatternEncodingCiruitSpecialTreatment2.java +++ b/src/main/java/reobf/proghatches/main/mixin/mixins/MixinPatternEncodingCiruitSpecialTreatment2.java @@ -97,8 +97,6 @@ private List g(List c) { * Iterator ii, PositionedStack iii){ * } * 牛的 mixin还能混出VerifyError - * 真想直接上coremod了 - * 我不用localcapture还不行吗 * cpw.mods.fml.common.LoaderException: java.lang.VerifyError: Bad local variable type * Exception Details: * Location: diff --git a/src/main/java/reobf/proghatches/main/registration/PHRecipes.java b/src/main/java/reobf/proghatches/main/registration/PHRecipes.java index 9a2ca78..1c27113 100644 --- a/src/main/java/reobf/proghatches/main/registration/PHRecipes.java +++ b/src/main/java/reobf/proghatches/main/registration/PHRecipes.java @@ -75,7 +75,7 @@ public class PHRecipes implements Runnable { public void run() { - +if(Config.skipRecipeAdding)return; ArrayList pc0 = new ArrayList<>(); HashMapproductivity */> pc = new HashMap<>();// List> diff --git a/src/main/java/reobf/proghatches/oc/ItemAPICard.java b/src/main/java/reobf/proghatches/oc/ItemAPICard.java index 56ab087..eeaebee 100644 --- a/src/main/java/reobf/proghatches/oc/ItemAPICard.java +++ b/src/main/java/reobf/proghatches/oc/ItemAPICard.java @@ -1,13 +1,18 @@ package reobf.proghatches.oc; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.StatCollector; import net.minecraftforge.oredict.OreDictionary; @@ -87,8 +92,27 @@ public Node node() { return _node; } + @Callback(doc = "getID(tag:string):table --parse binary deflated NBT tag as readable table", direct = false) + public Object[] getTag(final Context context, final Arguments args) { + + try { + + + return new Object[] { CompressedStreamTools.readCompressed(new ByteArrayInputStream( + //args.checkString(0)).getBytes() will truncate byte to 0~127 + //have no idea why that happens + (byte[]) args.checkAny(0)) + ) + }; + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("format error"); + } + + //return new Object[] { }; - @Callback(doc = "getID(database:address,index:number) --get item ID in number", direct = false) + } + @Callback(doc = "getID(database:address,index:number):string --get item ID in number", direct = false) public Object[] getID(final Context context, final Arguments args) { Node n = node().network() .node(args.checkString(0)); @@ -106,7 +130,7 @@ public Object[] getID(final Context context, final Arguments args) { // database.GET } - @Callback(doc = "getOreDict(database:address,index:number) --get OreDicts", direct = false) + @Callback(doc = "getOreDict(database:address,index:number):string --get OreDicts", direct = false) public Object[] getOreDict(final Context context, final Arguments args) { Node n = node().network() .node(args.checkString(0)); @@ -135,7 +159,7 @@ public Object[] getOreDict(final Context context, final Arguments args) { } @Callback( - doc = "match(database:address,index:number,regex:string[,mode:string]) --check with regex to see if target has OreDict, 'mode' can be 'find'(default) or 'match'", + doc = "match(database:address,index:number,regex:string[,mode:string]):boolean --check with regex to see if target has OreDict, 'mode' can be 'find'(default) or 'match'", direct = false) public Object[] match(final Context context, final Arguments args) { Node n = node().network() @@ -176,13 +200,13 @@ public Object[] match(final Context context, final Arguments args) { // database.GET } - @Callback(doc = "nameToID(name:string) --string ID -> number ID", direct = false) + @Callback(doc = "nameToID(name:string):int --string ID -> number ID", direct = false) public Object[] nameToID(final Context context, final Arguments args) { return new Object[] { Item.getIdFromItem((Item) itemRegistry.getObject(args.checkString(0))) }; } - @Callback(doc = "idToName(id:number) --number ID -> string ID", direct = false) + @Callback(doc = "idToName(id:number):string --number ID -> string ID", direct = false) public Object[] idToName(final Context context, final Arguments args) { return new Object[] { itemRegistry.getNameForObject(Item.getItemById(args.checkInteger(0))) }; @@ -197,30 +221,30 @@ public void onConnect(Node node) { @Override public void onDisconnect(Node node) { - // System.out.println("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"); + } @Override public void onMessage(Message message) { - // TODO Auto-generated method stub + } @Override public void load(NBTTagCompound nbt) { - // TODO Auto-generated method stub + Optional.ofNullable(nbt.getTag("node")).ifPresent(s->{if(node()!=null)node().load((NBTTagCompound) s);}); } - @Override public void save(NBTTagCompound nbt) { - // TODO Auto-generated method stub - + NBTTagCompound t=new NBTTagCompound(); + Optional.ofNullable(node()).ifPresent(s->s.save(t)); + nbt.setTag("node", t); } @Override public boolean canUpdate() { - // TODO Auto-generated method stub + return false; } diff --git a/src/main/java/reobf/proghatches/oc/ItemGTRedstoneCard.java b/src/main/java/reobf/proghatches/oc/ItemGTRedstoneCard.java index 1cf278c..35fdaac 100644 --- a/src/main/java/reobf/proghatches/oc/ItemGTRedstoneCard.java +++ b/src/main/java/reobf/proghatches/oc/ItemGTRedstoneCard.java @@ -194,14 +194,14 @@ public void onMessage(Message message) { @Override public void load(NBTTagCompound nbt) { - // TODO Auto-generated method stub + Optional.ofNullable(nbt.getTag("node")).ifPresent(s->{if(node()!=null)node().load((NBTTagCompound) s);}); } - @Override public void save(NBTTagCompound nbt) { - // TODO Auto-generated method stub - + NBTTagCompound t=new NBTTagCompound(); + Optional.ofNullable(node()).ifPresent(s->s.save(t)); + nbt.setTag("node", t); } @Override @@ -212,14 +212,14 @@ public boolean canUpdate() { @Override public void update() { - // TODO Auto-generated method stub + } } @Override public String slot(ItemStack stack) { - // TODO Auto-generated method stub + return li.cil.oc.common.Slot.Card(); } diff --git a/src/main/java/reobf/proghatches/oc/ItemWirelessPeripheralCard.java b/src/main/java/reobf/proghatches/oc/ItemWirelessPeripheralCard.java new file mode 100644 index 0000000..5736cfe --- /dev/null +++ b/src/main/java/reobf/proghatches/oc/ItemWirelessPeripheralCard.java @@ -0,0 +1,199 @@ +package reobf.proghatches.oc; +import static reobf.proghatches.oc.WirelessPeripheralManager.*; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Function; + +import li.cil.oc.api.network.EnvironmentHost; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.api.network.Message; +import li.cil.oc.api.network.Node; +import li.cil.oc.api.network.Visibility; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; + +public class ItemWirelessPeripheralCard extends Item implements li.cil.oc.api.driver.item.HostAware { + + + +@Override +public boolean worksWith(ItemStack stack) { + + return stack.getItem()==this; +} + +@Override +public ManagedEnvironment createEnvironment(ItemStack stack, EnvironmentHost host) { + + return new Env(stack, host); +} + public class Env implements ManagedEnvironment { + private ItemStack stack; + public Env(ItemStack stack, EnvironmentHost host) { + this.host=host; + this.stack=stack; + } + public EnvironmentHost host; + private Node node=li.cil.oc.api.Network.newNode(this, Visibility.Network). + withConnector(). + create(); + @Override + public void load(NBTTagCompound nbt) { + Optional.ofNullable(nbt.getTag("node")).ifPresent(s->{if(node()!=null)node().load((NBTTagCompound) s);}); + + } + @Override + public void save(NBTTagCompound nbt) { + NBTTagCompound t=new NBTTagCompound(); + Optional.ofNullable(node()).ifPresent(s->s.save(t)); + nbt.setTag("node", t); + } + + @Override + public void onMessage(Message message) { + + + } + public void createTagIfAbsent(){ + if(stack.getTagCompound()==null)stack.setTagCompound(new NBTTagCompound()); + } + public UUID getUUID(){ + createTagIfAbsent(); + return UUID.fromString(stack.getTagCompound().getString("remoteUUID")); + } + public void markBad(){ + createTagIfAbsent(); + stack.getTagCompound().setBoolean("isBad", true); + } + public boolean isBad(){ + createTagIfAbsent(); + return stack.getTagCompound().getBoolean("isBad"); + } + public boolean isValid(){ + + return (!isBad())&&Optional.ofNullable(stack.getTagCompound()).map(s->!s.getString("remoteUUID").isEmpty()).orElse(false); + } + + @Override + public void onDisconnect(Node node) { + if(!isValid())return; + if(node==this.node){//this means the card is removed + WirelessPeripheralManager.remove(cards,getUUID()); + }else{//otherwise means another component is removed, just ignore + } + + } + + @Override + public void onConnect(Node node) { + if(!isValid())return; + + if(WirelessPeripheralManager.cards.containsKey(getUUID()) + &&WirelessPeripheralManager.cards.get(getUUID())!=this.node){ + //channel in use, disable it + markBad(); + return; + } + if(this.node!=null){ + //TODO: check if node is a Computer Case? + WirelessPeripheralManager.add(cards,getUUID(), this.node); + } + } + + @Override + public Node node() { + + return node; + } + boolean init; + @Override + public void update() { + + if(!init){init=true; + if(isValid()&&node!=null){ + WirelessPeripheralManager.cards.put(this.getUUID(), node); + } + } + } + + @Override + public boolean canUpdate() { + + return true; + } + }; + + +@Override +public String slot(ItemStack stack) { + + return li.cil.oc.common.Slot.Card(); +} + +@Override +public int tier(ItemStack stack) { + + return 1; +} + +@Override +public NBTTagCompound dataTag(ItemStack stack) { + + return null; +} +@Override + public ItemStack onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer player) { + + if(player.isSneaking()){ + + itemStackIn.setTagCompound(null); + } + return super.onItemRightClick(itemStackIn, worldIn, player); + } +@SuppressWarnings("unchecked") +@Override + public void addInformation(ItemStack p_77624_1_, EntityPlayer p_77624_2_, List p_77624_3_, boolean p_77624_4_) { + + int i = 0; + while (true) { + String k = "item.proghatches.oc.peripheral_card.tooltip"; + if (StatCollector.translateToLocal(k) + .equals( + Integer.valueOf(i) + .toString())) { + break; + } + String key = k + "." + i; + String trans = StatCollector.translateToLocal(key); + + p_77624_3_.add(trans); + i++; + } + + + NBTTagCompound tag = p_77624_1_.getTagCompound(); + if(tag==null){ + p_77624_3_.add(StatCollector.translateToLocal("item.proghatches.oc.peripheral_card.tooltip.unbound")); + }else{ + if(tag.getBoolean("isBad")){ + p_77624_3_.add(StatCollector.translateToLocal("item.proghatches.oc.peripheral_card.tooltip.bad")); + }else + p_77624_3_.add(StatCollector.translateToLocalFormatted("item.proghatches.oc.peripheral_card.tooltip.valid",tag.getString("remoteUUID"))); + } + + + + super.addInformation(p_77624_1_, p_77624_2_, p_77624_3_, p_77624_4_); + } +@Override +public boolean worksWith(ItemStack stack, Class host) { + + return stack.getItem()==this; +} +} diff --git a/src/main/java/reobf/proghatches/oc/TileWirelessPeripheralStation.java b/src/main/java/reobf/proghatches/oc/TileWirelessPeripheralStation.java new file mode 100644 index 0000000..7adc9d2 --- /dev/null +++ b/src/main/java/reobf/proghatches/oc/TileWirelessPeripheralStation.java @@ -0,0 +1,354 @@ +package reobf.proghatches.oc; + +import static reobf.proghatches.oc.WirelessPeripheralManager.*; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.DoubleUnaryOperator; +import java.util.function.IntUnaryOperator; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import gregtech.api.interfaces.tileentity.IGregtechWailaProvider; +import li.cil.oc.api.network.Connector; +import li.cil.oc.api.network.EnvironmentHost; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.api.network.Message; +import li.cil.oc.api.network.Node; +import li.cil.oc.api.network.Visibility; +import li.cil.oc.common.tileentity.traits.Computer; +import li.cil.oc.integration.util.Wrench; +import li.cil.oc.server.machine.Machine; +import li.cil.oc.util.BlockPosition; +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; +import mcp.mobius.waila.api.IWailaDataProvider; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import reobf.proghatches.oc.ItemWirelessPeripheralCard.Env; +import scala.Some; + +public class TileWirelessPeripheralStation extends TileEntity implements li.cil.oc.api.network.Environment { + public TileWirelessPeripheralStation() {} + static public IWailaDataProvider provider=new IWailaDataProvider(){ + @Override + public List getWailaBody(ItemStack itemStack, List currenttip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + currenttip.add(StatCollector.translateToLocalFormatted("tile.proghatches.oc.peripheral_station.waila.channel", accessor.getNBTData().getString("UUID"))); + currenttip.add(StatCollector.translateToLocalFormatted("tile.proghatches.oc.peripheral_station.waila.connection", + StatCollector.translateToLocal("tile.proghatches.oc.peripheral_station.waila.connection."+ + (accessor.getNBTData().getBoolean("connection")?"true":accessor.getNBTData().getBoolean("inrange")? + accessor.getNBTData().getBoolean("oneComputer")?"false":"more_than_one":"out_of_range")) + + + )); + return currenttip; + + } + @Override + public NBTTagCompound getNBTData(EntityPlayerMP player, TileEntity te, NBTTagCompound tag, World world, int x, int y, + int z){ + tag.setString("UUID", ((TileWirelessPeripheralStation)world.getTileEntity(x, y, z)).thisUUID.toString()); + tag.setBoolean("inrange", ((TileWirelessPeripheralStation)world.getTileEntity(x, y, z)).inrange); + tag.setBoolean("oneComputer", ((TileWirelessPeripheralStation)world.getTileEntity(x, y, z)).oneComputer); + + Optional.ofNullable( + WirelessPeripheralManager.cards.get( + ((TileWirelessPeripheralStation)world.getTileEntity(x, y, z)).thisUUID + )) + .ifPresent( + s->{ + Optional.ofNullable(WirelessPeripheralManager.stations.get( + ((TileWirelessPeripheralStation)world.getTileEntity(x, y, z)).thisUUID + )) + .ifPresent(w->{ + + tag.setBoolean("connection",s.network()==w.network()); + + }); + ; + + + } + ); + + + ; + + + return tag; + }; + @Override + public ItemStack getWailaStack(IWailaDataAccessor accessor, IWailaConfigHandler config) { + + return null; + } + @Override + public List getWailaHead(ItemStack itemStack, List currenttip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + + return ImmutableList.of(); + } + @Override + public List getWailaTail(ItemStack itemStack, List currenttip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + + return ImmutableList.of(); + } +}; + public static class ItemBlock extends net.minecraft.item.ItemBlock{ +@Override +public void addInformation(ItemStack p_77624_1_, EntityPlayer p_77624_2_, List p_77624_3_, boolean p_77624_4_) { + int i = 0; + while (true) { + String k = "tile.proghatches.peripheral_station.tooltip"; + if (StatCollector.translateToLocal(k) + .equals( + Integer.valueOf(i) + .toString())) { + break; + } + String key = k + "." + i; + String trans = StatCollector.translateToLocal(key); + + p_77624_3_.add(trans); + i++; + } + + + super.addInformation(p_77624_1_, p_77624_2_, p_77624_3_, p_77624_4_); +} + public ItemBlock(net.minecraft.block.Block p_i45328_1_) { + super(p_i45328_1_); + + } + + } + public static class Block extends net.minecraft.block.BlockContainer { + @Override + public void registerBlockIcons(IIconRegister reg) { + super.registerBlockIcons(reg); + a=reg.registerIcon("proghatches:pstation"); + b=reg.registerIcon("proghatches:pstation_0"); + c=reg.registerIcon("proghatches:pstation_1"); + } + IIcon a,b,c; + @Override + public IIcon getIcon(int side, int meta) { + if(side<=1)return a;//top bottom + if(meta==0)return b;else return c; + } + @Override + public boolean onBlockActivated(World worldIn, int x, int y, int z, EntityPlayer player, int side, float subX, + float subY, float subZ) { + TileWirelessPeripheralStation tile=(TileWirelessPeripheralStation) worldIn.getTileEntity(x, y, z); + if(Wrench.holdsApplicableWrench(player, new BlockPosition(x, y, z, Some.apply(worldIn)))){ + if(!worldIn.isRemote&&tile.oneComputer==false){ + Wrench.wrenchUsed(player, new BlockPosition(x, y, z, Some.apply(worldIn))); + tile.oneComputer=true; + } + return true; + } + ItemStack is; + if (worldIn.isRemote) + return false; + if ((is = player.getHeldItem()) != null) { + + if (is.getTagCompound() == null) + is.setTagCompound(new NBTTagCompound()); + + // System.out.println(((TileWirelessPeripheralStation)worldIn.getTileEntity(x, + // y, z))); + // System.out.println(((TileWirelessPeripheralStation)worldIn.getTileEntity(x, + // y, z)).thisUUID); + + is.getTagCompound().setString("remoteUUID", + tile.thisUUID.toString()); + + } + + return super.onBlockActivated(worldIn, x, y, z, player, side, subX, subY, subZ); + } + + public Block() { + super(Material.rock); + setHardness(1); + setHarvestLevel("pickaxe", 1); + setBlockName("proghatch.peripheral_station"); + } + + @Override + public TileEntity createNewTileEntity(World worldIn, int meta) { + + return new TileWirelessPeripheralStation(); + } + + } + + private Node node = li.cil.oc.api.Network.newNode(this, Visibility.Network).withConnector().create(); + + @Override + public void writeToNBT(NBTTagCompound nbt) { + NBTTagCompound t = new NBTTagCompound(); + Optional.ofNullable(node()).ifPresent(s -> s.save(t)); + nbt.setTag("node", t); + nbt.setString("UUID", thisUUID.toString()); + nbt.setBoolean("inrange", inrange); + nbt.setBoolean("oneComputer", oneComputer); + super.writeToNBT(nbt); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + Optional.ofNullable(nbt.getTag("node")).ifPresent(s -> { + if (node() != null) + node().load((NBTTagCompound) s); + }); + thisUUID = UUID.fromString(nbt.getString("UUID")); + inrange=nbt.getBoolean("inrange"); + oneComputer=nbt.getBoolean("oneComputer"); + super.readFromNBT(nbt); + } + + @Override + public Node node() { + return node; + } + //TODO:use oc UUID? + UUID thisUUID = UUID.randomUUID(); + + @Override + public void onConnect(Node node) { + //TODO:check if node belongs to card + WirelessPeripheralManager.add(stations, thisUUID, this.node); + } + + @Override + public void onDisconnect(Node node) { + //card will call onDisconnect to cut the connection + //do nothing here + } + + @Override + public void onMessage(Message message) { + + } + + @Override + public void invalidate() { + if (node != null) { + WirelessPeripheralManager.remove(stations, thisUUID); + } + } + + @Override + public void validate() { + if (node != null) { + WirelessPeripheralManager.add(stations, thisUUID, node); + } + } + + @Override + public void onChunkUnload() { + if (node != null) { + WirelessPeripheralManager.remove(stations, thisUUID); + } + } + + private boolean init; + boolean inrange=true; + boolean oneComputer=true; + int range=16; + private static Class computer; + static { + try { + computer=Class.forName("li.cil.oc.common.tileentity.traits.Computer"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + }} + + @Override + public void updateEntity() { + if (!init) { + init = true; + li.cil.oc.api.Network.joinOrCreateNetwork(this); + if (node != null) { + + WirelessPeripheralManager.add(stations, thisUUID, node); + + } + } + + if(this.worldObj.isRemote){ + thisUUID=new UUID(0,0);//set to 0 on client to prevent Waila from showing random UUID + + }else{ + + if(oneComputer^this.worldObj.getBlockMetadata(xCoord, yCoord, zCoord)==0) + this.worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 1-this.worldObj.getBlockMetadata(xCoord, yCoord, zCoord), 2); + + if(!oneComputer){return;} + if(node ==null)return; + + int[] counter=new int[1]; + node.network().nodes().forEach(s->{ + if(s.host() instanceof li.cil.oc.server.machine.Machine){ + li.cil.oc.server.machine.Machine mch=(Machine) s.host(); + //if(mch.host() instanceof Computer)//won't compile... projectred interfaces missing + + if(computer.isInstance(mch.host())) //workaround + + counter[0]++;} + }); + oneComputer=(counter[0]<=1); + + + + Node remoteID = WirelessPeripheralManager.cards.get(thisUUID); + if(remoteID==null){inrange=true;} + if(remoteID!=null){ + ItemWirelessPeripheralCard.Env me=(Env) remoteID.host(); + DoubleUnaryOperator op=s->s*s; + double x=me.host.xPosition() + ,y=me.host.yPosition() + ,z=me.host.zPosition(); + double x1=this.xCoord+0.5 + ,y1=this.yCoord+0.5 + ,z1=this.zCoord+0.5; + double epsilon=0.01; + inrange=range*range+epsilon>= + op.applyAsDouble(x-x1)+ op.applyAsDouble(y-y1)+ op.applyAsDouble(z-z1) + &&me.host.world()==this.worldObj + ; + boolean sameNet=node.network()==remoteID.network(); + + if((inrange&&oneComputer)&&!sameNet){ + this.node.connect(remoteID); + } + if(!(inrange&&oneComputer)&&sameNet){ + this.node.disconnect(remoteID); + } + + + } + + } + + + + + + } + + +} diff --git a/src/main/java/reobf/proghatches/oc/WirelessPeripheralManager.java b/src/main/java/reobf/proghatches/oc/WirelessPeripheralManager.java new file mode 100644 index 0000000..aa23189 --- /dev/null +++ b/src/main/java/reobf/proghatches/oc/WirelessPeripheralManager.java @@ -0,0 +1,38 @@ +package reobf.proghatches.oc; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.WeakHashMap; +@SuppressWarnings({"rawtypes","unchecked"}) +public class WirelessPeripheralManager { +static public HashMap cards=new HashMap<>(); +static public HashMap stations=new HashMap<>(); + + public static void add(Map a,UUID k,li.cil.oc.api.network.Node v){ + a.put(k, v); + connect(k);} + public static void remove(Map a,UUID k){ + disconnect(k); + a.remove(k); + } +public static void disconnect(UUID thisUUID) { + Optional.ofNullable(stations.get(thisUUID)).ifPresent( + s->Optional.ofNullable(cards.get(thisUUID)).ifPresent( + w->s.disconnect(w) + ) + ); + + } + public static void connect(UUID thisUUID) { + Optional.ofNullable(stations.get(thisUUID)).ifPresent( + s->Optional.ofNullable(cards.get(thisUUID)).ifPresent( + w->s.connect(w) + ) + ); + } + + + +} diff --git a/src/main/resources/assets/proghatches/lang/en_US.lang b/src/main/resources/assets/proghatches/lang/en_US.lang index 6d785b9..4959194 100644 --- a/src/main/resources/assets/proghatches/lang/en_US.lang +++ b/src/main/resources/assets/proghatches/lang/en_US.lang @@ -152,4 +152,27 @@ tile.iohub.tooltip.2=but controlled by OC Computers via OC cable. tile.iohub.tooltip.3=No Security Station needed, connect to AE2 network with ME cable. tile.iohub.tooltip.4=32 Item Slots+8 Fluid Tanks tile.iohub.tooltip.5=hold [SHIFT] to see more details -tile.iohub.tooltip=6 \ No newline at end of file +tile.iohub.tooltip=6 +item.proghatches.oc.peripheral_card.name=Wireless Peripheral Bridging Card +tile.proghatch.peripheral_station.name=Wireless Peripheral Driving Station +item.proghatches.oc.peripheral_card.tooltip.unbound=Unbound +item.proghatches.oc.peripheral_card.tooltip.bad=Invalid: need resetting. Usually caused by trying to establish a multi-to-one connection. +item.proghatches.oc.peripheral_card.tooltip.valid=Channel: %s +tile.proghatches.oc.peripheral_station.waila.channel=Channel: %s +tile.proghatches.oc.peripheral_station.waila.connection=Connection: %s +tile.proghatches.oc.peripheral_station.waila.connection.true=true +tile.proghatches.oc.peripheral_station.waila.connection.false=false +tile.proghatches.oc.peripheral_station.waila.connection.out_of_range=Out of range. +tile.proghatches.oc.peripheral_station.waila.connection.more_than_one=Error: More than one computers in this network. Use wrench to reset. +item.proghatches.oc.peripheral_card.tooltip.0=Right click a Peripheral Driving Station to bind. +item.proghatches.oc.peripheral_card.tooltip.1=Shift+right click to reset. +item.proghatches.oc.peripheral_card.tooltip.2=You can install this card in ANY card slot(not limited to Casing). +item.proghatches.oc.peripheral_card.tooltip.3=Require no component channel. +item.proghatches.oc.peripheral_card.tooltip=4 +tile.proghatches.peripheral_station.tooltip.0=Drive connected machines and provide components access to computer +tile.proghatches.peripheral_station.tooltip.1=with Wireless Peripheral Bridging Card bound to this station. +tile.proghatches.peripheral_station.tooltip.2=Cannot work in network that contains more than one computer. +tile.proghatches.peripheral_station.tooltip.3=Can only establish one-to-one connection with one single Wireless Peripheral Bridging Card. +tile.proghatches.peripheral_station.tooltip.4=Range:16 with no inter-dimension support +tile.proghatches.peripheral_station.tooltip.5=Require no component channel. +tile.proghatches.peripheral_station.tooltip=6 diff --git a/src/main/resources/assets/proghatches/lang/zh_CN.lang b/src/main/resources/assets/proghatches/lang/zh_CN.lang index 05db917..bffba19 100644 --- a/src/main/resources/assets/proghatches/lang/zh_CN.lang +++ b/src/main/resources/assets/proghatches/lang/zh_CN.lang @@ -163,3 +163,25 @@ tile.iohub.tooltip.3=无需安全终端,直接使用AE线缆链接网络 tile.iohub.tooltip.4=32 物品栏+8 流体 tile.iohub.tooltip.5=按 [SHIFT] 获取更多信息 tile.iohub.tooltip=6 +item.proghatches.oc.peripheral_card.name=无线外设桥接卡 +tile.proghatch.peripheral_station.name=无线外设驱动站 +item.proghatches.oc.peripheral_card.tooltip.unbound=未绑定 +item.proghatches.oc.peripheral_card.tooltip.bad=失效: 需要复位 这通常是尝试多对一连接导致的 +item.proghatches.oc.peripheral_card.tooltip.valid=频道: %s +tile.proghatches.oc.peripheral_station.waila.channel=频道: %s +tile.proghatches.oc.peripheral_station.waila.connection=连接状态: %s +tile.proghatches.oc.peripheral_station.waila.connection.true=true +tile.proghatches.oc.peripheral_station.waila.connection.false=false +tile.proghatches.oc.peripheral_station.waila.connection.out_of_range=超出信号范围 +tile.proghatches.oc.peripheral_station.waila.connection.more_than_one=错误:无法在有多于一个计算机的网络中工作 使用扳手复位 +item.proghatches.oc.peripheral_card.tooltip.0=右键外设驱动站以绑定 +item.proghatches.oc.peripheral_card.tooltip.1=Shift右键以复位 +item.proghatches.oc.peripheral_card.tooltip.2=可以安装在任何卡槽内(不限于机箱) +item.proghatches.oc.peripheral_card.tooltip.3=不占用组件数量 +item.proghatches.oc.peripheral_card.tooltip=4 +tile.proghatches.peripheral_station.tooltip.0=驱动连接的机器,并对安装了无线外设桥接卡的电脑提供组件访问 +tile.proghatches.peripheral_station.tooltip.1=无法在有多个电脑的网络中工作 +tile.proghatches.peripheral_station.tooltip.2=只能和无线外设桥接卡建立一对一的连接 +tile.proghatches.peripheral_station.tooltip.3=距离:16格 无法跨维度 +tile.proghatches.peripheral_station.tooltip.4=不占用组件数量 +tile.proghatches.peripheral_station.tooltip=5 diff --git a/src/main/resources/assets/proghatches/textures/blocks/pstation.png b/src/main/resources/assets/proghatches/textures/blocks/pstation.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1e6b61bd1220fc9db21f90f4ebafdf3fe8dee0 GIT binary patch literal 465 zcmV;?0WSWDP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0cJ@=K~y+TWs*(H zf>02J^%`ZgX;}-mEd*VJ(ciBSTKPAmaAOpNne{&7DGA;Kj%Vh~+?o5~FBS{$2fpvW zUN7g|yNAec&|fZ>o6UyQ$z;-X9iboyl#2U&K9NQ}sLAu(erSio0f9X0@&yYk0-4Qb zS(ZUYe1s69C{o6dC&+Ev77lUvbie{?{)3sN3T{|KpqO#l&v-m$GZ1DTB$DmJ!2&AD zW!2t;Gce5key79r zdc9mOSV_vU4d5^X4k*j=d_JE}Cs_gBZ_v&ISO*@=bUNh_05{6XVCjYo5lExP#^NHk z+byjKVJSx7+#uWugjFC&)E|#Wd)}YY@1w#3xgw-~BA)jLw9X+ZB1a6N00000NkvXX Hu0mjf+6cm% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/proghatches/textures/blocks/pstation_0.png b/src/main/resources/assets/proghatches/textures/blocks/pstation_0.png new file mode 100644 index 0000000000000000000000000000000000000000..c92ce9368a71a866e51b457c99d4ae20d7795798 GIT binary patch literal 536 zcmV+z0_XjSP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0j)_yK~y+TO_IB6 z0#Oi#&)MUx5$se18%rSpA$ft6c??_M$``Q;b|MHC8w4*{*oe1vSKYJuW=Dd5G5%-f zpX+KHjfQ!Fwbpwd1VNTV$*a>go6T;wi?moQ^41)+X%2XyP;kzXGnq^Reu$OJWeVU0 z5P%aMWHy^kr_=d-PBKmjR4Nt9q@)^~W(MmsAwWa#UvKn>KS!!otM~i8R4R$&1yaG7 z!{PAx{Sp5BqCTBYk}wzycDo&|2Qfgu zpLuI+W-|EW@sQNK%y2lArD?QSEN-{kYPCw@Bn-oAbX~94@a1xepJ;p)kSGVaTrM1k zHRwQ?<6v1SNfJC*qQ~QrWf<78ajVtBMS#OG8zta?LMYDXGxuSzD2g_ljf_MLFJW9H zU;$~gl9JBRP(Om~Qm@wukj6+<>U27Yc%mZ=XAN082O9Y=wcBkNqWyl47ZJtOQVUP5 zR-++LE+Gkk2Ovh^zq@j3!SOIT_mrg>5ie_Dbsns8r22`_0El$Z?pjqvK%X>01n|pN a#{2Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T8Ow3BHZt`c}d|hrtGBA}9uepn`!4-klkBoYP+oEra1^=Wq(j z>bm`P>9L)1xg5zGIgTUG=TltQl_-jo?fKp3R4SFIUaxCnCX-PkM4**n7%D^QbXroW zl!6Qf193SJl*{E56(`IY#zzw8(P$*Y;ZP=%i2~wt`N`+=iXIv;11F(r0{M*MGh}1_ z{rIV!qQ6Ec6bf>`-zA&PYS25;C3H9((;+;&+>TCG;n z@AtJj<1`u#>GgUsK)c-*-}ki=0pT;0lxr3hF^D7P9#nrk9x<8$2fo|w#!IA?*=#1a z+f5dWg#>;e)9F+^)9P}$RDC|5tDiXE^Taa@nQmOUTrRqK_CN;&vUwzX34%cFNaBvi zqwa%IT~GiZ00&9?{a)up$G6#RGUC4-d_Kq5$Ot$w5PZE}bstC=AiAL%)hS@V z0mvzpN)Z77fz18ZYBf#3MiPY19+E`7{uip%swyPxb~|<2tF)3LP_bCluCTFS1u(1z z+ZF-IHmyz(2s>lHJ|q@M1sEqfWD^+!J3B#Iu-6E-O&CJAWNm;kB8=beMz1lMXu*;) znP}&?@t^QLXf~VL>3_cmtyW9MPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0X|7YK~y+T-I2{o z!%z@~PntAIO(F4Y`BwK$t;k$eg z)a0?chqY=&CS&rtE~}L0#Z}TE$BD$AcVO9eM!IM)t7$ap%+UAo+I@j_aE4GfpvFEB zhk^gIehLrJCqEy(W=SWy(R zk02)5IZZ^FVH)zr%o4x08YnH5Wb!-h=Qb+0$3K@ybUR&^KM<1$-FtVeo6GAYn zwRxzJsD6L@VA+m?+EYVWEEbbY)6(5%{=$UbQG{}N0j*Y#9d4SrZaw+ze*y3f!fb`T TTB?K600000NkvXXu0mjf&|$Yb literal 0 HcmV?d00001