├── logs └── latest.log ├── .travis.yml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src ├── main │ ├── resources │ │ ├── assets │ │ │ └── minecoprocessors │ │ │ │ ├── textures │ │ │ │ ├── gui │ │ │ │ │ ├── book_code.png │ │ │ │ │ ├── minecoprocessor.png │ │ │ │ │ └── minecoprocessor.xcf │ │ │ │ ├── items │ │ │ │ │ ├── book_code.png │ │ │ │ │ ├── minecoprocessor.png │ │ │ │ │ ├── minecoprocessor.xcf │ │ │ │ │ └── minecoprocessor_overclocked.png │ │ │ │ └── blocks │ │ │ │ │ ├── minecoprocessor.png │ │ │ │ │ └── minecoprocessor.xcf │ │ │ │ ├── models │ │ │ │ ├── item │ │ │ │ │ ├── minecoprocessor.json │ │ │ │ │ ├── minecoprocessor_overclocked.json │ │ │ │ │ └── book_code.json │ │ │ │ └── block │ │ │ │ │ ├── minecoprocessor_off.json │ │ │ │ │ ├── minecoprocessor_on.json │ │ │ │ │ ├── minecoprocessor_overclocked_off.json │ │ │ │ │ └── minecoprocessor_overclocked_on.json │ │ │ │ ├── lang │ │ │ │ ├── zh_CN.lang │ │ │ │ └── en_US.lang │ │ │ │ ├── blockstates │ │ │ │ ├── unpowered_minecoprocessor.json │ │ │ │ └── minecoprocessor.json │ │ │ │ ├── recipes │ │ │ │ ├── minecoprocessor_overclocked.json │ │ │ │ └── minecoprocessor.json │ │ │ │ └── books │ │ │ │ └── manual.txt │ │ └── mcmod.info │ └── java │ │ └── net │ │ └── torocraft │ │ └── minecoprocessors │ │ ├── items │ │ ├── IMetaBlockName.java │ │ ├── ItemBlockMeta.java │ │ └── ItemBookCode.java │ │ ├── processor │ │ ├── IProcessor.java │ │ ├── FaultCode.java │ │ ├── InstructionCode.java │ │ ├── Register.java │ │ └── Processor.java │ │ ├── Settings.java │ │ ├── util │ │ ├── ParseException.java │ │ ├── Label.java │ │ ├── ByteUtil.java │ │ ├── RedstoneUtil.java │ │ ├── BookCreator.java │ │ └── InstructionUtil.java │ │ ├── ClientProxy.java │ │ ├── CommonProxy.java │ │ ├── Minecoprocessors.java │ │ ├── gui │ │ ├── MinecoprocessorGuiHandler.java │ │ ├── ScaledGuiButton.java │ │ └── GuiMinecoprocessor.java │ │ ├── network │ │ ├── AbstractMessageHandler.java │ │ ├── MessageEnableGuiUpdates.java │ │ ├── MessageBookCodeData.java │ │ ├── MessageProcessorUpdate.java │ │ └── MessageProcessorAction.java │ │ └── blocks │ │ ├── ContainerMinecoprocessor.java │ │ ├── BlockMinecoprocessor.java │ │ └── TileEntityMinecoprocessor.java └── test │ └── java │ └── net │ └── torocraft │ └── minecoprocessors │ ├── gui │ └── GuiMinecoprocessorTest.java │ ├── blocks │ └── TileEntityMinecoprocessorTest.java │ └── util │ ├── RedstoneUtilTest.java │ ├── ByteUtilTest.java │ └── InstructionUtilTest.java ├── gradle.properties ├── .gitignore ├── README.md ├── .github └── stale.yml ├── gradlew.bat └── gradlew /logs/latest.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/gui/book_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/gui/book_code.png -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/items/book_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/items/book_code.png -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/gui/minecoprocessor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/gui/minecoprocessor.png -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/gui/minecoprocessor.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/gui/minecoprocessor.xcf -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/item/minecoprocessor.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "minecoprocessors:items/minecoprocessor" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/blocks/minecoprocessor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/blocks/minecoprocessor.png -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/blocks/minecoprocessor.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/blocks/minecoprocessor.xcf -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/items/minecoprocessor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/items/minecoprocessor.png -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/items/minecoprocessor.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/items/minecoprocessor.xcf -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/lang/zh_CN.lang: -------------------------------------------------------------------------------- 1 | tile.minecoprocessor.name=红石处理器 2 | container.minecoprocessor=红石处理器 3 | gui.button.reset=重置 4 | gui.button.sleep=休眠 5 | gui.button.step=步进 6 | gui.button.wake=唤醒 -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx3G 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/item/minecoprocessor_overclocked.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "minecoprocessors:items/minecoprocessor_overclocked" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/textures/items/minecoprocessor_overclocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ToroCraft/Minecoprocessors/HEAD/src/main/resources/assets/minecoprocessors/textures/items/minecoprocessor_overclocked.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # gradle 17 | build 18 | .gradle 19 | 20 | # other 21 | eclipse 22 | run 23 | logs/ 24 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/items/IMetaBlockName.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.items; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | public interface IMetaBlockName { 6 | 7 | String getSpecialName(ItemStack stack); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 19 08:10:44 EDT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip 7 | -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "minecoprocessors", 4 | "name": "Minecoprocessors", 5 | "description": "This mods add a programmable block that functions like a microprocessor.", 6 | "version": "${version}", 7 | "mcversion": "${mcversion}", 8 | "url": "", 9 | "updateUrl": "", 10 | "authorList": ["ToroCraft"], 11 | "credits": "", 12 | "logoFile": "", 13 | "screenshots": [], 14 | "dependencies": [] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /src/test/java/net/torocraft/minecoprocessors/gui/GuiMinecoprocessorTest.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.gui; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class GuiMinecoprocessorTest { 7 | 8 | @Test 9 | public void toBinary() { 10 | Assert.assertEquals("11110000", GuiMinecoprocessor.toBinary((byte) 0xf0)); 11 | Assert.assertEquals("00000000", GuiMinecoprocessor.toBinary((byte) 0x0)); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/blockstates/unpowered_minecoprocessor.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "facing=south": { "model": "minecoprocessors:minecoprocessor_off" }, 4 | "facing=west": { "model": "minecoprocessors:minecoprocessor_off", "y": 90 }, 5 | "facing=north": { "model": "minecoprocessors:minecoprocessor_off", "y": 180 }, 6 | "facing=east": { "model": "minecoprocessors:minecoprocessor_off", "y": 270 } 7 | } 8 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/processor/IProcessor.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.processor; 2 | 3 | import java.util.List; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | 6 | public interface IProcessor { 7 | 8 | void reset(); 9 | 10 | boolean tick(); 11 | 12 | void wake(); 13 | 14 | void load(List program); 15 | 16 | void readFromNBT(NBTTagCompound c); 17 | 18 | NBTTagCompound writeToNBT(); 19 | 20 | byte[] getRegisters(); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/recipes/minecoprocessor_overclocked.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "pattern": [ 4 | " d ", 5 | "dmd", 6 | " d " 7 | ], 8 | "key": { 9 | "d": { 10 | "item": "minecraft:diamond" 11 | }, 12 | 13 | "m": { 14 | "item": "minecoprocessors:minecoprocessor", 15 | "data": 0 16 | } 17 | }, 18 | "result": { 19 | "item": "minecoprocessors:minecoprocessor", 20 | "data": 4 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/Settings.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors; 2 | 3 | import net.minecraftforge.common.config.Config; 4 | import net.minecraftforge.common.config.Config.Comment; 5 | import net.minecraftforge.common.config.Config.RangeInt; 6 | 7 | @Config(modid = Minecoprocessors.MODID) 8 | public class Settings { 9 | 10 | @Comment("The maximum number of characters a single line in the code book may have.") 11 | @RangeInt(min = 1, max = 80) 12 | public static int maxColumnsPerLine = 18; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/recipes/minecoprocessor.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "minecraft:crafting_shaped", 3 | "pattern": [ 4 | "tct", 5 | "crc", 6 | "tct" 7 | ], 8 | "key": { 9 | "t": { 10 | "item": "minecraft:redstone_torch" 11 | }, 12 | 13 | "c": { 14 | "item": "minecraft:comparator" 15 | }, 16 | 17 | "r": { 18 | "item": "minecraft:redstone_block" 19 | } 20 | }, 21 | "result": { 22 | "item": "minecoprocessors:minecoprocessor", 23 | "data": 0 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/item/book_code.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "item/generated", 3 | "textures": { 4 | "layer0": "minecoprocessors:items/book_code" 5 | }, 6 | "display": { 7 | "thirdperson": { 8 | "rotation": [ -90, 0, 0 ], 9 | "translation": [ 0, 1, -3 ], 10 | "scale": [ 0.55, 0.55, 0.55 ] 11 | }, 12 | "firstperson": { 13 | "rotation": [ 0, -135, 25 ], 14 | "translation": [ 0, 4, 2 ], 15 | "scale": [ 1.7, 1.7, 1.7 ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/lang/en_US.lang: -------------------------------------------------------------------------------- 1 | tile.minecoprocessor.name=Redstone Processor 2 | tile.minecoprocessor_overclocked.name=Overclocked Processor 3 | item.book_code.name=Code Book 4 | item.book_code.tooltip=Redstone Processor 5 | container.minecoprocessor=Redstone Processor 6 | gui.button.reset=reset 7 | gui.button.sleep=sleep 8 | gui.button.step=step 9 | gui.button.wake=wake 10 | gui.button.help=manual 11 | minecoprocessors.error_chat=An unexpected exception occurred in Minecoprocessors. This may cause problems and should be reported to the developer. Details have been logged. 12 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/processor/FaultCode.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.processor; 2 | 3 | public class FaultCode { 4 | 5 | public static final byte FAULT_DIVISION_BY_ZERO = 0x00; 6 | public static final byte FAULT_STACK_UNDERFLOW = 0x01; 7 | public static final byte FAULT_STACK_OVERFLOW = 0x02; 8 | public static final byte FAULT_UNDEFINED_IP = 0x03; 9 | public static final byte FAULT_UNKNOWN_OPCODE = 0x04; 10 | public static final byte FAULT_OUT_OF_BOUNDS = 0x05; 11 | public static final byte FAULT_HLT_INSTRUCTION = (byte) 0xFE; 12 | public static final byte FAULT_STATE_NOMINAL = (byte) 0xFF; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/processor/InstructionCode.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.processor; 2 | 3 | public enum InstructionCode { 4 | MOV, 5 | ADD, 6 | SUB, 7 | AND, 8 | OR, 9 | XOR, 10 | NOT, 11 | MUL, 12 | DIV, 13 | JMP, 14 | JZ, 15 | JNZ, 16 | JG, 17 | JL, 18 | JGE, 19 | JLE, 20 | JE, 21 | JNE, 22 | LOOP, 23 | CMP, 24 | SHL, 25 | SHR, 26 | PUSHA, 27 | POPA, 28 | PUSH, 29 | POP, 30 | RET, 31 | CALL, 32 | NOP, 33 | INT, 34 | WFE, 35 | INC, 36 | DEC, 37 | DJNZ, 38 | JC, 39 | JNC, 40 | ROR, 41 | ROL, 42 | SAR, 43 | SAL, 44 | HLT, 45 | CLZ, 46 | CLC, 47 | SEZ, 48 | SEC, 49 | DUMP 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/items/ItemBlockMeta.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.items; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.item.ItemBlock; 5 | import net.minecraft.item.ItemStack; 6 | 7 | public class ItemBlockMeta extends ItemBlock { 8 | 9 | public ItemBlockMeta(Block block) { 10 | super(block); 11 | if (!(block instanceof IMetaBlockName)) { 12 | throw new IllegalArgumentException(block.getUnlocalizedName()); 13 | } 14 | this.setMaxDamage(0); 15 | this.setHasSubtypes(true); 16 | } 17 | 18 | @Override 19 | public String getUnlocalizedName(ItemStack stack) { 20 | return ((IMetaBlockName) block).getSpecialName(stack); 21 | } 22 | 23 | @Override 24 | public int getMetadata(int damage) { 25 | return damage; 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/util/ParseException.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | public class ParseException extends Exception { 4 | 5 | private static final long serialVersionUID = 1493829582935568613L; 6 | 7 | public String line; 8 | public String message; 9 | public int lineNumber; 10 | public int pageNumber; 11 | 12 | public ParseException(String line, String message) { 13 | super(genMessage(line, message)); 14 | this.line = line; 15 | this.message = message; 16 | } 17 | 18 | public ParseException(String line, String message, Throwable cause) { 19 | super(genMessage(line, message), cause); 20 | this.line = line; 21 | this.message = message; 22 | } 23 | 24 | private static String genMessage(String line, String message) { 25 | return line; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/util/Label.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | 5 | public class Label { 6 | 7 | private static final String NBT_ADDRESS = "address"; 8 | private static final String NBT_NAME = "name"; 9 | 10 | public short address; 11 | public String name; 12 | 13 | public Label(short address, String name) { 14 | this.address = address; 15 | this.name = name; 16 | } 17 | 18 | public NBTTagCompound toNbt() { 19 | NBTTagCompound c = new NBTTagCompound(); 20 | c.setShort(NBT_ADDRESS, address); 21 | c.setString(NBT_NAME, name); 22 | return c; 23 | } 24 | 25 | public static Label fromNbt(NBTTagCompound c) { 26 | short address = c.getShort(NBT_ADDRESS); 27 | String name = c.getString(NBT_NAME); 28 | return new Label(address, name); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return name + "[" + address + "]"; 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/net/torocraft/minecoprocessors/blocks/TileEntityMinecoprocessorTest.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.blocks; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | public class TileEntityMinecoprocessorTest { 8 | 9 | @Test 10 | public void testNameParser() { 11 | Assert.assertNull(TileEntityMinecoprocessor.readNameFromHeader(Arrays.asList(""))); 12 | Assert.assertNull(TileEntityMinecoprocessor.readNameFromHeader(Arrays.asList(" "))); 13 | Assert.assertNull(TileEntityMinecoprocessor.readNameFromHeader(Arrays.asList("asdf"))); 14 | Assert.assertNull(TileEntityMinecoprocessor.readNameFromHeader(Arrays.asList("; ", " foo code ", " ", ""))); 15 | Assert.assertEquals("test title", TileEntityMinecoprocessor.readNameFromHeader(Arrays.asList("; test title ", " foo code ", " ", ""))); 16 | 17 | //TODO fix test or code 18 | //Assert.assertNull(TileEntityMinecoprocessor.readNameFromHeader(null)); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/processor/Register.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.processor; 2 | 3 | public enum Register { 4 | /** 5 | * general purpose register (accumulator) 6 | */ 7 | A, 8 | /** 9 | * general purpose register 10 | */ 11 | B, 12 | /** 13 | * general purpose register (counter) 14 | */ 15 | C, 16 | /** 17 | * general purpose register 18 | */ 19 | D, 20 | /** 21 | * front port register 22 | */ 23 | PF, 24 | /** 25 | * back port register 26 | */ 27 | PB, 28 | /** 29 | * left port register 30 | */ 31 | PL, 32 | /** 33 | * right port register 34 | */ 35 | PR, 36 | /** 37 | * port direction registers (high / low Z)
38 | * 39 | * 0: output mode (low Z)
40 | * 41 | * 1: input mode (high Z)
42 | * 43 | * 44 | */ 45 | PORTS, 46 | /** 47 | * ADC control for ports
48 | * 49 | * 0: digital
50 | * 51 | * 1: ADC/DAC
52 | * 53 | * 54 | */ 55 | ADC 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Redstone Processor Block](http://i.imgur.com/Vp1e18J.png) 2 | 3 | # Minecoprocessors 4 | 5 | [![Build Status](https://travis-ci.org/ToroCraft/Minecoprocessors.svg?branch=master)](https://travis-ci.org/ToroCraft/Minecoprocessors) 6 | 7 | Increase your redstone possibilities and learn assembly programming at the same time with the Minecoprocessors Minecraft Mod! The Minecoprocessors Mod adds a redstone processor block that can be programed similar to a real microprocessor. The redstone processor block is styled to look and operate like the other redstone blocks in the game. 8 | 9 | ### [Getting Started](https://github.com/ToroCraft/Minecoprocessors/wiki/Getting-Started) 10 | 11 | ### [Items, Blocks and Recipes](https://github.com/ToroCraft/Minecoprocessors/wiki/Items,-Blocks-and-Recipes) 12 | 13 | ### [Processor Details](https://github.com/ToroCraft/Minecoprocessors/wiki/Processor-Details) 14 | 15 | ### [Programs for Common Circuits](https://github.com/ToroCraft/Minecoprocessors/wiki/Programs-for-Common-Circuits) 16 | 17 | ## Development Environment Setup 18 | 19 | ``` 20 | git clone git@github.com:ToroCraft/Minecoprocessors.git 21 | cd Minecoprocessors 22 | gradle setupDecompWorkspace 23 | ``` 24 | 25 | To setup an Intellij environment: 26 | ``` 27 | gradle idea 28 | ``` 29 | 30 | To setup an Eclipse environment: 31 | ``` 32 | gradle eclipse 33 | ``` 34 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/ClientProxy.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.resources.I18n; 5 | import net.minecraft.util.text.TextComponentTranslation; 6 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 7 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 8 | import net.torocraft.minecoprocessors.blocks.BlockMinecoprocessor; 9 | 10 | public class ClientProxy extends CommonProxy { 11 | 12 | private boolean toldPlayerAboutException = false; 13 | 14 | @Override 15 | public String i18nFormat(String key, Object... parameters) { 16 | return I18n.format(key, parameters); 17 | } 18 | 19 | @Override 20 | public void handleUnexpectedException(Exception e) { 21 | super.handleUnexpectedException(e); 22 | if (!toldPlayerAboutException) { 23 | toldPlayerAboutException = true; 24 | Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("minecoprocessors.error_chat")); 25 | } 26 | } 27 | 28 | @Override 29 | public void preInit(FMLPreInitializationEvent e) { 30 | super.preInit(e); 31 | BlockMinecoprocessor.preRegisterRenders(); 32 | } 33 | 34 | @Override 35 | public void init(FMLInitializationEvent e) { 36 | super.init(e); 37 | BlockMinecoprocessor.registerRenders(); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/CommonProxy.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors; 2 | 3 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 4 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 5 | import net.torocraft.minecoprocessors.blocks.TileEntityMinecoprocessor; 6 | import net.torocraft.minecoprocessors.gui.MinecoprocessorGuiHandler; 7 | import net.torocraft.minecoprocessors.network.MessageBookCodeData; 8 | import net.torocraft.minecoprocessors.network.MessageEnableGuiUpdates; 9 | import net.torocraft.minecoprocessors.network.MessageProcessorAction; 10 | import net.torocraft.minecoprocessors.network.MessageProcessorUpdate; 11 | import org.apache.logging.log4j.Logger; 12 | 13 | public class CommonProxy { 14 | 15 | public Logger logger; 16 | 17 | public String i18nFormat(String key, Object... parameters) { 18 | return key; 19 | } 20 | 21 | public void handleUnexpectedException(Exception e) { 22 | e.printStackTrace(); 23 | } 24 | 25 | public void preInit(FMLPreInitializationEvent e) { 26 | logger = e.getModLog(); 27 | int packetId = 0; 28 | MessageEnableGuiUpdates.init(packetId++); 29 | MessageProcessorUpdate.init(packetId++); 30 | MessageProcessorAction.init(packetId++); 31 | MessageBookCodeData.init(packetId++); 32 | TileEntityMinecoprocessor.init(); 33 | MinecoprocessorGuiHandler.init(); 34 | } 35 | 36 | public void init(@SuppressWarnings("unused") FMLInitializationEvent e) { 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/Minecoprocessors.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors; 2 | 3 | import net.minecraftforge.fml.common.Mod; 4 | import net.minecraftforge.fml.common.Mod.EventHandler; 5 | import net.minecraftforge.fml.common.SidedProxy; 6 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 7 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 8 | import net.minecraftforge.fml.common.network.NetworkRegistry; 9 | import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; 10 | 11 | @Mod(modid = Minecoprocessors.MODID, version = Minecoprocessors.VERSION, name = Minecoprocessors.MODNAME) 12 | public class Minecoprocessors { 13 | 14 | public static final String MODID = "minecoprocessors"; 15 | public static final String VERSION = "1.12.2-5"; 16 | public static final String MODNAME = "Minecoprocessors"; 17 | 18 | @Mod.Instance(MODID) 19 | public static Minecoprocessors INSTANCE; 20 | 21 | public static SimpleNetworkWrapper NETWORK = NetworkRegistry.INSTANCE 22 | .newSimpleChannel(Minecoprocessors.MODID); 23 | 24 | @SidedProxy(clientSide = "net.torocraft.minecoprocessors.ClientProxy", serverSide = "net.torocraft.minecoprocessors.CommonProxy") 25 | public static CommonProxy proxy; 26 | 27 | @EventHandler 28 | public void preInit(FMLPreInitializationEvent e) { 29 | proxy.preInit(e); 30 | } 31 | 32 | @EventHandler 33 | public void init(FMLInitializationEvent e) { 34 | proxy.init(e); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 60 5 | 6 | # Number of days of inactivity before a stale Issue or Pull Request is closed. 7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 8 | daysUntilClose: 7 9 | 10 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 11 | exemptLabels: 12 | - pinned 13 | - security 14 | 15 | # Set to true to ignore issues in a project (defaults to false) 16 | exemptProjects: false 17 | 18 | # Set to true to ignore issues in a milestone (defaults to false) 19 | exemptMilestones: false 20 | 21 | # Label to use when marking as stale 22 | staleLabel: stale 23 | 24 | # Comment to post when marking as stale. Set to `false` to disable 25 | markComment: > 26 | This issue has been automatically marked as stale because it has not had 27 | recent activity. It will be closed if no further activity occurs. Thank you 28 | for your contributions. 29 | 30 | # Comment to post when removing the stale label. 31 | # unmarkComment: > 32 | # Your comment here. 33 | 34 | # Comment to post when closing a stale Issue or Pull Request. 35 | # closeComment: > 36 | # Your comment here. 37 | 38 | # Limit the number of actions per hour, from 1-30. Default is 30 39 | limitPerRun: 30 40 | 41 | # Limit to only `issues` or `pulls` 42 | # only: issues 43 | 44 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': 45 | # pulls: 46 | # daysUntilStale: 30 47 | # markComment: > 48 | # This pull request has been automatically marked as stale because it has not had 49 | # recent activity. It will be closed if no further activity occurs. Thank you 50 | # for your contributions. 51 | 52 | # issues: 53 | # exemptLabels: 54 | # - confirmed 55 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/gui/MinecoprocessorGuiHandler.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.gui; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.util.EnumHand; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.world.World; 7 | import net.minecraftforge.fml.common.network.IGuiHandler; 8 | import net.minecraftforge.fml.common.network.NetworkRegistry; 9 | import net.torocraft.minecoprocessors.Minecoprocessors; 10 | import net.torocraft.minecoprocessors.blocks.ContainerMinecoprocessor; 11 | import net.torocraft.minecoprocessors.blocks.TileEntityMinecoprocessor; 12 | import net.torocraft.minecoprocessors.items.ItemBookCode; 13 | 14 | public class MinecoprocessorGuiHandler implements IGuiHandler { 15 | 16 | public static final int MINECOPROCESSOR_ENTITY_GUI = 0; 17 | public static final int MINECOPROCESSOR_BOOK_GUI = 1; 18 | 19 | public static void init() { 20 | NetworkRegistry.INSTANCE 21 | .registerGuiHandler(Minecoprocessors.INSTANCE, new MinecoprocessorGuiHandler()); 22 | } 23 | 24 | @Override 25 | public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { 26 | if (ID == MINECOPROCESSOR_ENTITY_GUI) { 27 | return new ContainerMinecoprocessor(player.inventory, 28 | (TileEntityMinecoprocessor) world.getTileEntity(new BlockPos(x, y, z))); 29 | } 30 | return null; 31 | } 32 | 33 | @Override 34 | public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { 35 | if (ID == MINECOPROCESSOR_ENTITY_GUI) { 36 | return new GuiMinecoprocessor(player.inventory, 37 | (TileEntityMinecoprocessor) world.getTileEntity(new BlockPos(x, y, z))); 38 | } else if (ID == MINECOPROCESSOR_BOOK_GUI && ItemBookCode.isBookCode(player.getHeldItem(EnumHand.MAIN_HAND))) { 39 | return new GuiBookCode(player); 40 | } 41 | return null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/blockstates/minecoprocessor.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "active=true,facing=south,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_on" }, 4 | "active=true,facing=west,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_on", "y": 90 }, 5 | "active=true,facing=north,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_on", "y": 180 }, 6 | "active=true,facing=east,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_on", "y": 270 }, 7 | "active=false,facing=south,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_off" }, 8 | "active=false,facing=west,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_off", "y": 90 }, 9 | "active=false,facing=north,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_off", "y": 180 }, 10 | "active=false,facing=east,overclocked=true": { "model": "minecoprocessors:minecoprocessor_overclocked_off", "y": 270 }, 11 | "active=true,facing=south,overclocked=false": { "model": "minecoprocessors:minecoprocessor_on" }, 12 | "active=true,facing=west,overclocked=false": { "model": "minecoprocessors:minecoprocessor_on", "y": 90 }, 13 | "active=true,facing=north,overclocked=false": { "model": "minecoprocessors:minecoprocessor_on", "y": 180 }, 14 | "active=true,facing=east,overclocked=false": { "model": "minecoprocessors:minecoprocessor_on", "y": 270 }, 15 | "active=false,facing=south,overclocked=false": { "model": "minecoprocessors:minecoprocessor_off" }, 16 | "active=false,facing=west,overclocked=false": { "model": "minecoprocessors:minecoprocessor_off", "y": 90 }, 17 | "active=false,facing=north,overclocked=false": { "model": "minecoprocessors:minecoprocessor_off", "y": 180 }, 18 | "active=false,facing=east,overclocked=false": { "model": "minecoprocessors:minecoprocessor_off", "y": 270 } 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/util/ByteUtil.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | public class ByteUtil { 4 | 5 | public static boolean getBit(long l, int position) { 6 | return (l & 1 << position) != 0; 7 | } 8 | 9 | public static byte setBit(byte b, boolean bit, int position) { 10 | if (bit) { 11 | return (byte) (b | 1 << position); 12 | } 13 | return (byte) (b & ~(1 << position)); 14 | } 15 | 16 | public static long setBit(long l, boolean bit, int position) { 17 | if (bit) { 18 | return l | 1 << position; 19 | } 20 | return l & ~(1 << position); 21 | } 22 | 23 | public static byte getByte(long l, int position) { 24 | return (byte) (l >> 8 * position); 25 | } 26 | 27 | public static short setByte(short s, byte b, int position) { 28 | if (position > 1) { 29 | throw new IndexOutOfBoundsException("position of " + position); 30 | } 31 | int mask = ~(0xff << position * 8); 32 | int insert = (b << position * 8) & ~mask; 33 | return (short) (s & mask | insert); 34 | } 35 | 36 | public static int setByte(int i, byte b, int position) { 37 | if (position > 3) { 38 | throw new IndexOutOfBoundsException("byte position of " + position); 39 | } 40 | int mask = ~(0xff << position * 8); 41 | int insert = (b << position * 8) & ~mask; 42 | return i & mask | insert; 43 | } 44 | 45 | public static long setByte(long l, byte b, int position) { 46 | if (position > 7) { 47 | throw new IndexOutOfBoundsException("position of " + position); 48 | } 49 | long mask = ~(0xffL << position * 8); 50 | long insert = ((long) b << position * 8) & ~mask; 51 | return l & mask | insert; 52 | } 53 | 54 | public static short getShort(long l, int position) { 55 | return (short) (l >> position * 16); 56 | } 57 | 58 | public static long setShort(long l, short b, int position) { 59 | if (position > 3) { 60 | throw new IndexOutOfBoundsException("short position of " + position); 61 | } 62 | long mask = ~(0xffffL << position * 16); 63 | long insert = ((long) b << position * 16) & ~mask; 64 | return l & mask | insert; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/gui/ScaledGuiButton.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.FontRenderer; 5 | import net.minecraft.client.gui.GuiButton; 6 | import net.minecraft.client.renderer.GlStateManager; 7 | 8 | public class ScaledGuiButton extends GuiButton { 9 | 10 | public ScaledGuiButton(int id, int x, int y, int w, int h, String s) { 11 | super(id, x, y, w, h, s); 12 | } 13 | 14 | public ScaledGuiButton(int id, int x, int y, String s) { 15 | super(id, x, y, s); 16 | } 17 | 18 | @Override 19 | public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) { 20 | if (!visible) { 21 | return; 22 | } 23 | 24 | int xScaled = x * 2; 25 | int yScaled = y * 2; 26 | int widthScaled = width * 2; 27 | int heightScaled = height * 2; 28 | 29 | hovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height; 30 | 31 | mc.getTextureManager().bindTexture(BUTTON_TEXTURES); 32 | GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); 33 | 34 | GlStateManager.enableBlend(); 35 | GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, 36 | GlStateManager.DestFactor.ZERO); 37 | GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); 38 | 39 | GlStateManager.pushMatrix(); 40 | GlStateManager.scale(0.5d, 0.5d, 0.5d); 41 | 42 | int hoverState = getHoverState(hovered); 43 | drawTexturedModalRect(xScaled, yScaled, 0, 46 + hoverState * 20, widthScaled / 2, heightScaled); 44 | drawTexturedModalRect(xScaled + widthScaled / 2, yScaled, 200 - widthScaled / 2, 46 + hoverState * 20, widthScaled / 2, heightScaled); 45 | mouseDragged(mc, mouseX, mouseY); 46 | 47 | int color = 14737632; 48 | if (packedFGColour != 0) { 49 | color = packedFGColour; 50 | } else if (!enabled) { 51 | color = 10526880; 52 | } else if (hovered) { 53 | color = 16777120; 54 | } 55 | 56 | FontRenderer fr = mc.fontRenderer; 57 | drawCenteredString(fr, displayString, xScaled + widthScaled / 2, yScaled + (heightScaled - 8) / 2, color); 58 | 59 | GlStateManager.popMatrix(); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/util/RedstoneUtil.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | import net.minecraft.block.BlockHorizontal; 4 | import net.minecraft.block.state.IBlockState; 5 | import net.minecraft.util.EnumFacing; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.world.IBlockAccess; 8 | 9 | public class RedstoneUtil { 10 | 11 | public static EnumFacing convertPortIndexToFacing(EnumFacing facing, int portIndex) { 12 | int rotation = getRotation(facing); 13 | return rotateFacing(EnumFacing.getFront(portIndex + 2), rotation); 14 | } 15 | 16 | public static int convertFacingToPortIndex(EnumFacing facing, EnumFacing side) { 17 | int rotation = getRotation(facing); 18 | return rotateFacing(side, -rotation).getIndex() - 2; 19 | } 20 | 21 | private static EnumFacing rotateFacing(EnumFacing facing, int rotation) { 22 | if (rotation >= 0) { 23 | for (int i = 0; i < rotation; i++) { 24 | facing = facing.rotateY(); 25 | } 26 | } else { 27 | rotation = -rotation; 28 | for (int i = 0; i < rotation; i++) { 29 | facing = facing.rotateYCCW(); 30 | } 31 | } 32 | return facing; 33 | } 34 | 35 | private static int getRotation(EnumFacing facing) { 36 | switch (facing) { 37 | case NORTH: 38 | return 0; 39 | case EAST: 40 | return 1; 41 | case SOUTH: 42 | return 2; 43 | case WEST: 44 | return 3; 45 | default: 46 | return -1; 47 | } 48 | } 49 | 50 | public static int portToPower(byte port) { 51 | return port & 0x0f; 52 | } 53 | 54 | public static byte powerToPort(int powerValue) { 55 | return (byte) Math.min(powerValue, 15); 56 | } 57 | 58 | public static boolean isFrontPort(IBlockState blockState, EnumFacing side) { 59 | return blockState.getValue(BlockHorizontal.FACING) == side; 60 | } 61 | 62 | public static boolean isBackPort(IBlockState blockState, EnumFacing side) { 63 | return blockState.getValue(BlockHorizontal.FACING).getOpposite() == side; 64 | } 65 | 66 | public static boolean isLeftPort(IBlockState blockState, EnumFacing side) { 67 | return blockState.getValue(BlockHorizontal.FACING).rotateYCCW() == side; 68 | } 69 | 70 | public static boolean isRightPort(IBlockState blockState, EnumFacing side) { 71 | return blockState.getValue(BlockHorizontal.FACING).rotateY() == side; 72 | } 73 | 74 | public static BlockPos getFrontBlock(IBlockAccess blockAccess, BlockPos pos) { 75 | return pos.offset(blockAccess.getBlockState(pos).getValue(BlockHorizontal.FACING)); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/network/AbstractMessageHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code and resources for our Code Book were taken from TIS-3D 3 | * (https://github.com/MightyPirates/TIS-3D), released under the MIT license 4 | * by Florian "Sangar" Nücke. 5 | */ 6 | 7 | package net.torocraft.minecoprocessors.network; 8 | 9 | import javax.annotation.Nullable; 10 | import net.minecraft.util.IThreadListener; 11 | import net.minecraft.world.World; 12 | import net.minecraftforge.common.DimensionManager; 13 | import net.minecraftforge.fml.client.FMLClientHandler; 14 | import net.minecraftforge.fml.common.FMLCommonHandler; 15 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 16 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 17 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 18 | import net.minecraftforge.fml.relauncher.Side; 19 | import net.minecraftforge.fml.relauncher.SideOnly; 20 | 21 | public abstract class AbstractMessageHandler implements IMessageHandler { 22 | 23 | @Override 24 | @Nullable 25 | public IMessage onMessage(final T message, final MessageContext context) { 26 | final IThreadListener thread = FMLCommonHandler.instance().getWorldThread(context.netHandler); 27 | if (thread.isCallingFromMinecraftThread()) { 28 | onMessageSynchronized(message, context); 29 | } else { 30 | thread.addScheduledTask(() -> onMessageSynchronized(message, context)); 31 | } 32 | return null; 33 | } 34 | 35 | // --------------------------------------------------------------------- // 36 | 37 | protected abstract void onMessageSynchronized(final T message, final MessageContext context); 38 | 39 | // --------------------------------------------------------------------- // 40 | 41 | @Nullable 42 | protected static World getWorld(final int dimension, final MessageContext context) { 43 | switch (context.side) { 44 | case CLIENT: 45 | return getWorldClient(dimension); 46 | case SERVER: 47 | return getWorldServer(dimension); 48 | } 49 | return null; 50 | } 51 | 52 | @SideOnly(Side.CLIENT) 53 | @Nullable 54 | private static World getWorldClient(final int dimension) { 55 | final World world = FMLClientHandler.instance().getClient().world; 56 | if (world == null) { 57 | return null; 58 | } 59 | if (world.provider.getDimension() != dimension) { 60 | return null; 61 | } 62 | return world; 63 | } 64 | 65 | @Nullable 66 | private static World getWorldServer(final int dimension) { 67 | return DimensionManager.getWorld(dimension); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/network/MessageEnableGuiUpdates.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.network; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.entity.player.EntityPlayerMP; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 7 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 8 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 9 | import net.minecraftforge.fml.relauncher.Side; 10 | import net.torocraft.minecoprocessors.Minecoprocessors; 11 | import net.torocraft.minecoprocessors.blocks.TileEntityMinecoprocessor; 12 | 13 | public class MessageEnableGuiUpdates implements IMessage { 14 | 15 | public BlockPos pos; 16 | public Boolean enable; 17 | 18 | public static void init(int packetId) { 19 | Minecoprocessors.NETWORK.registerMessage(MessageEnableGuiUpdates.Handler.class, MessageEnableGuiUpdates.class, packetId, Side.SERVER); 20 | } 21 | 22 | public MessageEnableGuiUpdates() { 23 | 24 | } 25 | 26 | public MessageEnableGuiUpdates(BlockPos controlBlockPos, Boolean enable) { 27 | this.pos = controlBlockPos; 28 | this.enable = enable; 29 | } 30 | 31 | @Override 32 | public void fromBytes(ByteBuf buf) { 33 | pos = BlockPos.fromLong(buf.readLong()); 34 | enable = buf.readBoolean(); 35 | } 36 | 37 | @Override 38 | public void toBytes(ByteBuf buf) { 39 | buf.writeLong(pos.toLong()); 40 | buf.writeBoolean(enable); 41 | } 42 | 43 | public static class Handler implements IMessageHandler { 44 | 45 | @Override 46 | public IMessage onMessage(final MessageEnableGuiUpdates message, MessageContext ctx) { 47 | if (message.pos == null) { 48 | return null; 49 | } 50 | final EntityPlayerMP payer = ctx.getServerHandler().player; 51 | payer.getServerWorld().addScheduledTask(new Worker(payer, message)); 52 | return null; 53 | } 54 | } 55 | 56 | private static class Worker implements Runnable { 57 | 58 | private final EntityPlayerMP player; 59 | private final MessageEnableGuiUpdates message; 60 | 61 | public Worker(EntityPlayerMP player, MessageEnableGuiUpdates message) { 62 | this.player = player; 63 | this.message = message; 64 | } 65 | 66 | @Override 67 | public void run() { 68 | try { 69 | TileEntityMinecoprocessor mp = (TileEntityMinecoprocessor) player.world.getTileEntity(message.pos); 70 | mp.enablePlayerGuiUpdates(player, message.enable); 71 | } catch (Exception e) { 72 | Minecoprocessors.proxy.handleUnexpectedException(e); 73 | } 74 | } 75 | 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/network/MessageBookCodeData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code and resources for our Code Book were taken from TIS-3D 3 | * (https://github.com/MightyPirates/TIS-3D), released under the MIT license 4 | * by Florian "Sangar" Nücke. 5 | */ 6 | 7 | package net.torocraft.minecoprocessors.network; 8 | 9 | import io.netty.buffer.ByteBuf; 10 | import java.io.IOException; 11 | import net.minecraft.entity.player.EntityPlayer; 12 | import net.minecraft.item.ItemStack; 13 | import net.minecraft.nbt.NBTTagCompound; 14 | import net.minecraft.network.PacketBuffer; 15 | import net.minecraft.util.EnumHand; 16 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 17 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 18 | import net.minecraftforge.fml.relauncher.Side; 19 | import net.torocraft.minecoprocessors.Minecoprocessors; 20 | import net.torocraft.minecoprocessors.items.ItemBookCode; 21 | 22 | public final class MessageBookCodeData implements IMessage { 23 | 24 | private NBTTagCompound nbt; 25 | 26 | public static void init(int packetId) { 27 | Minecoprocessors.NETWORK.registerMessage(MessageBookCodeData.Handler.class, MessageBookCodeData.class, packetId, Side.SERVER); 28 | } 29 | 30 | public MessageBookCodeData(final NBTTagCompound nbt) { 31 | this.nbt = nbt; 32 | } 33 | 34 | public MessageBookCodeData() { 35 | } 36 | 37 | // --------------------------------------------------------------------- // 38 | 39 | public NBTTagCompound getNbt() { 40 | return nbt; 41 | } 42 | 43 | // --------------------------------------------------------------------- // 44 | // IMessage 45 | 46 | @Override 47 | public void fromBytes(final ByteBuf buf) { 48 | final PacketBuffer buffer = new PacketBuffer(buf); 49 | try { 50 | nbt = buffer.readCompoundTag(); 51 | } catch (final IOException e) { 52 | Minecoprocessors.proxy.logger.warn("Invalid packet received.", e); 53 | } 54 | } 55 | 56 | @Override 57 | public void toBytes(final ByteBuf buf) { 58 | final PacketBuffer buffer = new PacketBuffer(buf); 59 | buffer.writeCompoundTag(nbt); 60 | } 61 | 62 | public static final class Handler extends AbstractMessageHandler { 63 | 64 | @Override 65 | protected void onMessageSynchronized(final MessageBookCodeData message, final MessageContext context) { 66 | final EntityPlayer player = context.getServerHandler().player; 67 | if (player != null) { 68 | final ItemStack stack = player.getHeldItem(EnumHand.MAIN_HAND); 69 | if (ItemBookCode.isBookCode(stack)) { 70 | final ItemBookCode.Data data = ItemBookCode.Data.loadFromNBT(message.getNbt()); 71 | ItemBookCode.Data.saveToStack(stack, data); 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/blocks/ContainerMinecoprocessor.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.blocks; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.Container; 5 | import net.minecraft.inventory.IInventory; 6 | import net.minecraft.inventory.Slot; 7 | import net.minecraft.item.ItemStack; 8 | 9 | public class ContainerMinecoprocessor extends Container { 10 | 11 | private final IInventory te; 12 | @SuppressWarnings("unused") 13 | private final Slot codeBookSlot; 14 | 15 | public ContainerMinecoprocessor(IInventory playerInventory, IInventory te) { 16 | this.te = te; 17 | 18 | this.codeBookSlot = this.addSlotToContainer(new CodeBookSlot(te, 0, 80, 35)); 19 | 20 | for (int i = 0; i < 3; ++i) { 21 | for (int j = 0; j < 9; ++j) { 22 | this.addSlotToContainer(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); 23 | } 24 | } 25 | 26 | for (int k = 0; k < 9; ++k) { 27 | this.addSlotToContainer(new Slot(playerInventory, k, 8 + k * 18, 142)); 28 | } 29 | 30 | } 31 | 32 | static class CodeBookSlot extends Slot { 33 | 34 | public CodeBookSlot(IInventory iInventoryIn, int index, int xPosition, int yPosition) { 35 | super(iInventoryIn, index, xPosition, yPosition); 36 | } 37 | 38 | @Override 39 | public boolean isItemValid(ItemStack stack) { 40 | return TileEntityMinecoprocessor.isBook(stack.getItem()); 41 | } 42 | 43 | @Override 44 | public int getSlotStackLimit() { 45 | return 1; 46 | } 47 | } 48 | 49 | @Override 50 | public void detectAndSendChanges() { 51 | 52 | } 53 | 54 | @Override 55 | public boolean canInteractWith(EntityPlayer player) { 56 | return te.isUsableByPlayer(player); 57 | } 58 | 59 | @Override 60 | public ItemStack transferStackInSlot(EntityPlayer playerIn, int fromSlot) { 61 | ItemStack previous = ItemStack.EMPTY; 62 | Slot slot = this.inventorySlots.get(fromSlot); 63 | 64 | if (slot != null && slot.getHasStack()) { 65 | ItemStack current = slot.getStack(); 66 | previous = current.copy(); 67 | 68 | if (fromSlot == 0) { 69 | if (!this.mergeItemStack(current, 1, 37, true)) { 70 | return ItemStack.EMPTY; 71 | } 72 | } else { 73 | if (!this.mergeItemStack(current, 0, 1, true)) { 74 | return ItemStack.EMPTY; 75 | } 76 | } 77 | 78 | slot.onSlotChange(current, previous); 79 | 80 | if (current.isEmpty()) { 81 | slot.putStack(ItemStack.EMPTY); 82 | } else { 83 | slot.onSlotChanged(); 84 | } 85 | 86 | if (current.getCount() == previous.getCount()) { 87 | return ItemStack.EMPTY; 88 | } 89 | 90 | slot.onTake(playerIn, current); 91 | } 92 | 93 | return previous; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/network/MessageProcessorUpdate.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.network; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import net.minecraft.util.IThreadListener; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraftforge.fml.common.network.ByteBufUtils; 9 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 10 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 11 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 12 | import net.minecraftforge.fml.relauncher.Side; 13 | import net.torocraft.minecoprocessors.Minecoprocessors; 14 | import net.torocraft.minecoprocessors.gui.GuiMinecoprocessor; 15 | 16 | public class MessageProcessorUpdate implements IMessage { 17 | 18 | public BlockPos pos; 19 | public String name; 20 | public NBTTagCompound processorData; 21 | 22 | public static void init(int packetId) { 23 | Minecoprocessors.NETWORK.registerMessage(MessageProcessorUpdate.Handler.class, MessageProcessorUpdate.class, packetId, Side.CLIENT); 24 | } 25 | 26 | public MessageProcessorUpdate() { 27 | 28 | } 29 | 30 | public MessageProcessorUpdate(NBTTagCompound processorData, BlockPos pos, String name) { 31 | this.processorData = processorData; 32 | this.pos = pos; 33 | this.name = name; 34 | } 35 | 36 | @Override 37 | public void fromBytes(ByteBuf buf) { 38 | processorData = ByteBufUtils.readTag(buf); 39 | pos = BlockPos.fromLong(buf.readLong()); 40 | name = ByteBufUtils.readUTF8String(buf); 41 | } 42 | 43 | @Override 44 | public void toBytes(ByteBuf buf) { 45 | ByteBufUtils.writeTag(buf, processorData); 46 | buf.writeLong(pos.toLong()); 47 | ByteBufUtils.writeUTF8String(buf, name); 48 | } 49 | 50 | public static class Handler implements IMessageHandler { 51 | 52 | @Override 53 | public IMessage onMessage(final MessageProcessorUpdate message, MessageContext ctx) { 54 | 55 | if (message.processorData == null || message.processorData == null) { 56 | return null; 57 | } 58 | 59 | IThreadListener mainThread = Minecraft.getMinecraft(); 60 | 61 | mainThread.addScheduledTask(new Runnable() { 62 | @Override 63 | public void run() { 64 | if (GuiMinecoprocessor.INSTANCE == null) { 65 | return; 66 | } 67 | 68 | if (!GuiMinecoprocessor.INSTANCE.getPos().equals(message.pos)) { 69 | Minecoprocessors.NETWORK.sendToServer(new MessageEnableGuiUpdates(message.pos, false)); 70 | return; 71 | } 72 | 73 | GuiMinecoprocessor.INSTANCE.updateData(message.processorData, message.name); 74 | } 75 | }); 76 | 77 | return null; 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/books/manual.txt: -------------------------------------------------------------------------------- 1 | Redstone Processor Manual 2 | Minecoprocessors 3 | 4 | Minecoprocessors 5 | 6 | Redstone 7 | Processor 8 | Manual 9 | 10 | ~~~ 11 | §1Visit the Wiki§r 12 | 13 | For more information, visit the wiki: 14 | 15 | https://github.com/ToroCraft/Minecoprocessors/wiki 16 | ~~~ 17 | §1Instructions§r 18 | 19 | §lMOV a, b§r Move 20 | §lPUSH a§r Push to Stack 21 | §lPOP a§r Pop from Stack 22 | §lNOP§r No Operation 23 | §lHLT§r Halt Processor 24 | §lCLC§r Clear Carry 25 | §lSEC§r Set Carry 26 | §lCLZ§r Clear Zero 27 | §lSEZ§r Set Zero 28 | §lHLT§r Halt Processor 29 | §lWFE§r Sleep (experimental) 30 | ~~~ 31 | §1Arithmetic Instructions§r 32 | 33 | §lADD a, b§r Add 34 | §lSUB a, b§r Subtract 35 | §lMUL a§r Multiply 36 | §lDIV a§r Divide 37 | §lINC a§r Increment by 1 38 | §lDEC a§r Decrement by 1 39 | ~~~ 40 | §1Logical Instructions§r 41 | 42 | §lAND a, b§r Bitwise AND 43 | §lOR a, b§r Bitwise OR 44 | §lXOR a, b§r Bitwise XOR 45 | §lNOT a§r Bitwise NOT 46 | ~~~ 47 | §1Shift Instructions§r 48 | 49 | §lSHL a§r Shift Left 50 | §lSHR a§r Shift Right 51 | §lSAR a§r Arithmetic Right 52 | §lSAL a§r Arithmetic Left 53 | §lROR a§r Rotate Right 54 | §lROL a§r Rotate Right 55 | ~~~ 56 | §1Loop Instructions§r 57 | 58 | §lJMP label§r Jump 59 | §lJZ label§r Jump if Zero 60 | §lJNZ label§r not Zero 61 | §lJC label§r if Carry 62 | §lJNC label§r if no Carry 63 | §lDJNZ a, label§r Dec and Jump if not zero 64 | §lCALL label§r Call 65 | §lRET§r Return 66 | §lCMP a, b§r Compare 67 | ~~~ 68 | §1Number Formats§r 69 | 70 | §l-1§r two's complement 71 | §l0xff§r Hexadecimal 72 | §l0o377§r Octal 73 | §l11111111b§r Binary 74 | ~~~ 75 | §1Registers§r 76 | 77 | The redstone processor has four one byte general purpose registers: 78 | §la b c d§r 79 | along with four port registers: 80 | §lpf pb pl pr§r 81 | which control the font, back, left and right ports respectively. 82 | ~~~ 83 | §1Ports§r 84 | 85 | There is one additional register, §lports§r, that is used to set mode of the ports. There are three modes that the ports can be set to: input, output or reset. 86 | ~~~ 87 | Put a zero value in corresponding low nibble bit to set a port as an output, or set it to one to use it as an input port. 88 | 89 | Set the corresponding bits in both the high and low nibble to use the port as a reset port. 90 | ~~~ 91 | §1Flags§r 92 | 93 | §lZ§r Zero Flag 94 | §lC§r Carry Flag 95 | §lF§r Fault Flag 96 | §lS§r Sleep Flag 97 | ~~~ 98 | 99 | Example Programs 100 | 101 | ~~~ 102 | §1Repeater§r 103 | 104 | mov ports, 0010b 105 | start: 106 | mov pf, pb 107 | jmp start 108 | ~~~ 109 | §13 Input AND Gate§r 110 | 111 | mov ports, 1110b 112 | start: 113 | mov a, pb 114 | and a, pl 115 | and a, pr 116 | mov pf, a 117 | jmp start 118 | ~~~ 119 | §1Enabled-clock§r 120 | §1Pulse Multiplier§r 121 | 122 | mov ports, 0010b 123 | start: 124 | cmp pb, 0 125 | jz off 126 | not pf 127 | jmp start 128 | off: 129 | mov pf, 0 130 | jmp start 131 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/network/MessageProcessorAction.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.network; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.entity.player.EntityPlayerMP; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 7 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 8 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 9 | import net.minecraftforge.fml.relauncher.Side; 10 | import net.torocraft.minecoprocessors.Minecoprocessors; 11 | import net.torocraft.minecoprocessors.blocks.TileEntityMinecoprocessor; 12 | 13 | public class MessageProcessorAction implements IMessage { 14 | 15 | public enum Action { 16 | RESET, PAUSE, STEP 17 | } 18 | 19 | public Action action; 20 | public BlockPos pos; 21 | 22 | public static void init(int packetId) { 23 | Minecoprocessors.NETWORK.registerMessage(MessageProcessorAction.Handler.class, MessageProcessorAction.class, packetId, Side.SERVER); 24 | } 25 | 26 | public MessageProcessorAction() { 27 | 28 | } 29 | 30 | public MessageProcessorAction(BlockPos pos, Action action) { 31 | this.action = action; 32 | this.pos = pos; 33 | } 34 | 35 | @Override 36 | public void fromBytes(ByteBuf buf) { 37 | action = Action.values()[buf.readInt()]; 38 | pos = BlockPos.fromLong(buf.readLong()); 39 | } 40 | 41 | @Override 42 | public void toBytes(ByteBuf buf) { 43 | buf.writeInt(action.ordinal()); 44 | buf.writeLong(pos.toLong()); 45 | } 46 | 47 | public static class Handler implements IMessageHandler { 48 | 49 | @Override 50 | public IMessage onMessage(final MessageProcessorAction message, MessageContext ctx) { 51 | if (message.action == null) { 52 | return null; 53 | } 54 | final EntityPlayerMP payer = ctx.getServerHandler().player; 55 | payer.getServerWorld().addScheduledTask(new Worker(payer, message)); 56 | return null; 57 | } 58 | } 59 | 60 | private static class Worker implements Runnable { 61 | 62 | private final EntityPlayerMP player; 63 | private final MessageProcessorAction message; 64 | 65 | public Worker(EntityPlayerMP player, MessageProcessorAction message) { 66 | this.player = player; 67 | this.message = message; 68 | } 69 | 70 | @Override 71 | public void run() { 72 | try { 73 | TileEntityMinecoprocessor mp = (TileEntityMinecoprocessor) player.world.getTileEntity(message.pos); 74 | 75 | switch (message.action) { 76 | case PAUSE: 77 | mp.getProcessor().setWait(!mp.getProcessor().isWait()); 78 | mp.updatePlayers(); 79 | break; 80 | case RESET: 81 | mp.reset(); 82 | break; 83 | case STEP: 84 | mp.getProcessor().setStep(true); 85 | break; 86 | } 87 | 88 | } catch (Exception e) { 89 | Minecoprocessors.proxy.handleUnexpectedException(e); 90 | } 91 | } 92 | 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/util/BookCreator.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.io.UncheckedIOException; 9 | import java.nio.charset.StandardCharsets; 10 | import net.minecraft.init.Items; 11 | import net.minecraft.item.ItemStack; 12 | import net.minecraft.nbt.NBTTagCompound; 13 | import net.minecraft.nbt.NBTTagList; 14 | import net.minecraft.nbt.NBTTagString; 15 | import net.minecraft.util.text.ITextComponent; 16 | import net.minecraft.util.text.TextComponentString; 17 | 18 | public class BookCreator { 19 | 20 | private static final String PATH = "/assets/minecoprocessors/books/"; 21 | private static final String PAGE_DELIMITER = "~~~"; 22 | public static final ItemStack manual; 23 | 24 | static { 25 | try { 26 | manual = loadBook("manual"); 27 | } catch (IOException e) { 28 | throw new UncheckedIOException(e); 29 | } 30 | } 31 | 32 | private static ItemStack loadBook(String name) throws IOException { 33 | ItemStack book = new ItemStack(Items.WRITTEN_BOOK); 34 | String line; 35 | int lineNumber = 1; 36 | StringBuilder page = newPage(); 37 | try (BufferedReader reader = openBookReader(name)) { 38 | while ((line = reader.readLine()) != null) { 39 | if (lineNumber == 1) { 40 | book.setTagInfo("title", new NBTTagString(line)); 41 | } else if (lineNumber == 2) { 42 | book.setTagInfo("author", new NBTTagString(line)); 43 | } else if (PAGE_DELIMITER.equals(line)) { 44 | writePage(book, page); 45 | page = newPage(); 46 | } else { 47 | page.append(line).append("\n"); 48 | } 49 | lineNumber++; 50 | } 51 | } 52 | writePage(book, page); 53 | return book; 54 | } 55 | 56 | private static BufferedReader openBookReader(String name) throws FileNotFoundException { 57 | String path = PATH + name + ".txt"; 58 | InputStream is = BookCreator.class.getResourceAsStream(path); 59 | if (is == null) { 60 | throw new FileNotFoundException("Book file not found [" + path + "]"); 61 | } 62 | return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); 63 | } 64 | 65 | private static void writePage(ItemStack book, StringBuilder page) { 66 | NBTTagList pages = getPagesNbt(book); 67 | pages.appendTag(createPage(page.toString())); 68 | book.setTagInfo("pages", pages); 69 | } 70 | 71 | private static NBTTagList getPagesNbt(ItemStack book) { 72 | if (book.getTagCompound() == null) { 73 | book.setTagCompound(new NBTTagCompound()); 74 | } 75 | return book.getTagCompound().getTagList("pages", 8); 76 | } 77 | 78 | private static StringBuilder newPage() { 79 | return new StringBuilder(256); 80 | } 81 | 82 | private static NBTTagString createPage(String page) { 83 | return new NBTTagString(ITextComponent.Serializer.componentToJson(new TextComponentString(page))); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/net/torocraft/minecoprocessors/util/RedstoneUtilTest.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | import mockit.Deencapsulation; 4 | import net.minecraft.util.EnumFacing; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class RedstoneUtilTest { 9 | 10 | @Test 11 | public void testPortToPower() { 12 | Assert.assertEquals(0, RedstoneUtil.portToPower((byte) 0x00)); 13 | Assert.assertEquals(0, RedstoneUtil.portToPower((byte) 0xf0)); 14 | Assert.assertEquals(1, RedstoneUtil.portToPower((byte) 0x11)); 15 | Assert.assertEquals(1, RedstoneUtil.portToPower((byte) 0xf1)); 16 | Assert.assertEquals(15, RedstoneUtil.portToPower((byte) 0xff)); 17 | Assert.assertEquals(15, RedstoneUtil.portToPower((byte) 0x0f)); 18 | } 19 | 20 | @Test 21 | public void testPowerToPort() { 22 | Assert.assertEquals((byte) 0x00, RedstoneUtil.powerToPort(0)); 23 | Assert.assertEquals((byte) 0x01, RedstoneUtil.powerToPort(1)); 24 | Assert.assertEquals((byte) 0x0e, RedstoneUtil.powerToPort(14)); 25 | Assert.assertEquals((byte) 0x0f, RedstoneUtil.powerToPort(15)); 26 | } 27 | 28 | @Test 29 | public void testConvertPortIndexToFacing() { 30 | int f = 0; 31 | int b = 1; 32 | int l = 2; 33 | int r = 3; 34 | Assert.assertEquals(EnumFacing.NORTH, RedstoneUtil.convertPortIndexToFacing(EnumFacing.NORTH, f)); 35 | Assert.assertEquals(EnumFacing.EAST, RedstoneUtil.convertPortIndexToFacing(EnumFacing.NORTH, r)); 36 | Assert.assertEquals(EnumFacing.SOUTH, RedstoneUtil.convertPortIndexToFacing(EnumFacing.NORTH, b)); 37 | Assert.assertEquals(EnumFacing.EAST, RedstoneUtil.convertPortIndexToFacing(EnumFacing.EAST, f)); 38 | Assert.assertEquals(EnumFacing.WEST, RedstoneUtil.convertPortIndexToFacing(EnumFacing.EAST, b)); 39 | Assert.assertEquals(EnumFacing.NORTH, RedstoneUtil.convertPortIndexToFacing(EnumFacing.EAST, l)); 40 | Assert.assertEquals(EnumFacing.NORTH, RedstoneUtil.convertPortIndexToFacing(EnumFacing.SOUTH, b)); 41 | Assert.assertEquals(EnumFacing.NORTH, RedstoneUtil.convertPortIndexToFacing(EnumFacing.WEST, r)); 42 | } 43 | 44 | @Test 45 | public void testConvertFacingToPortIndex() { 46 | int f = 0; 47 | int b = 1; 48 | int l = 2; 49 | int r = 3; 50 | Assert.assertEquals(f, RedstoneUtil.convertFacingToPortIndex(EnumFacing.NORTH, EnumFacing.NORTH)); 51 | Assert.assertEquals(b, RedstoneUtil.convertFacingToPortIndex(EnumFacing.NORTH, EnumFacing.SOUTH)); 52 | Assert.assertEquals(r, RedstoneUtil.convertFacingToPortIndex(EnumFacing.EAST, EnumFacing.SOUTH)); 53 | Assert.assertEquals(r, RedstoneUtil.convertFacingToPortIndex(EnumFacing.WEST, EnumFacing.NORTH)); 54 | Assert.assertEquals(l, RedstoneUtil.convertFacingToPortIndex(EnumFacing.SOUTH, EnumFacing.EAST)); 55 | } 56 | 57 | @Test 58 | public void testRotateFacing() { 59 | Assert.assertEquals(EnumFacing.EAST, Deencapsulation.invoke(RedstoneUtil.class, "rotateFacing", EnumFacing.NORTH, -3)); 60 | Assert.assertEquals(EnumFacing.NORTH, Deencapsulation.invoke(RedstoneUtil.class, "rotateFacing", EnumFacing.NORTH, 0)); 61 | Assert.assertEquals(EnumFacing.EAST, Deencapsulation.invoke(RedstoneUtil.class, "rotateFacing", EnumFacing.EAST, 0)); 62 | Assert.assertEquals(EnumFacing.EAST, Deencapsulation.invoke(RedstoneUtil.class, "rotateFacing", EnumFacing.WEST, -2)); 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/block/minecoprocessor_off.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientocclusion": false, 3 | "textures": { 4 | "particle": "blocks/repeater_on", 5 | "slab": "blocks/stone_slab_top", 6 | "top": "minecoprocessors:blocks/minecoprocessor", 7 | "unlit": "blocks/redstone_torch_off", 8 | "redstone": "blocks/redstone_block" 9 | }, 10 | 11 | "elements": [ 12 | { "from": [ 0, 0, 0 ], 13 | "to": [ 16, 3, 16 ], 14 | "faces": { 15 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#slab", "cullface": "down" }, 16 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, 17 | "north": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "north" }, 18 | "south": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "south" }, 19 | "west": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "west" }, 20 | "east": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "east" } 21 | } 22 | }, 23 | 24 | { "from": [ 5, 0, 5 ], 25 | "to": [ 11, 5, 11 ], 26 | "faces": { 27 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "down" }, 28 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone" }, 29 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "north" }, 30 | "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "south" }, 31 | "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "west" }, 32 | "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "east" } 33 | } 34 | }, 35 | 36 | 37 | { "from": [ 1, 3, 1 ], 38 | "to": [ 3, 8, 3 ], 39 | "faces": { 40 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 41 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 42 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 43 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 44 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 45 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 46 | } 47 | }, 48 | 49 | { "from": [ 1, 3, 13 ], 50 | "to": [ 3, 8, 15 ], 51 | "faces": { 52 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 53 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 54 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 55 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 56 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 57 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 58 | } 59 | }, 60 | 61 | 62 | { "from": [13, 3, 1 ], 63 | "to": [ 15, 8, 3 ], 64 | "faces": { 65 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 66 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 67 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 68 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 69 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 70 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 71 | } 72 | }, 73 | 74 | { "from": [ 13, 3, 13 ], 75 | "to": [ 15, 8, 15 ], 76 | "faces": { 77 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 78 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 79 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 80 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 81 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 82 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 83 | } 84 | } 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/net/torocraft/minecoprocessors/util/ByteUtilTest.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class ByteUtilTest { 7 | 8 | @Test 9 | public void testSetBit() { 10 | Assert.assertEquals((byte) 0xfe, ByteUtil.setBit((byte) 0xff, false, 0)); 11 | Assert.assertEquals((byte) 0x7e, ByteUtil.setBit((byte) 0xfe, false, 7)); 12 | Assert.assertEquals((byte) 0xfe, ByteUtil.setBit((byte) 0x7e, true, 7)); 13 | Assert.assertEquals((byte) 0xff, ByteUtil.setBit((byte) 0xfe, true, 0)); 14 | } 15 | 16 | @Test 17 | public void testGetBit() { 18 | byte b = (byte) 0xfe; 19 | Assert.assertTrue(ByteUtil.getBit(b, 7)); 20 | Assert.assertTrue(ByteUtil.getBit(b, 1)); 21 | Assert.assertFalse(ByteUtil.getBit(b, 0)); 22 | 23 | b = (byte) 0x7e; 24 | Assert.assertFalse(ByteUtil.getBit(b, 7)); 25 | } 26 | 27 | @Test 28 | public void testGetByte() { 29 | short s = (short) 0xabcd; 30 | Assert.assertEquals((byte) 0xcd, ByteUtil.getByte(s, 0)); 31 | Assert.assertEquals((byte) 0xab, ByteUtil.getByte(s, 1)); 32 | } 33 | 34 | @Test 35 | public void testSetByte() { 36 | short s = (short) 0x0f00; 37 | Assert.assertEquals((short) 0x0fab, ByteUtil.setByte(s, (byte) 0xab, 0)); 38 | Assert.assertEquals((short) 0x6900, ByteUtil.setByte(s, (byte) 0x69, 1)); 39 | } 40 | 41 | @Test 42 | public void testGetShort() { 43 | long l = Long.parseLong("0123456789abcdef", 16); 44 | Assert.assertEquals((short) 0xcdef, ByteUtil.getShort(l, 0)); 45 | Assert.assertEquals((short) 0x89ab, ByteUtil.getShort(l, 1)); 46 | Assert.assertEquals((short) 0x4567, ByteUtil.getShort(l, 2)); 47 | Assert.assertEquals((short) 0x0123, ByteUtil.getShort(l, 3)); 48 | } 49 | 50 | @Test 51 | public void testSetShort() { 52 | long l = Long.parseLong("0123456789abcdef", 16); 53 | l = ByteUtil.setShort(l, (short) 0x0ffff, 1); 54 | Assert.assertEquals("1234567ffffcdef", Long.toString(l, 16)); 55 | 56 | l = ByteUtil.setShort(l, (short) 0x01111, 3); 57 | Assert.assertEquals("11114567ffffcdef", Long.toString(l, 16)); 58 | 59 | l = ByteUtil.setShort(l, (short) 0x0aaaa, 2); 60 | Assert.assertEquals("1111aaaaffffcdef", Long.toString(l, 16)); 61 | 62 | l = ByteUtil.setShort(l, (short) 0x09999, 0); 63 | Assert.assertEquals("1111aaaaffff9999", Long.toString(l, 16)); 64 | } 65 | 66 | @Test 67 | public void testByteInIntMethods() { 68 | int i = 0x12345678; 69 | Assert.assertEquals(0x78, ByteUtil.getByte(i, 0)); 70 | Assert.assertEquals(0x56, ByteUtil.getByte(i, 1)); 71 | Assert.assertEquals(0x34, ByteUtil.getByte(i, 2)); 72 | Assert.assertEquals(0x12, ByteUtil.getByte(i, 3)); 73 | 74 | i = ByteUtil.setByte(i, (byte) 0xee, 1); 75 | Assert.assertEquals(0x1234ee78, i); 76 | 77 | i = ByteUtil.setByte(i, (byte) 0xff, 3); 78 | Assert.assertEquals(0xff34ee78, i); 79 | 80 | i = ByteUtil.setByte(i, (byte) 0xcc, 2); 81 | Assert.assertEquals(0xffccee78, i); 82 | 83 | i = ByteUtil.setByte(i, (byte) 0xaa, 0); 84 | Assert.assertEquals(0xffcceeaa, i); 85 | } 86 | 87 | @Test 88 | public void testByteInLongMethods() { 89 | long l = Long.parseLong("0123456789abcdef", 16); 90 | Assert.assertEquals((byte) 0xef, ByteUtil.getByte(l, 0)); 91 | Assert.assertEquals((byte) 0xcd, ByteUtil.getByte(l, 1)); 92 | Assert.assertEquals((byte) 0xab, ByteUtil.getByte(l, 2)); 93 | Assert.assertEquals((byte) 0x89, ByteUtil.getByte(l, 3)); 94 | Assert.assertEquals((byte) 0x01, ByteUtil.getByte(l, 7)); 95 | 96 | l = ByteUtil.setByte(l, (byte) 0x33, 1); 97 | Assert.assertEquals("123456789ab33ef", Long.toString(l, 16)); 98 | 99 | l = ByteUtil.setByte(l, (byte) 0xee, 4); 100 | Assert.assertEquals("12345ee89ab33ef", Long.toString(l, 16)); 101 | 102 | l = ByteUtil.setByte(l, (byte) 0xff, 7); 103 | Assert.assertEquals("ff2345ee89ab33ef", Long.toUnsignedString(l, 16)); 104 | } 105 | 106 | @Test 107 | public void testBitMethods() { 108 | long l = Long.parseLong("0110010", 2); 109 | 110 | Assert.assertFalse(ByteUtil.getBit(l, 0)); 111 | Assert.assertTrue(ByteUtil.getBit(l, 1)); 112 | Assert.assertFalse(ByteUtil.getBit(l, 2)); 113 | Assert.assertFalse(ByteUtil.getBit(l, 3)); 114 | Assert.assertTrue(ByteUtil.getBit(l, 4)); 115 | Assert.assertTrue(ByteUtil.getBit(l, 5)); 116 | Assert.assertFalse(ByteUtil.getBit(l, 6)); 117 | Assert.assertFalse(ByteUtil.getBit(l, 7)); 118 | 119 | l = ByteUtil.setBit(l, true, 0); 120 | Assert.assertEquals("110011", Long.toBinaryString(l)); 121 | 122 | l = ByteUtil.setBit(l, true, 2); 123 | Assert.assertEquals("110111", Long.toBinaryString(l)); 124 | 125 | l = ByteUtil.setBit(l, false, 0); 126 | l = ByteUtil.setBit(l, false, 2); 127 | Assert.assertEquals("110010", Long.toBinaryString(l)); 128 | } 129 | } -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/block/minecoprocessor_on.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientocclusion": false, 3 | "textures": { 4 | "particle": "blocks/repeater_on", 5 | "slab": "blocks/stone_slab_top", 6 | "top": "minecoprocessors:blocks/minecoprocessor", 7 | "unlit": "blocks/redstone_torch_off", 8 | "redstone": "blocks/redstone_block", 9 | "lit": "blocks/redstone_torch_on" 10 | }, 11 | 12 | "elements": [ 13 | { "from": [ 0, 0, 0 ], 14 | "to": [ 16, 3, 16 ], 15 | "faces": { 16 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#slab", "cullface": "down" }, 17 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, 18 | "north": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "north" }, 19 | "south": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "south" }, 20 | "west": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "west" }, 21 | "east": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "east" } 22 | } 23 | }, 24 | 25 | { "from": [ 5, 0, 5 ], 26 | "to": [ 11, 5, 11 ], 27 | "faces": { 28 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "down" }, 29 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone" }, 30 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "north" }, 31 | "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "south" }, 32 | "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "west" }, 33 | "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "east" } 34 | } 35 | }, 36 | 37 | { "from": [ 1, 8, 1 ], 38 | "to": [ 3, 8, 3 ], 39 | "faces": { 40 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 41 | } 42 | }, 43 | { "from": [ 1, 2, 0 ], 44 | "to": [ 3, 9, 4 ], 45 | "faces": { 46 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 47 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 48 | } 49 | }, 50 | { "from": [ 0, 2, 1 ], 51 | "to": [ 4, 9, 3 ], 52 | "faces": { 53 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 54 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 55 | } 56 | }, 57 | 58 | 59 | { "from": [ 1, 8, 13 ], 60 | "to": [ 3, 8, 15 ], 61 | "faces": { 62 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 63 | } 64 | }, 65 | { "from": [ 1, 2, 12 ], 66 | "to": [ 3, 9, 16 ], 67 | "faces": { 68 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 69 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 70 | } 71 | }, 72 | { "from": [ 0, 2, 13 ], 73 | "to": [ 4, 9, 15 ], 74 | "faces": { 75 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 76 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 77 | } 78 | }, 79 | 80 | { "from": [ 13, 8, 1 ], 81 | "to": [ 15, 8, 3 ], 82 | "faces": { 83 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 84 | } 85 | }, 86 | { "from": [ 13, 2, 0 ], 87 | "to": [ 15, 9, 4 ], 88 | "faces": { 89 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 90 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 91 | } 92 | }, 93 | { "from": [ 12, 2, 1 ], 94 | "to": [ 16, 9, 3 ], 95 | "faces": { 96 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 97 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 98 | } 99 | }, 100 | 101 | { "from": [ 13, 8, 13 ], 102 | "to": [ 15, 8, 15 ], 103 | "faces": { 104 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 105 | } 106 | }, 107 | { "from": [ 13, 2, 12 ], 108 | "to": [ 15, 9, 16 ], 109 | "faces": { 110 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 111 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 112 | } 113 | }, 114 | { "from": [ 12, 2, 13 ], 115 | "to": [ 16, 9, 15 ], 116 | "faces": { 117 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 118 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 119 | } 120 | } 121 | ] 122 | } 123 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/block/minecoprocessor_overclocked_off.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientocclusion": false, 3 | "textures": { 4 | "particle": "blocks/repeater_on", 5 | "slab": "blocks/stone_slab_top", 6 | "top": "minecoprocessors:blocks/minecoprocessor", 7 | "unlit": "blocks/redstone_torch_off", 8 | "diamond": "blocks/diamond_block", 9 | "redstone": "blocks/redstone_block" 10 | }, 11 | 12 | "elements": [ 13 | { "from": [ 0, 0, 0 ], 14 | "to": [ 16, 3, 16 ], 15 | "faces": { 16 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#slab", "cullface": "down" }, 17 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, 18 | "north": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "north" }, 19 | "south": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "south" }, 20 | "west": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "west" }, 21 | "east": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "east" } 22 | } 23 | }, 24 | 25 | { "from": [ 5, 0, 5 ], 26 | "to": [ 11, 5, 11 ], 27 | "faces": { 28 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "down" }, 29 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone" }, 30 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "north" }, 31 | "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "south" }, 32 | "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "west" }, 33 | "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "east" } 34 | } 35 | }, 36 | 37 | { 38 | "from": [ 4, 0, 4 ], 39 | "to": [ 12, 4, 12 ], 40 | "faces": { 41 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "down" }, 42 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond" }, 43 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "north" }, 44 | "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "south" }, 45 | "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "west" }, 46 | "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "east" } 47 | } 48 | }, 49 | 50 | 51 | { "from": [ 1, 3, 1 ], 52 | "to": [ 3, 8, 3 ], 53 | "faces": { 54 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 55 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 56 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 57 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 58 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 59 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 60 | } 61 | }, 62 | 63 | { "from": [ 1, 3, 13 ], 64 | "to": [ 3, 8, 15 ], 65 | "faces": { 66 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 67 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 68 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 69 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 70 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 71 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 72 | } 73 | }, 74 | 75 | 76 | { "from": [13, 3, 1 ], 77 | "to": [ 15, 8, 3 ], 78 | "faces": { 79 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 80 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 81 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 82 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 83 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 84 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 85 | } 86 | }, 87 | 88 | { "from": [ 13, 3, 13 ], 89 | "to": [ 15, 8, 15 ], 90 | "faces": { 91 | "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#unlit" }, 92 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#unlit" }, 93 | "north": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 94 | "south": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 95 | "west": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" }, 96 | "east": { "uv": [ 7, 6, 9, 11 ], "texture": "#unlit" } 97 | } 98 | } 99 | ] 100 | } 101 | -------------------------------------------------------------------------------- /src/main/resources/assets/minecoprocessors/models/block/minecoprocessor_overclocked_on.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientocclusion": false, 3 | "textures": { 4 | "particle": "blocks/repeater_on", 5 | "slab": "blocks/stone_slab_top", 6 | "top": "minecoprocessors:blocks/minecoprocessor", 7 | "unlit": "blocks/redstone_torch_off", 8 | "redstone": "blocks/redstone_block", 9 | "diamond": "blocks/diamond_block", 10 | "lit": "blocks/redstone_torch_on" 11 | }, 12 | 13 | "elements": [ 14 | 15 | { 16 | "from": [ 0, 0, 0 ], 17 | "to": [ 16, 3, 16 ], 18 | "faces": { 19 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#slab", "cullface": "down" }, 20 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, 21 | "north": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "north" }, 22 | "south": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "south" }, 23 | "west": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "west" }, 24 | "east": { "uv": [ 0, 13, 16, 16 ], "texture": "#slab", "cullface": "east" } 25 | } 26 | }, 27 | 28 | { 29 | "from": [ 5, 0, 5 ], 30 | "to": [ 11, 5, 11 ], 31 | "faces": { 32 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "down" }, 33 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone" }, 34 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "north" }, 35 | "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "south" }, 36 | "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "west" }, 37 | "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#redstone", "cullface": "east" } 38 | } 39 | }, 40 | 41 | { 42 | "from": [ 4, 0, 4 ], 43 | "to": [ 12, 4, 12 ], 44 | "faces": { 45 | "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "down" }, 46 | "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond" }, 47 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "north" }, 48 | "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "south" }, 49 | "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "west" }, 50 | "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#diamond", "cullface": "east" } 51 | } 52 | }, 53 | 54 | { "from": [ 1, 8, 1 ], 55 | "to": [ 3, 8, 3 ], 56 | "faces": { 57 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 58 | } 59 | }, 60 | { "from": [ 1, 2, 0 ], 61 | "to": [ 3, 9, 4 ], 62 | "faces": { 63 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 64 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 65 | } 66 | }, 67 | { "from": [ 0, 2, 1 ], 68 | "to": [ 4, 9, 3 ], 69 | "faces": { 70 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 71 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 72 | } 73 | }, 74 | 75 | 76 | { "from": [ 1, 8, 13 ], 77 | "to": [ 3, 8, 15 ], 78 | "faces": { 79 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 80 | } 81 | }, 82 | { "from": [ 1, 2, 12 ], 83 | "to": [ 3, 9, 16 ], 84 | "faces": { 85 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 86 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 87 | } 88 | }, 89 | { "from": [ 0, 2, 13 ], 90 | "to": [ 4, 9, 15 ], 91 | "faces": { 92 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 93 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 94 | } 95 | }, 96 | 97 | { "from": [ 13, 8, 1 ], 98 | "to": [ 15, 8, 3 ], 99 | "faces": { 100 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 101 | } 102 | }, 103 | { "from": [ 13, 2, 0 ], 104 | "to": [ 15, 9, 4 ], 105 | "faces": { 106 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 107 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 108 | } 109 | }, 110 | { "from": [ 12, 2, 1 ], 111 | "to": [ 16, 9, 3 ], 112 | "faces": { 113 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 114 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 115 | } 116 | }, 117 | 118 | { "from": [ 13, 8, 13 ], 119 | "to": [ 15, 8, 15 ], 120 | "faces": { 121 | "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#lit" } 122 | } 123 | }, 124 | { "from": [ 13, 2, 12 ], 125 | "to": [ 15, 9, 16 ], 126 | "faces": { 127 | "west": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 128 | "east": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 129 | } 130 | }, 131 | { "from": [ 12, 2, 13 ], 132 | "to": [ 16, 9, 15 ], 133 | "faces": { 134 | "north": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" }, 135 | "south": { "uv": [ 6, 5, 10, 11 ], "texture": "#lit" } 136 | } 137 | } 138 | ] 139 | } 140 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/items/ItemBookCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Code and resources for our Code Book were taken from TIS-3D 3 | * (https://github.com/MightyPirates/TIS-3D), released under the MIT license 4 | * by Florian "Sangar" Nücke. 5 | */ 6 | 7 | package net.torocraft.minecoprocessors.items; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | import java.util.Objects; 14 | import java.util.regex.Pattern; 15 | import javax.annotation.Nullable; 16 | import net.minecraft.client.renderer.block.model.ModelResourceLocation; 17 | import net.minecraft.client.util.ITooltipFlag; 18 | import net.minecraft.creativetab.CreativeTabs; 19 | import net.minecraft.entity.player.EntityPlayer; 20 | import net.minecraft.init.Items; 21 | import net.minecraft.inventory.InventoryCrafting; 22 | import net.minecraft.item.Item; 23 | import net.minecraft.item.ItemBook; 24 | import net.minecraft.item.ItemStack; 25 | import net.minecraft.item.crafting.IRecipe; 26 | import net.minecraft.item.crafting.Ingredient; 27 | import net.minecraft.item.crafting.ShapelessRecipes; 28 | import net.minecraft.nbt.NBTTagCompound; 29 | import net.minecraft.nbt.NBTTagList; 30 | import net.minecraft.nbt.NBTTagString; 31 | import net.minecraft.util.ActionResult; 32 | import net.minecraft.util.EnumHand; 33 | import net.minecraft.util.NonNullList; 34 | import net.minecraft.util.ResourceLocation; 35 | import net.minecraft.world.World; 36 | import net.minecraftforge.client.event.ModelRegistryEvent; 37 | import net.minecraftforge.client.model.ModelLoader; 38 | import net.minecraftforge.event.RegistryEvent; 39 | import net.minecraftforge.fml.common.Mod; 40 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 41 | import net.minecraftforge.fml.relauncher.Side; 42 | import net.minecraftforge.fml.relauncher.SideOnly; 43 | import net.minecraftforge.oredict.OreDictionary; 44 | import net.torocraft.minecoprocessors.Minecoprocessors; 45 | import net.torocraft.minecoprocessors.blocks.BlockMinecoprocessor; 46 | import net.torocraft.minecoprocessors.gui.MinecoprocessorGuiHandler; 47 | 48 | /** 49 | * The code book, utility book for coding ASM programs for execution modules. 50 | */ 51 | @Mod.EventBusSubscriber 52 | public final class ItemBookCode extends ItemBook { 53 | 54 | public static final Pattern PATTERN_LINES = Pattern.compile("\r?\n"); 55 | public static final int MAX_LINES_PER_PAGE = 20; 56 | 57 | public static final String NAME = "book_code"; 58 | private static final ResourceLocation REGISTRY_NAME = new ResourceLocation(Minecoprocessors.MODID, NAME); 59 | 60 | public static final ItemBookCode INSTANCE = new ItemBookCode(); 61 | 62 | public static boolean isBookCode(ItemStack stack) { 63 | return !stack.isEmpty() && stack.getItem() == INSTANCE; 64 | } 65 | 66 | @SubscribeEvent 67 | public static void init(final RegistryEvent.Register event) { 68 | event.getRegistry().register(INSTANCE); 69 | OreDictionary.registerOre("book", ItemBookCode.INSTANCE); 70 | } 71 | 72 | @SubscribeEvent 73 | public static void registerModels(@SuppressWarnings("unused") ModelRegistryEvent event) { 74 | ModelLoader.setCustomModelResourceLocation(INSTANCE, 0, new ModelResourceLocation(REGISTRY_NAME, "inventory")); 75 | } 76 | 77 | @SubscribeEvent 78 | public static void registerRecipes(final RegistryEvent.Register event) { 79 | NonNullList lst = NonNullList.create(); 80 | lst.add(Ingredient.fromItem(Items.WRITABLE_BOOK)); 81 | lst.add(Ingredient.fromItem(BlockMinecoprocessor.ITEM_INSTANCE)); 82 | event.getRegistry().register(new ShapelessRecipes("", new ItemStack(ItemBookCode.INSTANCE), lst) { 83 | @Override 84 | public NonNullList getRemainingItems(InventoryCrafting inv) { 85 | NonNullList l = NonNullList.withSize(inv.getSizeInventory(), ItemStack.EMPTY); 86 | 87 | for (int i = 0; i < l.size(); ++i) { 88 | ItemStack stack = inv.getStackInSlot(i); 89 | 90 | if (stack.getItem() == BlockMinecoprocessor.ITEM_INSTANCE) { 91 | ItemStack returnStack = stack.copy(); 92 | returnStack.setCount(1); 93 | l.set(i, returnStack); 94 | return l; 95 | } 96 | } 97 | 98 | throw new RuntimeException("Item to return not found in inventory"); 99 | } 100 | }.setRegistryName(ItemBookCode.REGISTRY_NAME)); 101 | } 102 | 103 | protected ItemBookCode() { 104 | setMaxStackSize(1); 105 | setCreativeTab(CreativeTabs.REDSTONE); 106 | setUnlocalizedName(NAME); 107 | setRegistryName(REGISTRY_NAME); 108 | } 109 | 110 | // --------------------------------------------------------------------- // 111 | // Item 112 | 113 | @Override 114 | public ActionResult onItemRightClick(final World world, final EntityPlayer player, final EnumHand hand) { 115 | if (world.isRemote) { 116 | player.openGui(Minecoprocessors.INSTANCE, MinecoprocessorGuiHandler.MINECOPROCESSOR_BOOK_GUI, world, 0, 0, 0); 117 | } 118 | return super.onItemRightClick(world, player, hand); 119 | } 120 | 121 | // --------------------------------------------------------------------- // 122 | // ItemBook 123 | 124 | @Override 125 | public boolean isEnchantable(final ItemStack stack) { 126 | return false; 127 | } 128 | 129 | @Override 130 | public int getItemEnchantability() { 131 | return 0; 132 | } 133 | 134 | @SideOnly(Side.CLIENT) 135 | @Override 136 | public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { 137 | tooltip.add(Minecoprocessors.proxy.i18nFormat("item.book_code.tooltip")); 138 | } 139 | 140 | // --------------------------------------------------------------------- // 141 | 142 | /** 143 | * Wrapper for list of pages stored in the code book. 144 | */ 145 | public static class Data { 146 | 147 | //public static final String CONTINUATION_MACRO = "#BWTM"; 148 | private static final String TAG_PAGES = "pages"; 149 | private static final String TAG_SELECTED = "selected"; 150 | 151 | private final List> pages = new ArrayList<>(); 152 | private int selectedPage = 0; 153 | 154 | // --------------------------------------------------------------------- // 155 | 156 | /** 157 | * Get the page currently selected in the book. 158 | * 159 | * @return the index of the selected page. 160 | */ 161 | public int getSelectedPage() { 162 | return selectedPage; 163 | } 164 | 165 | /** 166 | * Set which page is currently selected. 167 | * 168 | * @param index the new selected index. 169 | */ 170 | public void setSelectedPage(final int index) { 171 | this.selectedPage = index; 172 | validateSelectedPage(); 173 | } 174 | 175 | /** 176 | * Get the number of pages stored in the book. 177 | * 178 | * @return the number of pages stored in the book. 179 | */ 180 | public int getPageCount() { 181 | return pages.size(); 182 | } 183 | 184 | /** 185 | * Get the code on the specified page. 186 | * 187 | * @param index the index of the page to get the code of. 188 | * @return the code on the page. 189 | */ 190 | public List getPage(final int index) { 191 | return Collections.unmodifiableList(pages.get(index)); 192 | } 193 | 194 | /** 195 | * Add a new, blank page to the book. 196 | */ 197 | public void addPage() { 198 | pages.add(Collections.singletonList("")); 199 | setSelectedPage(pages.size() - 1); 200 | } 201 | 202 | /** 203 | * Overwrite a page at the specified index. 204 | * 205 | * @param page the index of the page to overwrite. 206 | * @param code the code of the page. 207 | */ 208 | public void setPage(final int page, final List code) { 209 | pages.set(page, new ArrayList<>(code)); 210 | } 211 | 212 | /** 213 | * Remove a page from the book. 214 | * 215 | * @param index the index of the page to remove. 216 | */ 217 | public void removePage(final int index) { 218 | pages.remove(index); 219 | validateSelectedPage(); 220 | } 221 | 222 | /** 223 | * Get the complete program of the selected page, taking into account the #BWTM preprocessor macro allowing programs to span multiple pages. 224 | * 225 | * @return the full program starting on the current page. 226 | */ 227 | public List> getProgram() { 228 | return Collections.unmodifiableList(pages); 229 | } 230 | 231 | public List getContinuousProgram() { 232 | final List program = new ArrayList<>(); 233 | for (int i = 0; i < pages.size(); i++) { 234 | program.addAll(getPage(i)); 235 | } 236 | return program; 237 | } 238 | 239 | /** 240 | * Load data from the specified NBT tag. 241 | * 242 | * @param nbt the tag to load the data from. 243 | */ 244 | public void readFromNBT(final NBTTagCompound nbt) { 245 | pages.clear(); 246 | 247 | final NBTTagList pagesNbt = nbt.getTagList(TAG_PAGES, net.minecraftforge.common.util.Constants.NBT.TAG_STRING); 248 | for (int index = 0; index < pagesNbt.tagCount(); index++) { 249 | pages.add(Arrays.asList(PATTERN_LINES.split(pagesNbt.getStringTagAt(index)))); 250 | } 251 | 252 | selectedPage = nbt.getInteger(TAG_SELECTED); 253 | validateSelectedPage(); 254 | } 255 | 256 | /** 257 | * Store the data to the specified NBT tag. 258 | * 259 | * @param nbt the tag to save the data to. 260 | */ 261 | public void writeToNBT(final NBTTagCompound nbt) { 262 | final NBTTagList pagesNbt = new NBTTagList(); 263 | int removed = 0; 264 | for (int index = 0; index < pages.size(); index++) { 265 | final List program = pages.get(index); 266 | if (program.size() > 1 || program.get(0).length() > 0) { 267 | pagesNbt.appendTag(new NBTTagString(String.join("\n", program))); 268 | } else if (index < selectedPage) { 269 | removed++; 270 | } 271 | } 272 | nbt.setTag(TAG_PAGES, pagesNbt); 273 | 274 | nbt.setInteger(TAG_SELECTED, selectedPage - removed); 275 | } 276 | 277 | // --------------------------------------------------------------------- // 278 | 279 | private void validateSelectedPage() { 280 | selectedPage = Math.max(0, Math.min(pages.size() - 1, selectedPage)); 281 | } 282 | 283 | private boolean areAllPagesEqual(final List> newPages, final int startPage) { 284 | for (int offset = 0; offset < newPages.size(); offset++) { 285 | final List have = pages.get(startPage + offset); 286 | final List want = newPages.get(offset); 287 | if (!Objects.equals(have, want)) { 288 | return false; 289 | } 290 | } 291 | 292 | return true; 293 | } 294 | 295 | // --------------------------------------------------------------------- // 296 | 297 | /** 298 | * Load code book data from the specified NBT tag. 299 | * 300 | * @param nbt the tag to load the data from. 301 | * @return the data loaded from the tag. 302 | */ 303 | public static Data loadFromNBT(@Nullable final NBTTagCompound nbt) { 304 | final Data data = new Data(); 305 | if (nbt != null) { 306 | data.readFromNBT(nbt); 307 | } 308 | return data; 309 | } 310 | 311 | /** 312 | * Load code book data from the specified item stack. 313 | * 314 | * @param stack the item stack to load the data from. 315 | * @return the data loaded from the stack. 316 | */ 317 | public static Data loadFromStack(final ItemStack stack) { 318 | return loadFromNBT(stack.getTagCompound()); 319 | } 320 | 321 | /** 322 | * Save the specified code book data to the specified item stack. 323 | * 324 | * @param stack the item stack to save the data to. 325 | * @param data the data to save to the item stack. 326 | */ 327 | public static void saveToStack(final ItemStack stack, final Data data) { 328 | NBTTagCompound nbt = stack.getTagCompound(); 329 | if (nbt == null) { 330 | stack.setTagCompound(nbt = new NBTTagCompound()); 331 | } 332 | data.writeToNBT(nbt); 333 | } 334 | } 335 | } 336 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/blocks/BlockMinecoprocessor.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.blocks; 2 | 3 | import java.util.Random; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.block.BlockRedstoneDiode; 6 | import net.minecraft.block.BlockRedstoneWire; 7 | import net.minecraft.block.ITileEntityProvider; 8 | import net.minecraft.block.properties.IProperty; 9 | import net.minecraft.block.properties.PropertyBool; 10 | import net.minecraft.block.state.BlockStateContainer; 11 | import net.minecraft.block.state.IBlockState; 12 | import net.minecraft.client.Minecraft; 13 | import net.minecraft.client.renderer.block.model.ModelBakery; 14 | import net.minecraft.client.renderer.block.model.ModelResourceLocation; 15 | import net.minecraft.creativetab.CreativeTabs; 16 | import net.minecraft.entity.EntityLivingBase; 17 | import net.minecraft.entity.player.EntityPlayer; 18 | import net.minecraft.init.Blocks; 19 | import net.minecraft.inventory.InventoryHelper; 20 | import net.minecraft.item.Item; 21 | import net.minecraft.item.ItemStack; 22 | import net.minecraft.tileentity.TileEntity; 23 | import net.minecraft.util.EnumFacing; 24 | import net.minecraft.util.EnumHand; 25 | import net.minecraft.util.Mirror; 26 | import net.minecraft.util.NonNullList; 27 | import net.minecraft.util.ResourceLocation; 28 | import net.minecraft.util.Rotation; 29 | import net.minecraft.util.math.AxisAlignedBB; 30 | import net.minecraft.util.math.BlockPos; 31 | import net.minecraft.world.IBlockAccess; 32 | import net.minecraft.world.World; 33 | import net.minecraftforge.event.RegistryEvent; 34 | import net.minecraftforge.fml.common.Mod; 35 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 36 | import net.torocraft.minecoprocessors.Minecoprocessors; 37 | import net.torocraft.minecoprocessors.gui.MinecoprocessorGuiHandler; 38 | import net.torocraft.minecoprocessors.items.IMetaBlockName; 39 | import net.torocraft.minecoprocessors.items.ItemBlockMeta; 40 | import net.torocraft.minecoprocessors.util.RedstoneUtil; 41 | 42 | @Mod.EventBusSubscriber 43 | public class BlockMinecoprocessor extends BlockRedstoneDiode implements ITileEntityProvider, IMetaBlockName { 44 | 45 | protected static final AxisAlignedBB AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.1875D, 1.0D); 46 | 47 | public static final PropertyBool ACTIVE = PropertyBool.create("active"); 48 | public static final PropertyBool OVERCLOCKED = PropertyBool.create("overclocked"); 49 | 50 | public static final String NAME = "minecoprocessor"; 51 | 52 | private static ResourceLocation REGISTRY_NAME = new ResourceLocation(Minecoprocessors.MODID, NAME); 53 | private static ResourceLocation REGISTRY_OVERCLOCKED_NAME = new ResourceLocation(Minecoprocessors.MODID, NAME + "_overclocked"); 54 | 55 | public static BlockMinecoprocessor INSTANCE = (BlockMinecoprocessor) new BlockMinecoprocessor() 56 | .setUnlocalizedName(NAME) 57 | .setRegistryName(REGISTRY_NAME); 58 | 59 | public static ItemBlockMeta ITEM_INSTANCE = (ItemBlockMeta) new ItemBlockMeta(INSTANCE). 60 | setRegistryName(REGISTRY_NAME); 61 | 62 | @SubscribeEvent 63 | public static void initBlock(final RegistryEvent.Register event) { 64 | event.getRegistry().register(INSTANCE); 65 | } 66 | 67 | @SubscribeEvent 68 | public static void initItem(final RegistryEvent.Register event) { 69 | event.getRegistry().register(ITEM_INSTANCE); 70 | } 71 | 72 | public static void preRegisterRenders() { 73 | ModelBakery.registerItemVariants(ITEM_INSTANCE, REGISTRY_NAME, REGISTRY_OVERCLOCKED_NAME); 74 | } 75 | 76 | public static void registerRenders() { 77 | registerRender(REGISTRY_NAME.toString(), 0); 78 | registerRender(REGISTRY_OVERCLOCKED_NAME.toString(), 4); 79 | } 80 | 81 | private static void registerRender(String file, int meta) { 82 | ModelResourceLocation model = new ModelResourceLocation(file, "inventory"); 83 | Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(ITEM_INSTANCE, meta, model); 84 | } 85 | 86 | @Override 87 | public int damageDropped(IBlockState state) { 88 | return getMetaFromState(state) & 4; 89 | } 90 | 91 | @Override 92 | public void getSubBlocks(CreativeTabs itemIn, NonNullList items) { 93 | items.add(new ItemStack(ITEM_INSTANCE)); 94 | items.add(new ItemStack(ITEM_INSTANCE, 1, 4)); 95 | } 96 | 97 | @Override 98 | public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, 99 | EntityLivingBase placer) { 100 | return super.getStateForPlacement(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer) 101 | .withProperty(OVERCLOCKED, Boolean.valueOf((meta & 4) > 0)) 102 | .withProperty(ACTIVE, Boolean.valueOf(false)); 103 | } 104 | 105 | @Override 106 | protected BlockStateContainer createBlockState() { 107 | return new BlockStateContainer(this, new IProperty[]{FACING, ACTIVE, OVERCLOCKED}); 108 | } 109 | 110 | @Override 111 | protected IBlockState getPoweredState(IBlockState unpoweredState) { 112 | return getUnpoweredState(unpoweredState); 113 | } 114 | 115 | @Override 116 | protected IBlockState getUnpoweredState(IBlockState poweredState) { 117 | Boolean obool = poweredState.getValue(ACTIVE); 118 | EnumFacing enumfacing = poweredState.getValue(FACING); 119 | return INSTANCE.getDefaultState().withProperty(FACING, enumfacing).withProperty(ACTIVE, obool); 120 | } 121 | 122 | /** 123 | * Convert the given metadata into a BlockState for this Block 124 | */ 125 | @Override 126 | public IBlockState getStateFromMeta(int meta) { 127 | IBlockState state = getDefaultState() 128 | .withProperty(FACING, EnumFacing.getHorizontal(meta)).withProperty(ACTIVE, Boolean.valueOf((meta & 8) > 0)) 129 | .withProperty(OVERCLOCKED, Boolean.valueOf((meta & 4) > 0)); 130 | return state; 131 | } 132 | 133 | /** 134 | * Convert the BlockState into the correct metadata value 135 | */ 136 | @Override 137 | public int getMetaFromState(IBlockState state) { 138 | int i = state.getValue(FACING).getHorizontalIndex(); 139 | 140 | if (state.getValue(ACTIVE)) { 141 | i |= 8; 142 | } 143 | 144 | if (state.getValue(OVERCLOCKED)) { 145 | i |= 4; 146 | } 147 | return i; 148 | } 149 | 150 | @Override 151 | public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { 152 | return AABB; 153 | } 154 | 155 | public BlockMinecoprocessor() { 156 | super(true); 157 | this.setDefaultState( 158 | this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(OVERCLOCKED, Boolean.valueOf(false)) 159 | .withProperty(ACTIVE, Boolean.valueOf(false))); 160 | setCreativeTab(CreativeTabs.REDSTONE); 161 | } 162 | 163 | @Override 164 | public TileEntity createNewTileEntity(World worldIn, int meta) { 165 | return new TileEntityMinecoprocessor(); 166 | } 167 | 168 | @Override 169 | public boolean canProvidePower(IBlockState state) { 170 | return true; 171 | } 172 | 173 | @Override 174 | protected void updateState(World worldIn, BlockPos pos, IBlockState state) { 175 | worldIn.updateBlockTick(pos, this, 0, -1); 176 | } 177 | 178 | public void onPortChange(World worldIn, BlockPos pos, IBlockState state, int portIndex) { 179 | notifyNeighborsOnSide(worldIn, pos, RedstoneUtil.convertPortIndexToFacing(state.getValue(FACING).getOpposite(), portIndex)); 180 | } 181 | 182 | protected void notifyNeighborsOnSide(World worldIn, BlockPos pos, EnumFacing side) { 183 | BlockPos neighborPos = pos.offset(side); 184 | if (net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(worldIn, pos, worldIn.getBlockState(pos), java.util.EnumSet.of(side), false) 185 | .isCanceled()) { 186 | return; 187 | } 188 | worldIn.neighborChanged(neighborPos, this, pos); 189 | worldIn.notifyNeighborsOfStateExcept(neighborPos, this, side.getOpposite()); 190 | } 191 | 192 | @Override 193 | public void updateTick(World world, BlockPos pos, IBlockState state, Random rand) { 194 | super.updateTick(world, pos, state, rand); 195 | updateInputPorts(world, pos, state); 196 | 197 | if (world.isRemote) { 198 | return; 199 | } 200 | 201 | TileEntityMinecoprocessor te = (TileEntityMinecoprocessor) world.getTileEntity(pos); 202 | 203 | boolean changed = false; 204 | 205 | boolean blockActive = state.getValue(ACTIVE); 206 | boolean processorActive = !te.getProcessor().isWait() && !te.getProcessor().isFault(); 207 | 208 | if (blockActive && !processorActive) { 209 | state = state.withProperty(ACTIVE, Boolean.valueOf(false)); 210 | changed = true; 211 | } else if (!blockActive && processorActive) { 212 | state = state.withProperty(ACTIVE, Boolean.valueOf(true)); 213 | changed = true; 214 | } 215 | 216 | if (changed) { 217 | world.setBlockState(pos, state, 2); 218 | } 219 | } 220 | 221 | public static void updateInputPorts(World world, BlockPos pos, IBlockState state) { 222 | if (world.isRemote) { 223 | return; 224 | } 225 | EnumFacing facing = state.getValue(FACING).getOpposite(); 226 | 227 | int e = calculateInputStrength(world, pos.offset(EnumFacing.EAST), EnumFacing.EAST); 228 | int w = calculateInputStrength(world, pos.offset(EnumFacing.WEST), EnumFacing.WEST); 229 | int n = calculateInputStrength(world, pos.offset(EnumFacing.NORTH), EnumFacing.NORTH); 230 | int s = calculateInputStrength(world, pos.offset(EnumFacing.SOUTH), EnumFacing.SOUTH); 231 | 232 | int[] values = new int[4]; 233 | 234 | values[RedstoneUtil.convertFacingToPortIndex(facing, EnumFacing.NORTH)] = n; 235 | values[RedstoneUtil.convertFacingToPortIndex(facing, EnumFacing.SOUTH)] = s; 236 | values[RedstoneUtil.convertFacingToPortIndex(facing, EnumFacing.WEST)] = w; 237 | values[RedstoneUtil.convertFacingToPortIndex(facing, EnumFacing.EAST)] = e; 238 | 239 | ((TileEntityMinecoprocessor) world.getTileEntity(pos)).updateInputPorts(values); 240 | } 241 | 242 | protected static int calculateInputStrength(World worldIn, BlockPos pos, EnumFacing enumfacing) { 243 | IBlockState adjacentState = worldIn.getBlockState(pos); 244 | Block block = adjacentState.getBlock(); 245 | 246 | int i = worldIn.getRedstonePower(pos, enumfacing); 247 | 248 | if (i >= 15) { 249 | return 15; 250 | } 251 | 252 | int redstoneWirePower = 0; 253 | 254 | if (block == Blocks.REDSTONE_WIRE) { 255 | redstoneWirePower = adjacentState.getValue(BlockRedstoneWire.POWER); 256 | } 257 | 258 | return Math.max(i, redstoneWirePower); 259 | 260 | } 261 | 262 | @Override 263 | public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { 264 | super.onBlockPlacedBy(worldIn, pos, state, placer, stack); 265 | if (stack.hasDisplayName()) { 266 | TileEntity tileentity = worldIn.getTileEntity(pos); 267 | 268 | if (tileentity instanceof TileEntityMinecoprocessor) { 269 | ((TileEntityMinecoprocessor) tileentity).setName(stack.getDisplayName()); 270 | } 271 | } 272 | } 273 | 274 | @Override 275 | public int getStrongPower(IBlockState state, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { 276 | return state.getWeakPower(blockAccess, pos, side); 277 | } 278 | 279 | @Override 280 | public int getWeakPower(IBlockState state, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) { 281 | TileEntityMinecoprocessor te = ((TileEntityMinecoprocessor) blockAccess.getTileEntity(pos)); 282 | 283 | if (te.getWorld().isRemote) { 284 | return 0; 285 | } 286 | 287 | if (RedstoneUtil.isFrontPort(state, side)) { 288 | return RedstoneUtil.portToPower(te.getFrontPortSignal()); 289 | } 290 | 291 | if (RedstoneUtil.isBackPort(state, side)) { 292 | return RedstoneUtil.portToPower(te.getBackPortSignal()); 293 | } 294 | 295 | if (RedstoneUtil.isLeftPort(state, side)) { 296 | return RedstoneUtil.portToPower(te.getLeftPortSignal()); 297 | } 298 | 299 | if (RedstoneUtil.isRightPort(state, side)) { 300 | return RedstoneUtil.portToPower(te.getRightPortSignal()); 301 | } 302 | 303 | return 0; 304 | } 305 | 306 | @Override 307 | public IBlockState withRotation(IBlockState state, Rotation rot) { 308 | return state.withProperty(FACING, rot.rotate(state.getValue(FACING))); 309 | } 310 | 311 | @Override 312 | public IBlockState withMirror(IBlockState state, Mirror mirrorIn) { 313 | return state.withRotation(mirrorIn.toRotation(state.getValue(FACING))); 314 | } 315 | 316 | @Override 317 | public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, 318 | float hitY, float hitZ) { 319 | 320 | if (!world.isRemote) { 321 | player.openGui(Minecoprocessors.INSTANCE, MinecoprocessorGuiHandler.MINECOPROCESSOR_ENTITY_GUI, world, pos.getX(), pos.getY(), 322 | pos.getZ()); 323 | } 324 | 325 | return true; 326 | } 327 | 328 | @Override 329 | protected int getDelay(IBlockState state) { 330 | return 0; 331 | } 332 | 333 | @Override 334 | public boolean isLocked(IBlockAccess worldIn, BlockPos pos, IBlockState state) { 335 | return true; 336 | } 337 | 338 | @Override 339 | protected boolean isAlternateInput(IBlockState state) { 340 | return true; 341 | } 342 | 343 | @Override 344 | public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { 345 | notifyNeighbors(worldIn, pos, state); 346 | 347 | TileEntity tileentity = worldIn.getTileEntity(pos); 348 | if (tileentity instanceof TileEntityMinecoprocessor) { 349 | InventoryHelper.dropInventoryItems(worldIn, pos, (TileEntityMinecoprocessor) tileentity); 350 | } 351 | super.breakBlock(worldIn, pos, state); 352 | } 353 | 354 | @Override 355 | public String getSpecialName(ItemStack stack) { 356 | return getUnlocalizedName() + ((stack.getItemDamage() & 4) == 0 ? "" : "_overclocked"); 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/blocks/TileEntityMinecoprocessor.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.blocks; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonParser; 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | import java.util.Set; 9 | import java.util.regex.Pattern; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.entity.player.EntityPlayer; 12 | import net.minecraft.entity.player.EntityPlayerMP; 13 | import net.minecraft.init.Items; 14 | import net.minecraft.inventory.IInventory; 15 | import net.minecraft.inventory.ItemStackHelper; 16 | import net.minecraft.item.Item; 17 | import net.minecraft.item.ItemStack; 18 | import net.minecraft.nbt.NBTTagCompound; 19 | import net.minecraft.nbt.NBTTagList; 20 | import net.minecraft.tileentity.TileEntity; 21 | import net.minecraft.util.ITickable; 22 | import net.minecraft.util.NonNullList; 23 | import net.minecraft.util.math.BlockPos; 24 | import net.minecraft.util.text.ITextComponent; 25 | import net.minecraft.util.text.TextComponentString; 26 | import net.minecraft.util.text.TextComponentTranslation; 27 | import net.minecraft.world.World; 28 | import net.minecraftforge.fml.common.registry.GameRegistry; 29 | import net.torocraft.minecoprocessors.Minecoprocessors; 30 | import net.torocraft.minecoprocessors.items.ItemBookCode; 31 | import net.torocraft.minecoprocessors.network.MessageProcessorUpdate; 32 | import net.torocraft.minecoprocessors.processor.Processor; 33 | import net.torocraft.minecoprocessors.processor.Register; 34 | import net.torocraft.minecoprocessors.util.ByteUtil; 35 | import net.torocraft.minecoprocessors.util.InstructionUtil; 36 | import net.torocraft.minecoprocessors.util.RedstoneUtil; 37 | 38 | public class TileEntityMinecoprocessor extends TileEntity implements ITickable, IInventory { 39 | 40 | private static final String NAME = "minecoprocessor_tile_entity"; 41 | private static final String NBT_PROCESSOR = "processor"; 42 | private static final String NBT_LOAD_TIME = "loadTime"; 43 | private static final String NBT_CUSTOM_NAME = "CustomName"; 44 | 45 | private final Processor processor = new Processor(); 46 | 47 | private NonNullList codeItemStacks = NonNullList.withSize(1, ItemStack.EMPTY); 48 | private String customName; 49 | private int loadTime; 50 | private boolean loaded; 51 | private Set playersToUpdate = new HashSet<>(); 52 | 53 | private final byte[] prevPortValues = new byte[4]; 54 | private byte prevPortsRegister = 0x0f; 55 | 56 | private boolean prevIsInactive; 57 | private boolean overClocked; 58 | 59 | public static void init() { 60 | GameRegistry.registerTileEntity(TileEntityMinecoprocessor.class, NAME); 61 | } 62 | 63 | @Override 64 | public void onLoad() { 65 | overClocked = world.getBlockState(pos).getValue(BlockMinecoprocessor.OVERCLOCKED); 66 | } 67 | 68 | @Override 69 | public boolean shouldRefresh(World worldIn, BlockPos blockPos, IBlockState oldState, IBlockState newState) { 70 | return BlockMinecoprocessor.INSTANCE != oldState.getBlock() || BlockMinecoprocessor.INSTANCE != newState.getBlock(); 71 | } 72 | 73 | @Override 74 | public void readFromNBT(NBTTagCompound c) { 75 | super.readFromNBT(c); 76 | processor.readFromNBT(c.getCompoundTag(NBT_PROCESSOR)); 77 | 78 | codeItemStacks = NonNullList.withSize(this.getSizeInventory(), ItemStack.EMPTY); 79 | ItemStackHelper.loadAllItems(c, codeItemStacks); 80 | 81 | loadTime = c.getShort(NBT_LOAD_TIME); 82 | 83 | if (c.hasKey(NBT_CUSTOM_NAME, 8)) { 84 | this.customName = c.getString(NBT_CUSTOM_NAME); 85 | } 86 | } 87 | 88 | @Override 89 | public NBTTagCompound writeToNBT(NBTTagCompound cIn) { 90 | NBTTagCompound c = super.writeToNBT(cIn); 91 | c.setTag(NBT_PROCESSOR, processor.writeToNBT()); 92 | 93 | c.setShort(NBT_LOAD_TIME, (short) loadTime); 94 | ItemStackHelper.saveAllItems(c, codeItemStacks); 95 | 96 | if (this.hasCustomName()) { 97 | c.setString(NBT_CUSTOM_NAME, this.customName); 98 | } 99 | 100 | return c; 101 | } 102 | 103 | @Override 104 | public void update() { 105 | if (world.isRemote) { 106 | return; 107 | } 108 | 109 | if (!overClocked && world.getTotalWorldTime() % 2 != 0) { 110 | return; 111 | } 112 | 113 | boolean isInactive = processor.isWait() || processor.isFault(); 114 | 115 | if (prevIsInactive != isInactive) { 116 | prevIsInactive = isInactive; 117 | int priority = -1; 118 | world.updateBlockTick(pos, BlockMinecoprocessor.INSTANCE, 0, priority); 119 | } 120 | /* 121 | if (prevIsHot != processor.isHot()) { 122 | prevIsHot = processor.isHot(); 123 | int priority = -1; 124 | world.updateBlockTick(pos, BlockMinecoprocessor.INSTANCE, 0, priority); 125 | } 126 | */ 127 | if (!loaded) { 128 | Processor.reset(prevPortValues); 129 | prevPortsRegister = 0x0f; 130 | BlockMinecoprocessor.updateInputPorts(world, pos, world.getBlockState(pos)); 131 | loaded = true; 132 | } 133 | 134 | if (processor.tick()) { 135 | updatePlayers(); 136 | detectOutputChanges(); 137 | } 138 | 139 | if (prevPortsRegister != processor.getRegisters()[Register.PORTS.ordinal()]) { 140 | BlockMinecoprocessor.updateInputPorts(world, pos, world.getBlockState(pos)); 141 | prevPortsRegister = processor.getRegisters()[Register.PORTS.ordinal()]; 142 | } 143 | } 144 | 145 | public void updatePlayers() { 146 | for (EntityPlayerMP player : playersToUpdate) { 147 | Minecoprocessors.NETWORK.sendTo(new MessageProcessorUpdate(processor.writeToNBT(), pos, getName()), player); 148 | } 149 | } 150 | 151 | private void detectOutputChanges() { 152 | detectOutputChange(0); 153 | detectOutputChange(1); 154 | detectOutputChange(2); 155 | detectOutputChange(3); 156 | } 157 | 158 | private boolean detectOutputChange(int portIndex) { 159 | byte[] registers = processor.getRegisters(); 160 | byte ports = registers[Register.PORTS.ordinal()]; 161 | 162 | byte curVal = registers[Register.PF.ordinal() + portIndex]; 163 | 164 | if (isInOutputMode(ports, portIndex) && prevPortValues[portIndex] != curVal) { 165 | prevPortValues[portIndex] = curVal; 166 | BlockMinecoprocessor.INSTANCE.onPortChange(world, pos, world.getBlockState(pos), portIndex); 167 | return true; 168 | } 169 | return false; 170 | } 171 | 172 | public boolean updateInputPorts(int[] values) { 173 | boolean updated = false; 174 | for (int i = 0; i < 4; i++) { 175 | updated = updateInputPort(i, values[i]) || updated; 176 | } 177 | if (updated) { 178 | processor.wake(); 179 | } 180 | return updated; 181 | } 182 | 183 | public static boolean isInInputMode(byte ports, int portIndex) { 184 | return ByteUtil.getBit(ports, portIndex) && !ByteUtil.getBit(ports, portIndex + 4); 185 | } 186 | 187 | public static boolean isInOutputMode(byte ports, int portIndex) { 188 | return !ByteUtil.getBit(ports, portIndex) && !ByteUtil.getBit(ports, portIndex + 4); 189 | } 190 | 191 | public static boolean isADCMode(byte adc, int portIndex) { 192 | return ByteUtil.getBit(adc, portIndex); 193 | } 194 | 195 | public static boolean isInResetMode(byte ports, int portIndex) { 196 | return ByteUtil.getBit(ports, portIndex) && ByteUtil.getBit(ports, portIndex + 4); 197 | } 198 | 199 | /** 200 | * return true for positive edge changes 201 | */ 202 | private boolean updateInputPort(int portIndex, int powerValue) { 203 | byte[] registers = processor.getRegisters(); 204 | byte ports = registers[Register.PORTS.ordinal()]; 205 | byte adc = registers[Register.ADC.ordinal()]; 206 | byte value; 207 | 208 | if (isADCMode(adc, portIndex)) { 209 | value = RedstoneUtil.powerToPort(powerValue); 210 | } else if (powerValue == 0) { 211 | value = 0; 212 | } else { 213 | value = (byte) 0xff; 214 | } 215 | 216 | if (isInInputMode(ports, portIndex) && prevPortValues[portIndex] != value) { 217 | prevPortValues[portIndex] = value; 218 | registers[Register.PF.ordinal() + portIndex] = value; 219 | return true; 220 | } 221 | 222 | if (isInResetMode(ports, portIndex) && prevPortValues[portIndex] != value) { 223 | prevPortValues[portIndex] = value; 224 | 225 | if (value != 0) { 226 | processor.reset(); 227 | return true; 228 | } 229 | } 230 | 231 | return false; 232 | } 233 | 234 | private byte getPortSignal(int portIndex) { 235 | if (!isInOutputMode(processor.getRegisters()[Register.PORTS.ordinal()], portIndex)) { 236 | return 0; 237 | } 238 | byte signal = processor.getRegisters()[Register.PF.ordinal() + portIndex]; 239 | 240 | if (!isADCMode(processor.getRegisters()[Register.ADC.ordinal()], portIndex)) { 241 | return signal == 0 ? 0 : (byte) 0xff; 242 | } 243 | 244 | return signal; 245 | } 246 | 247 | public byte getFrontPortSignal() { 248 | return getPortSignal(0); 249 | } 250 | 251 | public byte getBackPortSignal() { 252 | return getPortSignal(1); 253 | } 254 | 255 | public byte getLeftPortSignal() { 256 | return getPortSignal(2); 257 | } 258 | 259 | public byte getRightPortSignal() { 260 | return getPortSignal(3); 261 | } 262 | 263 | public void reset() { 264 | if (world.isRemote) { 265 | return; 266 | } 267 | processor.reset(); 268 | for (int portIndex = 0; portIndex < 4; portIndex++) { 269 | detectOutputChange(portIndex); 270 | } 271 | loaded = false; 272 | } 273 | 274 | @Override 275 | public ItemStack getStackInSlot(int index) { 276 | return index >= 0 && index < codeItemStacks.size() ? codeItemStacks.get(index) : ItemStack.EMPTY; 277 | } 278 | 279 | @Override 280 | public ItemStack decrStackSize(int index, int count) { 281 | markDirty(); 282 | return ItemStackHelper.getAndSplit(codeItemStacks, index, count); 283 | } 284 | 285 | @Override 286 | public ItemStack removeStackFromSlot(int index) { 287 | markDirty(); 288 | return ItemStackHelper.getAndRemove(codeItemStacks, index); 289 | } 290 | 291 | @Override 292 | public void setInventorySlotContents(int index, ItemStack stack) { 293 | if (index != 0) { 294 | return; 295 | } 296 | 297 | codeItemStacks.set(index, stack); 298 | 299 | if (stack.isEmpty()) { 300 | unloadBook(); 301 | } else { 302 | loadBook(stack); 303 | } 304 | 305 | markDirty(); 306 | 307 | } 308 | 309 | private void unloadBook() { 310 | if (world.isRemote) { 311 | return; 312 | } 313 | processor.load(null); 314 | loaded = false; 315 | setName(null); 316 | updatePlayers(); 317 | } 318 | 319 | private static void addLines(List lines, String toAdd) { 320 | for (String s : toAdd.split("\\n\\r?")) { 321 | lines.add(s); 322 | } 323 | } 324 | 325 | private void loadBook(ItemStack stack) { 326 | if (world.isRemote) { 327 | return; 328 | } 329 | 330 | if (!isBook(stack.getItem()) || !stack.hasTagCompound()) { 331 | return; 332 | } 333 | 334 | NBTTagList pages = stack.getTagCompound().getTagList("pages", 8); 335 | 336 | if (pages == null) { 337 | return; 338 | } 339 | 340 | boolean signed = stack.getTagCompound().hasKey("author"); 341 | JsonParser parser = null; 342 | 343 | List code; 344 | if (ItemBookCode.isBookCode(stack)) { 345 | code = ItemBookCode.Data.loadFromStack(stack).getContinuousProgram(); 346 | } else { 347 | code = new ArrayList<>(pages.tagCount()); 348 | for (int i = 0; i < pages.tagCount(); ++i) { 349 | if (signed) { 350 | if (parser == null) { 351 | parser = new JsonParser(); 352 | } 353 | JsonObject o = parser.parse(pages.getStringTagAt(i)).getAsJsonObject(); 354 | addLines(code, o.get("text").getAsString()); 355 | } else { 356 | addLines(code, pages.getStringTagAt(i)); 357 | } 358 | } 359 | } 360 | updateNameFromCode(code); 361 | processor.load(code); 362 | loaded = false; 363 | updatePlayers(); 364 | } 365 | 366 | private void updateNameFromCode(List code) { 367 | String name = readNameFromHeader(code); 368 | if ("".equals(name)) { 369 | setName(null); 370 | } else { 371 | setName(name); 372 | } 373 | } 374 | 375 | public static String readNameFromHeader(List code) { 376 | try { 377 | List nameSearch = InstructionUtil.regex("^\\s*;\\s*(.*)", code.get(0), Pattern.CASE_INSENSITIVE); 378 | if (nameSearch.size() != 1) { 379 | return null; 380 | } 381 | String name = nameSearch.get(0); 382 | if (name != null && !name.isEmpty()) { 383 | return name; 384 | } 385 | } catch (Exception e) { 386 | Minecoprocessors.proxy.handleUnexpectedException(e); 387 | } 388 | return null; 389 | } 390 | 391 | @Override 392 | public int getInventoryStackLimit() { 393 | return 64; 394 | } 395 | 396 | @Override 397 | public boolean isUsableByPlayer(EntityPlayer player) { 398 | return world.getTileEntity(pos) == this && player.getDistanceSq(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D) <= 64.0D; 399 | } 400 | 401 | @Override 402 | public void openInventory(EntityPlayer player) { 403 | } 404 | 405 | @Override 406 | public void closeInventory(EntityPlayer player) { 407 | } 408 | 409 | public static boolean isBook(Item item) { 410 | return item == ItemBookCode.INSTANCE || item == Items.WRITABLE_BOOK || item == Items.WRITTEN_BOOK; 411 | } 412 | 413 | @Override 414 | public boolean isItemValidForSlot(int index, ItemStack stack) { 415 | return isBook(stack.getItem()); 416 | } 417 | 418 | @Override 419 | public int getField(int id) { 420 | return 0; 421 | } 422 | 423 | @Override 424 | public void setField(int id, int value) { 425 | 426 | } 427 | 428 | @Override 429 | public int getFieldCount() { 430 | return 1; 431 | } 432 | 433 | @Override 434 | public String getName() { 435 | return hasCustomName() ? this.customName : "container.minecoprocessor"; 436 | } 437 | 438 | public void setName(String name) { 439 | this.customName = name; 440 | } 441 | 442 | @Override 443 | public boolean hasCustomName() { 444 | return customName != null && !customName.isEmpty(); 445 | } 446 | 447 | @Override 448 | public ITextComponent getDisplayName() { 449 | return this.hasCustomName() ? new TextComponentString(this.getName()) : new TextComponentTranslation(this.getName()); 450 | } 451 | 452 | @Override 453 | public int getSizeInventory() { 454 | return codeItemStacks.size(); 455 | } 456 | 457 | @Override 458 | public boolean isEmpty() { 459 | for (ItemStack itemstack : codeItemStacks) { 460 | if (!itemstack.isEmpty()) { 461 | return false; 462 | } 463 | } 464 | 465 | return true; 466 | } 467 | 468 | @Override 469 | public void clear() { 470 | codeItemStacks.clear(); 471 | markDirty(); 472 | } 473 | 474 | public void enablePlayerGuiUpdates(EntityPlayerMP player, boolean enable) { 475 | if (enable) { 476 | playersToUpdate.add(player); 477 | updatePlayers(); 478 | } else { 479 | playersToUpdate.remove(player); 480 | } 481 | } 482 | 483 | public Processor getProcessor() { 484 | return processor; 485 | } 486 | 487 | } 488 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/gui/GuiMinecoprocessor.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.gui; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import net.minecraft.client.gui.GuiButton; 6 | import net.minecraft.client.gui.GuiScreenBook; 7 | import net.minecraft.client.renderer.GlStateManager; 8 | import net.minecraft.client.resources.I18n; 9 | import net.minecraft.inventory.IInventory; 10 | import net.minecraft.nbt.NBTTagCompound; 11 | import net.minecraft.util.ResourceLocation; 12 | import net.minecraft.util.math.BlockPos; 13 | import net.minecraft.util.math.MathHelper; 14 | import net.torocraft.minecoprocessors.Minecoprocessors; 15 | import net.torocraft.minecoprocessors.blocks.ContainerMinecoprocessor; 16 | import net.torocraft.minecoprocessors.blocks.TileEntityMinecoprocessor; 17 | import net.torocraft.minecoprocessors.network.MessageEnableGuiUpdates; 18 | import net.torocraft.minecoprocessors.network.MessageProcessorAction; 19 | import net.torocraft.minecoprocessors.network.MessageProcessorAction.Action; 20 | import net.torocraft.minecoprocessors.processor.FaultCode; 21 | import net.torocraft.minecoprocessors.processor.Processor; 22 | import net.torocraft.minecoprocessors.processor.Register; 23 | import net.torocraft.minecoprocessors.util.BookCreator; 24 | import net.torocraft.minecoprocessors.util.InstructionUtil; 25 | 26 | public class GuiMinecoprocessor extends net.minecraft.client.gui.inventory.GuiContainer { 27 | 28 | private static final ResourceLocation TEXTURES = new ResourceLocation(Minecoprocessors.MODID, "textures/gui/minecoprocessor.png"); 29 | 30 | private final IInventory playerInventory; 31 | private final TileEntityMinecoprocessor minecoprocessor; 32 | private final List hoveredFeature = new ArrayList<>(5); 33 | 34 | private GuiButton buttonReset; 35 | private GuiButton buttonPause; 36 | private GuiButton buttonStep; 37 | private GuiButton buttonHelp; 38 | private Processor processor; 39 | private byte[] registers = new byte[Register.values().length]; 40 | private byte faultCode = FaultCode.FAULT_STATE_NOMINAL; 41 | 42 | public BlockPos getPos() { 43 | return minecoprocessor.getPos(); 44 | } 45 | 46 | public static GuiMinecoprocessor INSTANCE; 47 | 48 | public GuiMinecoprocessor(IInventory playerInv, TileEntityMinecoprocessor te) { 49 | super(new ContainerMinecoprocessor(playerInv, te)); 50 | this.playerInventory = playerInv; 51 | this.minecoprocessor = te; 52 | INSTANCE = this; 53 | Minecoprocessors.NETWORK.sendToServer(new MessageEnableGuiUpdates(minecoprocessor.getPos(), true)); 54 | } 55 | 56 | public void updateData(NBTTagCompound processorData, String name) { 57 | if (processor == null) { 58 | processor = new Processor(); 59 | } 60 | processor.readFromNBT(processorData); 61 | minecoprocessor.setName(I18n.format(name)); 62 | registers = processor.getRegisters(); 63 | faultCode = processor.getFaultCode(); 64 | } 65 | 66 | @Override 67 | public void onGuiClosed() { 68 | super.onGuiClosed(); 69 | Minecoprocessors.NETWORK.sendToServer(new MessageEnableGuiUpdates(minecoprocessor.getPos(), false)); 70 | INSTANCE = null; 71 | } 72 | 73 | /** 74 | * Draw the foreground layer for the GuiContainer (everything in front of the items) 75 | */ 76 | @Override 77 | protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { 78 | hoveredFeature.clear(); 79 | 80 | GlStateManager.pushMatrix(); 81 | GlStateManager.scale(0.5d, 0.5d, 0.5d); 82 | int scale = 2; 83 | int y; 84 | 85 | mouseX = (mouseX - guiLeft) * scale; 86 | mouseY = (mouseY - guiTop) * scale; 87 | 88 | y = 50; 89 | drawRegister(Register.A, 130 * 2, y, mouseX, mouseY); 90 | drawRegister(Register.B, 139 * 2, y, mouseX, mouseY); 91 | drawRegister(Register.C, 148 * 2, y, mouseX, mouseY); 92 | drawRegister(Register.D, 157 * 2, y, mouseX, mouseY); 93 | 94 | y = 82; 95 | drawFlag("Z", processor == null ? null : processor.isZero(), 130 * 2, y, mouseX, mouseY); 96 | drawFlag("C", processor == null ? null : processor.isCarry() || processor.isOverflow(), 139 * 2, y, mouseX, mouseY); 97 | drawFlag("F", processor == null ? null : processor.isFault(), 148 * 2, y, 0xff0000, mouseX, mouseY); 98 | drawFlag("S", processor == null ? null : processor.isWait(), 157 * 2, y, 0x00ff00, mouseX, mouseY); 99 | 100 | y = 114; 101 | boolean mouseIsOver = drawLabeledShort("IP", processor == null ? null : processor.getIp(), 128 * 2, y, mouseX, mouseY); 102 | if (mouseIsOver) { 103 | hoveredFeature.add("Instruction Pointer"); 104 | } 105 | 106 | drawRegister(Register.ADC, 142 * 2, y, mouseX, mouseY); 107 | drawRegister(Register.PORTS, 158 * 2, y, mouseX, mouseY); 108 | 109 | drawPortRegister(Register.PF, 176, 47, mouseX, mouseY); 110 | drawPortRegister(Register.PR, 216, 86, mouseX, mouseY); 111 | drawPortRegister(Register.PL, 137, 86, mouseX, mouseY); 112 | drawPortRegister(Register.PB, 176, 125, mouseX, mouseY); 113 | 114 | drawCode(); 115 | 116 | GlStateManager.popMatrix(); 117 | 118 | drawGuiTitle(); 119 | drawInventoryTitle(); 120 | 121 | String pauseText = "gui.button.sleep"; 122 | if (processor == null || processor.isWait()) { 123 | pauseText = "gui.button.wake"; 124 | } 125 | buttonPause.displayString = I18n.format(pauseText); 126 | buttonStep.enabled = processor != null && processor.isWait(); 127 | } 128 | 129 | private void drawPortRegister(Register register, int x, int y, int mouseX, int mouseY) { 130 | byte value = registers[register.ordinal()]; 131 | boolean mouseIsOver = centered(toHex(value), x, y, mouseX, mouseY); 132 | if (mouseIsOver) { 133 | 134 | int portIndex = register.ordinal() - Register.PF.ordinal(); 135 | byte ports = registers[Register.PORTS.ordinal()]; 136 | byte adc = registers[Register.ADC.ordinal()]; 137 | 138 | switch (register) { 139 | case PF: 140 | hoveredFeature.add("Front Port - PF"); 141 | break; 142 | case PB: 143 | hoveredFeature.add("Back Port - PB"); 144 | break; 145 | case PL: 146 | hoveredFeature.add("Left Port - PL"); 147 | break; 148 | case PR: 149 | hoveredFeature.add("Right Port - PR"); 150 | break; 151 | } 152 | 153 | if (TileEntityMinecoprocessor.isInOutputMode(ports, portIndex)) { 154 | hoveredFeature.add("Output Port"); 155 | } else if (TileEntityMinecoprocessor.isInInputMode(ports, portIndex)) { 156 | hoveredFeature.add("Input Port"); 157 | } else if (TileEntityMinecoprocessor.isInResetMode(ports, portIndex)) { 158 | hoveredFeature.add("Reset Port"); 159 | } 160 | 161 | if (TileEntityMinecoprocessor.isADCMode(adc, portIndex)) { 162 | hoveredFeature.add("Analog Mode"); 163 | } else { 164 | hoveredFeature.add("Digital Mode"); 165 | } 166 | 167 | hoveredFeature.add(String.format("0x%s %sb %s", toHex(value), toBinary(value), Integer.toString(value, 10))); 168 | } 169 | } 170 | 171 | private void drawCode() { 172 | int x = 22; 173 | int y = 50; 174 | 175 | String label = "NEXT"; 176 | 177 | byte[] a = null; 178 | if (processor != null) { 179 | try { 180 | int ip = processor.getIp(); 181 | List program = processor.getProgram(); 182 | if (ip < program.size()) { 183 | a = program.get(ip); 184 | } 185 | } catch (Exception e) { 186 | Minecoprocessors.proxy.handleUnexpectedException(e); 187 | } 188 | } 189 | 190 | int color = 0xffffff; 191 | 192 | String value = ""; 193 | 194 | if (a != null) { 195 | value = InstructionUtil.compileLine(a, processor.getLabels(), (short) -1); 196 | } 197 | 198 | if (value.isEmpty() && processor != null && processor.getError() != null) { 199 | value = processor.getError(); 200 | color = 0xff0000; 201 | } 202 | 203 | fontRenderer.drawString(label, x - 4, y - 14, 0x404040); 204 | fontRenderer.drawString(value, x, y, color); 205 | } 206 | 207 | private void drawRegister(Register register, int x, int y, int mouseX, int mouseY) { 208 | String label = register.toString(); 209 | byte value = registers[register.ordinal()]; 210 | 211 | boolean mouseIsOver = drawLabeledValue(label, toHex(value), x, y, null, mouseX, mouseY); 212 | if (mouseIsOver) { 213 | hoveredFeature.add(label + " Register"); 214 | if (Register.PORTS.equals(register)) { 215 | hoveredFeature.add("I/O port direction"); 216 | } else if (Register.ADC.equals(register)) { 217 | hoveredFeature.add("ADC/DAC switch"); 218 | } else { 219 | hoveredFeature.add("General Purpose"); 220 | } 221 | hoveredFeature.add(String.format("0x%s %sb %s", toHex(value), toBinary(value), Integer.toString(value, 10))); 222 | } 223 | } 224 | 225 | public static String toBinary(Byte b) { 226 | if (b == null) { 227 | return null; 228 | } 229 | return maxLength(leftPad(Integer.toBinaryString(b), 8), 8); 230 | } 231 | 232 | private static String maxLength(String s, int l) { 233 | if (s.length() > l) { 234 | return s.substring(s.length() - l, s.length()); 235 | } 236 | return s; 237 | } 238 | 239 | public static String toHex(Byte b) { 240 | if (b == null) { 241 | return null; 242 | } 243 | String s = Integer.toHexString(b); 244 | if (s.length() > 2) { 245 | return s.substring(s.length() - 2, s.length()); 246 | } 247 | return leftPad(s, 2); 248 | } 249 | 250 | public static String leftPad(final String str, final int size) { 251 | if (str == null) { 252 | return null; 253 | } 254 | final int pads = size - str.length(); 255 | if (pads <= 0) { 256 | return str; 257 | } 258 | StringBuilder buf = new StringBuilder(); 259 | for (int i = 0; i < pads; i++) { 260 | buf.append("0"); 261 | } 262 | buf.append(str); 263 | return buf.toString(); 264 | } 265 | 266 | private static String toHex(Short b) { 267 | if (b == null) { 268 | return null; 269 | } 270 | String s = Integer.toHexString(b); 271 | if (s.length() > 4) { 272 | return s.substring(s.length() - 4, s.length()); 273 | } 274 | return leftPad(s, 4); 275 | } 276 | 277 | private void drawFlag(String label, Boolean flag, int x, int y, int mouseX, int mouseY) { 278 | drawFlag(label, flag, x, y, null, mouseX, mouseY); 279 | } 280 | 281 | private void drawFlag(String label, Boolean flag, int x, int y, Integer flashColor, int mouseX, int mouseY) { 282 | if (flag == null) { 283 | flag = false; 284 | } 285 | boolean mouseIsOver = drawLabeledValue(label, flag ? "1" : "0", x, y, flag ? flashColor : null, mouseX, mouseY); 286 | if (mouseIsOver) { 287 | switch (label) { 288 | case "Z": 289 | hoveredFeature.add("Zero Flag"); 290 | break; 291 | case "C": 292 | hoveredFeature.add("Carry Flag"); 293 | break; 294 | case "F": 295 | hoveredFeature.add("Fault Indicator"); 296 | hoveredFeature.add("STATUS 0x" + toHex(faultCode).toUpperCase()); 297 | break; 298 | case "S": 299 | hoveredFeature.add("Sleep Indicator"); 300 | break; 301 | } 302 | hoveredFeature.add(Boolean.toString(flag).toUpperCase()); 303 | } 304 | } 305 | 306 | @SuppressWarnings("unused") 307 | private void drawLabeledByte(String label, Byte b, int x, int y, int mouseX, int mouseY) { 308 | drawLabeledValue(label, toHex(b), x, y, null, mouseX, mouseY); 309 | } 310 | 311 | private boolean drawLabeledShort(String label, Short b, int x, int y, int mouseX, int mouseY) { 312 | return drawLabeledValue(label, toHex(b), x, y, null, mouseX, mouseY); 313 | } 314 | 315 | private boolean drawLabeledValue(String label, String value, int x, int y, Integer flashColor, int mouseX, int mouseY) { 316 | 317 | int wLabel = fontRenderer.getStringWidth(label) / 2; 318 | int wValue = 0; 319 | if (value != null) { 320 | wValue = fontRenderer.getStringWidth(value) / 2; 321 | } 322 | 323 | int color = 0xffffff; 324 | 325 | if (flashColor != null && (minecoprocessor.getWorld().getTotalWorldTime() / 10) % 2 == 0) { 326 | color = flashColor; 327 | } 328 | 329 | fontRenderer.drawString(label, x - wLabel, y - 14, 0x404040); 330 | if (value != null) { 331 | fontRenderer.drawString(value, x - wValue, y, color); 332 | } 333 | 334 | int wMax = Math.max(wLabel, wValue); 335 | boolean mouseIsOver = mouseX > (x - wMax) && mouseX < (x + wMax); 336 | mouseIsOver = mouseIsOver && mouseY > y - 14 && mouseY < y + 14; 337 | 338 | return mouseIsOver; 339 | } 340 | 341 | private boolean centered(String s, float x, float y, int mouseX, int mouseY) { 342 | int hWidth = fontRenderer.getStringWidth(s) / 2; 343 | int hHeight = fontRenderer.FONT_HEIGHT / 2; 344 | int xs = (int) x - hWidth; 345 | int ys = (int) y - hHeight; 346 | fontRenderer.drawString(s, xs, ys, 0xffffff); 347 | 348 | boolean mouseIsOver = mouseX > (x - hWidth) && mouseX < (x + hWidth); 349 | mouseIsOver = mouseIsOver && mouseY > y - hHeight - 2 && mouseY < y + hHeight + 2; 350 | return mouseIsOver; 351 | } 352 | 353 | private void drawInventoryTitle() { 354 | fontRenderer.drawString(playerInventory.getDisplayName().getUnformattedText(), 8, ySize - 96 + 2, 4210752); 355 | } 356 | 357 | private void drawGuiTitle() { 358 | String s = minecoprocessor.getDisplayName().getUnformattedText(); 359 | fontRenderer.drawString(s, xSize / 2 - fontRenderer.getStringWidth(s) / 2, 6, 4210752); 360 | } 361 | 362 | @Override 363 | public void drawScreen(int mouseX, int mouseY, float partialTicks) { 364 | super.drawScreen(mouseX, mouseY, partialTicks); 365 | renderHoveredToolTip(mouseX, mouseY); 366 | renderFeatureToolTip(mouseX, mouseY); 367 | } 368 | 369 | private void renderFeatureToolTip(int x, int y) { 370 | if (hoveredFeature.size() == 0) { 371 | return; 372 | } 373 | drawHoveringText(hoveredFeature, x, y, fontRenderer); 374 | } 375 | 376 | @Override 377 | public void initGui() { 378 | super.initGui(); 379 | drawButtons(); 380 | } 381 | 382 | private void drawButtons() { 383 | int buttonId = 0; 384 | int x = 8 + guiLeft; 385 | int y = 34 + guiTop; 386 | int buttonWidth = 49; 387 | int buttonHeight = 10; 388 | 389 | buttonReset = new ScaledGuiButton(buttonId++, x, y, buttonWidth, buttonHeight, I18n.format("gui.button.reset")); 390 | buttonPause = new ScaledGuiButton(buttonId++, x, y + 11, buttonWidth, buttonHeight, I18n.format("gui.button.sleep")); 391 | buttonStep = new ScaledGuiButton(buttonId++, x, y + 22, buttonWidth, buttonHeight, I18n.format("gui.button.step")); 392 | buttonHelp = new ScaledGuiButton(buttonId++, guiLeft + 133, guiTop + 66, 35, buttonHeight, I18n.format("gui.button.help")); 393 | 394 | buttonList.add(buttonReset); 395 | buttonList.add(buttonStep); 396 | buttonList.add(buttonPause); 397 | buttonList.add(buttonHelp); 398 | } 399 | 400 | @Override 401 | protected void actionPerformed(GuiButton button) { 402 | if (button == buttonReset) { 403 | Minecoprocessors.NETWORK.sendToServer(new MessageProcessorAction(minecoprocessor.getPos(), Action.RESET)); 404 | } 405 | if (button == buttonPause) { 406 | Minecoprocessors.NETWORK.sendToServer(new MessageProcessorAction(minecoprocessor.getPos(), Action.PAUSE)); 407 | } 408 | if (button == buttonStep) { 409 | Minecoprocessors.NETWORK.sendToServer(new MessageProcessorAction(minecoprocessor.getPos(), Action.STEP)); 410 | } 411 | if (button == buttonHelp) { 412 | // TODO override the book GUI so that it returns the processor GUI when closed 413 | this.mc.displayGuiScreen(new GuiScreenBook(mc.player, BookCreator.manual, false)); 414 | } 415 | } 416 | 417 | /** 418 | * Draws the background layer of this container (behind the items). 419 | */ 420 | @Override 421 | protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { 422 | GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); 423 | this.mc.getTextureManager().bindTexture(TEXTURES); 424 | int i = (this.width - this.xSize) / 2; 425 | int j = (this.height - this.ySize) / 2; 426 | this.drawTexturedModalRect(i, j, 0, 0, this.xSize, this.ySize); 427 | int k = this.minecoprocessor.getField(1); 428 | int l = MathHelper.clamp((18 * k + 20 - 1) / 20, 0, 18); 429 | 430 | if (l > 0) { 431 | this.drawTexturedModalRect(i + 60, j + 44, 176, 29, l, 4); 432 | } 433 | 434 | int i1 = this.minecoprocessor.getField(0); 435 | 436 | if (i1 > 0) { 437 | int j1 = (int) (28.0F * (1.0F - i1 / 400.0F)); 438 | 439 | if (j1 > 0) { 440 | this.drawTexturedModalRect(i + 97, j + 16, 176, 0, 9, j1); 441 | } 442 | 443 | j1 = 0; 444 | 445 | if (j1 > 0) { 446 | this.drawTexturedModalRect(i + 63, j + 14 + 29 - j1, 185, 29 - j1, 12, j1); 447 | } 448 | } 449 | } 450 | } 451 | -------------------------------------------------------------------------------- /src/main/java/net/torocraft/minecoprocessors/util/InstructionUtil.java: -------------------------------------------------------------------------------- 1 | package net.torocraft.minecoprocessors.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | import net.torocraft.minecoprocessors.Minecoprocessors; 8 | import net.torocraft.minecoprocessors.processor.InstructionCode; 9 | import net.torocraft.minecoprocessors.processor.Processor; 10 | import net.torocraft.minecoprocessors.processor.Register; 11 | 12 | public class InstructionUtil { 13 | 14 | public static final String ERROR_DOUBLE_REFERENCE = "only one memory reference allowed"; 15 | public static final String ERROR_NON_REFERENCE_OFFSET = "offsets can only be used with labels and references"; 16 | public static final String ERROR_LABEL_IN_FIRST_OPERAND = "labels can not be the first of two operands"; 17 | 18 | public static List compileFile(List instructions, List