diff options
Diffstat (limited to 'src/main/java/tectech/thing/metaTileEntity/multi/godforge')
12 files changed, 17761 insertions, 0 deletions
diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsRingsStructureString.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsRingsStructureString.java new file mode 100644 index 0000000000..fcff5c7026 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsRingsStructureString.java @@ -0,0 +1,5105 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static tectech.util.TTUtility.replaceLetters; + +public abstract class ForgeOfGodsRingsStructureString { + + public static final String[][] SECOND_RING = { { + + " BBBBBBB ", + " BBCCCCCCCBB ", + " BBCC CCBB ", + " BBEC CEBB ", + " BEEC CEEB ", + " EEC CEE ", + " EC CE ", + " EC CCCCC CE ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " EC CCCCC CE ", + " EC CE ", + " EEC CEE ", + " BEEC CEEB ", + " BBEC CEBB ", + " BBCC CCBB ", + " BBCCCCCCCBB ", + " BBBBBBB " }, + { " BBBBBBB ", + " BBCCCCCCCBB ", + " BBCC D CCBB ", + " BBEC D CEBB ", + " BBBEEC DD CEEBBB ", + " EEEEC D CEEEE ", + " EEEC DD CEEE ", + " EEEC CCCCC CEEE ", + " EEC CHHHHHC CEE ", + " EEC CHHHHHHHC CEE ", + " EEC CHHHHHHHC CEE ", + " EEC CHHHHHHHC CEE ", + " EEC CHHHHHHHC CEE ", + " EEC CHHHHHHHC CEE ", + " EEC CHHHHHC CEE ", + " EEEC CCCCC CEEE ", + " EEEC DD CEEE ", + " EEEEC D CEEEE ", + " BBBEEC DD CEEBBB ", + " BBEC D CEBB ", + " BBCC D CCBB ", + " BBCCCCCCCBB ", + " BBBBBBB " }, + { " BBBBBBB ", + " BBCCCCCCCBB ", + " BBCC CCBB ", + " BBEC CEBB ", + " BBBEEC CEEBBB ", + " BBBBEEEEC CEEEEBBBB ", + " EEEEEEEC CEEEEEEE ", + " EEEEEEEC CCCCC CEEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEEC CCCCC CEEEEEEE ", + " EEEEEEEC CEEEEEEE ", + " BBBBEEEEC CEEEEBBBB ", + " BBBEEC CEEBBB ", + " BBEC CEBB ", + " BBCC CCBB ", + " BBCCCCCCCBB ", + " BBBBBBB " }, + { " ", + " ", + " ", + " ", + " BBB BBB ", + " BBBBEEE EEEBBBB ", + " BBBEEEEEEE EEEEEEEBBB ", + " EEEEEEEEEE EEEEEEEEEE ", + " EEEEEEEEEE EEEEEEEEEE ", + " EEEEEEEKKK KKKEEEEEEE ", + " EEEEEEEKKK KKKEEEEEEE ", + " EEEEEEEKKK KKKEEEEEEE ", + " EEEEEEEKKK KKKEEEEEEE ", + " EEEEEEEKKK KKKEEEEEEE ", + " EEEEEEEEEE EEEEEEEEEE ", + " EEEEEEEEEE EEEEEEEEEE ", + " BBBEEEEEEE EEEEEEEBBB ", + " BBBBEEE EEEBBBB ", + " BBB BBB ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BBBBBEEEE EEEEBBBBB ", + " EEEEEEEEE EEEEEEEEE ", + " EEEEEEEEE EEEEEEEEE ", + " EEEEEKKKK KKKKEEEEE ", + " EEEEEKKKK KKKKEEEEE ", + " EEEEEKKKK KKKKEEEEE ", + " EEEEEKKKK KKKKEEEEE ", + " EEEEEKKKK KKKKEEEEE ", + " EEEEEEEEE EEEEEEEEE ", + " EEEEEEEEE EEEEEEEEE ", + " BBBBBEEEE EEEEBBBBB ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " BBBEEEEE EEEEEBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEKK KKEEEEEE ", + " EEEEEEKK KKEEEEEE ", + " EEEEEEKK KKEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBEEEEE EEEEEBBB ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " BBBBBEEE EEEBBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEKKK KKKEEEEE ", + " EEEEEKKK KKKEEEEE ", + " EEEEEKKK KKKEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBBEEE EEEBBBBB ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEKK KKEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BBEEEE EEEEBB ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEKK KKEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " BBEEEE EEEEBB ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BB BB ", + " BBBBEE EEBBBB ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEKK KKEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " BBBBEE EEBBBB ", + " BB BB ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEK KEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEKK KKEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BEEEE EEEEB ", + " EEEEE EEEEE ", + " EEEEK KEEEE ", + " EEEEE EEEEE ", + " BEEEE EEEEB ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " BBEEE EEEBB ", + " EEEEE EEEEE ", + " EEEEK KEEEE ", + " EEEEE EEEEE ", + " BBEEE EEEBB ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " BBBBE EBBBB ", + " EEEEE EEEEE ", + " EEEKK KKEEE ", + " EEEEE EEEEE ", + " BBBBE EBBBB ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEK KEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEK KEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEK KEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEKK KKEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEK KEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEK KEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEKK KKEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEK KEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEKK KKEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEKK KKEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEKK KKEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBB BBBBBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEKKK KKKEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBBBBB BBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBB BBBBBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEKK KKEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBBBBB BBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBB BBBBBBBBB ", + " EEEEEEEEE EEEEEEEEE ", + " EEEEEKKKK KKKKEEEEE ", + " EEEEEEEEE EEEEEEEEE ", + " BBBBBBBBB BBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBB BBBBBBBBBBBB ", + " EEEEEEEEEEEE EEEEEEEEEEEE ", + " EEEEEEEKKKKK KKKKKEEEEEEE ", + " EEEEEEEEEEEE EEEEEEEEEEEE ", + " BBBBBBBBBBBB BBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEKKKKKKKKKKKKKKKEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " } }; + + public static final String[][] THIRD_RING = { + { " BBBBBBB ", + " BBCCCCCCCBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBBEC CEBBB ", + " EEEC CEEE ", + " EEC CEE ", + " EEC CCCCC CEE ", + " EC CC CC CE ", + " EC C C CE ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C C C C ", + " EC C C CE ", + " EC CC CC CE ", + " EEC CCCCC CEE ", + " EEC CEE ", + " EEEC CEEE ", + " BBBEC CEBBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBCCCCCCCBB ", + " BBBBBBB " }, + { " BBBBBBB ", + " BBCCCCCCCBB ", + " BBCC CCBB ", + " BBCCD CCBB ", + " BBBEC DD CEBBB ", + " BBBEEEC D CEEEBBB ", + " EEEEEC DD CEEEEE ", + " EEEEEC DCCCCC CEEEEE ", + " EEEEC CCHHHHHCC CEEEE ", + " EEEEC CHHHHHHHHHC CEEEE ", + " EEEC CHHHHHHHHHC CEEE ", + " EEEC CHHHHHHHHHHHC CEEE ", + " EEEC CHHHHHHHHHHHC CEEE ", + " EEEC CHHHHHHHHHHHC CEEE ", + " EEEC CHHHHHHHHHHHC CEEE ", + " EEEC CHHHHHHHHHHHC CEEE ", + " EEEC CHHHHHHHHHC CEEE ", + " EEEEC CHHHHHHHHHC CEEEE ", + " EEEEC CCHHHHHCC CEEEE ", + " EEEEEC CCCCCD CEEEEE ", + " EEEEEC DD CEEEEE ", + " BBBEEEC D CEEEBBB ", + " BBBEC DD CEBBB ", + " BBCC DCCBB ", + " BBCC CCBB ", + " BBCCCCCCCBB ", + " BBBBBBB " }, + { " BBBBBBB ", + " BBCCCCCCCBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBBEC CEBBB ", + " BBBBEEEC CEEEBBBB ", + " BEEEEEEC CEEEEEEB ", + " EEEEEEEC CCCCC CEEEEEEE ", + " EEEEEEC CC CC CEEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEC C C CEEEEE ", + " EEEEEEC C C CEEEEEE ", + " EEEEEEC CC CC CEEEEEE ", + " EEEEEEEC CCCCC CEEEEEEE ", + " BEEEEEEC CEEEEEEB ", + " BBBBEEEC CEEEBBBB ", + " BBBEC CEBBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBCCCCCCCBB ", + " BBBBBBB " }, + { " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BBBBEEEE EEEEBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEII IIEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBEEEE EEEEBBBB ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " BB BB ", + " BBBBBEE EEBBBBB ", + " BEEEEEEE EEEEEEEB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEEEE EEEEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BEEEEEEE EEEEEEEB ", + " BBBBBEE EEBBBBB ", + " BB BB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BBEEEE EEEEBB ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " BBEEEE EEEEBB ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " BBBBBE EBBBBB ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " BBBBBE EBBBBB ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEII IIEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " BBEEE EEEBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEII IIEEE ", + " EEEII IIEEE ", + " EEEII IIEEE ", + " EEEII IIEEE ", + " EEEII IIEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBEEE EEEBB ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEI IEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " BEEE EEEB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEI IEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BEEE EEEB ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " BBBE EBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEI IEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBE EBBB ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI EEEE ", + " EEEI IEEE ", + " EEEI EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEI IEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEI IEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEI IEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEII IIEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEI IEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEII IIEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEII IIEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEII IIEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBB BBBBBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEIII IIIEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBBBBB BBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBB BBBBBBBBB ", + " EEEEEEEEE EEEEEEEEE ", + " EEEEEEIII IIIEEEEEE ", + " EEEEEEEEE EEEEEEEEE ", + " BBBBBBBBB BBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBB BBBBBBBBBBB ", + " EEEEEEEEEEE EEEEEEEEEEE ", + " EEEEEEIIIII IIIIIEEEEEE ", + " EEEEEEEEEEE EEEEEEEEEEE ", + " BBBBBBBBBBB BBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEIIIIIIIIIIIIIEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBB ", + " EEEEEEEEEEEEE ", + " EEEEEEEEEEEEE ", + " EEEEEEEEEEEEE ", + " BBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " } }; + public static final String[][] SECOND_RING_AIR = replaceLetters(SECOND_RING, "L"); + public static final String[][] THIRD_RING_AIR = replaceLetters(THIRD_RING, "L"); + +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsStructureString.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsStructureString.java new file mode 100644 index 0000000000..1780be0079 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsStructureString.java @@ -0,0 +1,5435 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static tectech.util.TTUtility.appendStringArrays; +import static tectech.util.TTUtility.replaceLetters; + +public abstract class ForgeOfGodsStructureString { + + public static final String[][] BEAM_SHAFT = { { + " ", + " ", + " ", + " ", + " ", + " ", + " BB BB ", + " BB BB ", + " B DDD DDD B ", + " DDFD DFDD ", + " DDADD DDADD ", + " DFDD DDFD ", + " DDD DDD ", + " ", + " ", + " ", + " DDD DDD ", + " DFDD DDFD ", + " DDADD DDADD ", + " DDFD DFDD ", + " B DDD DDD B ", + " BB BB ", + " BB BB ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " BB BB ", + " BEEBBBBB BBBBBEEB ", + " BEEEECCCCBCCCCEEEEB ", + " BEEECEE CFC EECEEEB ", + " BECEEE CFC EEECEB ", + " BCEE CFC EECB ", + " BCEE CCCFC EECB ", + " BC CFFCCFC CB ", + " BCCCCFCCFCFCCCCCB ", + " BFFFCCF~FCCFFFB ", + " BCCCCCFCFCCFCCCCB ", + " BC CFCCFFC CB ", + " BCEE CFCCC EECB ", + " BCEE CFC EECB ", + " BECEEE CFC EEECEB ", + " BEEECEE CFC EECEEEB ", + " BEEEECCCCBCCCCEEEEB ", + " BEEBBBBB BBBBBEEB ", + " BB BB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " BB BB ", + " BBEEBBB BBBEEBB ", + " BEEEEEEB BEEEEEEB ", + " BEEDDDDDBBBBBDDDDDEEB ", + " BEEDEE EEDEEB ", + " BEDE EDEB ", + " BED DEB ", + " BED DEB ", + " BB BB ", + " B B ", + " B B ", + " B B ", + " BB BB ", + " BED DEB ", + " BED DEB ", + " BEDE EDEB ", + " BEEDEE EEDEEB ", + " BEEDDDDDBBBBBDDDDDEEB ", + " BEEEEEEB BEEEEEEB ", + " BBEEBBB BBBEEBB ", + " BB BB ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BEEEEB BEEEEB ", + " BEEDDBBB BBBDDEEB ", + " BED DEB ", + " BED DEB ", + " BB BB ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " BB BB ", + " BED DEB ", + " BED DEB ", + " BEEDDBBB BBBDDEEB ", + " BEEEEB BEEEEB ", + " BBBB BBBB ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " BB BB ", + " BEEBB BBEEB ", + " BBB BEB ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " BEB BEB ", + " BEBBB BBEEB ", + " BB BB ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " BB BB ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " BB BB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " J ", + " BEEEEEB ", + " EEE EEE ", + " E E ", + " EE EE ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " JE EJ ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " EE EE ", + " E E ", + " EEE EEE ", + " BEEEEEB ", + " J " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " J ", + " BEEEEEB ", + " EEE EEE ", + " E E ", + " EE EE ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " JE EJ ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " EE EE ", + " E E ", + " EEE EEE ", + " BEEEEEB ", + " J " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " J ", + " BEEEEEB ", + " EEE EEE ", + " E E ", + " EE EE ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " JE EJ ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " EE EE ", + " E E ", + " EEE EEE ", + " BEEEEEB ", + " J " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " J ", + " BEEEEEB ", + " EEE EEE ", + " E E ", + " EE EE ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " JE EJ ", + " E E ", + " E E ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " EE EE ", + " E E ", + " EEE EEE ", + " BEEEEEB ", + " J " }, + { " ", + " BEEEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEEEB ", + " " }, + { " ", + " BEEEB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " E E ", + " E E ", + " E E ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BEEEB ", + " " }, + { " ", + " BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " B B ", + " B B ", + " B B ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " } }; + public static final String[][] FIRST_RING = { { + " ", + " ", + " ", + " ", + " ", + " BBBBB ", + " BBCCCCCBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " EEC CEE ", + " EC CE ", + " EC CE ", + " C CCC C ", + " C C C C ", + " C C C C ", + " C C C C ", + " C CCC C ", + " EC CE ", + " EC CE ", + " EEC CEE ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBCCCCCBB ", + " BBBBB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " BBBBB ", + " BBCCCCCBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBBEEC CEEBBB ", + " BBEEEEC DDCEEEEBB ", + " EEEEEEC DDD CEEEEEE ", + " EEEEEC CCCDD CEEEEE ", + " EEEEEC CHHHC CEEEEE ", + " EEEEEC CHHHC CEEEEE ", + " EEEEEC CHHHC CEEEEE ", + " EEEEEC DDCCC CEEEEE ", + " EEEEEEC DDD CEEEEEE ", + " BBEEEECDD CEEEEBB ", + " BBBEEC CEEBBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBCCCCCBB ", + " BBBBB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " BBBBB ", + " BBCCCCCBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBBEEC CEEBBB ", + " BBBBEEEEC CEEEEBBBB ", + " BBEEEEEEEEC CEEEEEEEEBB ", + " EEEEEEEEEC CCC CEEEEEEEEE ", + " EEEEEEEEEC C C CEEEEEEEEE ", + " EEEEEEEEEC C C CEEEEEEEEE ", + " EEEEEEEEEC C C CEEEEEEEEE ", + " EEEEEEEEEC CCC CEEEEEEEEE ", + " BBEEEEEEEEC CEEEEEEEEBB ", + " BBBBEEEEC CEEEEBBBB ", + " BBBEEC CEEBBB ", + " BBCC CCBB ", + " BBCC CCBB ", + " BBCCCCCBB ", + " BBBBB ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " BBBBEEEE EEEEBBBB ", + " BBBBBEEEEEEEE EEEEEEEEBBBBB ", + " EEEEEEEEEEEEE EEEEEEEEEEEEE ", + " EEEEEEEEEGGGG GGGGEEEEEEEEE ", + " EEEEEEEGGGGGG GGGGGGEEEEEEE ", + " EEEEEEEEEGGGG GGGGEEEEEEEEE ", + " EEEEEEEEEEEEE EEEEEEEEEEEEE ", + " BBBBBEEEEEEEE EEEEEEEEBBBBB ", + " BBBBEEEE EEEEBBBB ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BB BB ", + " BBBBBEE EEBBBBB ", + " BBBEEEEEEE EEEEEEEBBB ", + " EEEEEEEEEE EEEEEEEEEE ", + " EEEEEEGGGG GGGGEEEEEE ", + " EEEEEEEEEE EEEEEEEEEE ", + " BBBEEEEEEE EEEEEEEBBB ", + " BBBBBEE EEBBBBB ", + " BB BB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " BBBBBEEE EEEBBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEGGG GGGEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBBEEE EEEBBBBB ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBB BBBBBBB ", + " EEEEEEE EEEEEEE ", + " EEEEEGG GGEEEEE ", + " EEEEEEE EEEEEEE ", + " BBBBBBB BBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBB BBBBBBB ", + " EEEEEEE EEEEEEE ", + " EEEEGGG GGGEEEE ", + " EEEEEEE EEEEEEE ", + " BBBBBBB BBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEGG GGEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEGG GGEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEG GEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEGG GGEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEGG GGEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEG GEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEG GEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEGG GGEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "BBB BBB", + "EEE EEE", + "EEG GEE", + "EEE EEE", + "BBB BBB", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBB BBB ", + " EEE EEE ", + " EEG GEE ", + " EEE EEE ", + " BBB BBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBB BBBB ", + " EEEE EEEE ", + " EEEG GEEE ", + " EEEE EEEE ", + " BBBB BBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEGG GGEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEG GEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEG GEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEGG GGEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEGG GGEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBB BBBBB ", + " EEEEE EEEEE ", + " EEEEG GEEEE ", + " EEEEE EEEEE ", + " BBBBB BBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEGG GGEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBB BBBBBB ", + " EEEEEE EEEEEE ", + " EEEEGG GGEEEE ", + " EEEEEE EEEEEE ", + " BBBBBB BBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBB BBBBBBB ", + " EEEEEEE EEEEEEE ", + " EEEEGGG GGGEEEE ", + " EEEEEEE EEEEEEE ", + " BBBBBBB BBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBB BBBBBBB ", + " EEEEEEE EEEEEEE ", + " EEEEEGG GGEEEEE ", + " EEEEEEE EEEEEEE ", + " BBBBBBB BBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBB BBBBBBBB ", + " EEEEEEEE EEEEEEEE ", + " EEEEEGGG GGGEEEEE ", + " EEEEEEEE EEEEEEEE ", + " BBBBBBBB BBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBB BBBBBBBBBB ", + " EEEEEEEEEE EEEEEEEEEE ", + " EEEEEEGGGG GGGGEEEEEE ", + " EEEEEEEEEE EEEEEEEEEE ", + " BBBBBBBBBB BBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBB BBBBBBBBBBBBB ", + " EEEEEEEEEEEEE EEEEEEEEEEEEE ", + " EEEEEEEGGGGGG GGGGGGEEEEEEE ", + " EEEEEEEEEEEEE EEEEEEEEEEEEE ", + " BBBBBBBBBBBBB BBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEGGGGGGGGGGGGGGGEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " }, + { " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " BBBBBBBBBBBBBBB ", + " EEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEE ", + " EEEEEEEEEEEEEEE ", + " BBBBBBBBBBBBBBB ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " } }; + public static final String[][] MAIN_STRUCTURE = appendStringArrays(BEAM_SHAFT, FIRST_RING); + public static final String[][] FIRST_RING_AIR = replaceLetters(FIRST_RING, "L"); +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsUI.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsUI.java new file mode 100644 index 0000000000..a63ba81d7e --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/ForgeOfGodsUI.java @@ -0,0 +1,549 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static net.minecraft.util.StatCollector.translateToLocal; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; +import java.util.function.Supplier; + +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.Text; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Size; +import com.gtnewhorizons.modularui.api.screen.ModularUIContext; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicTextWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.Scrollable; +import com.gtnewhorizons.modularui.common.widget.SliderWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget; + +import gregtech.api.enums.VoidingMode; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.modularui.IControllerWithOptionalFeatures; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import tectech.TecTech; +import tectech.thing.gui.TecTechUITextures; +import tectech.thing.metaTileEntity.multi.godforge.color.ForgeOfGodsStarColor; + +/** + * Holds UI element builders and other conveniences shared between the primary Forge of the Gods and its modules. + */ +public class ForgeOfGodsUI { + + // ARGB representations of the 4 colors used in the color selector (red, green, blue, gold) + public static final int RED_ARGB = 0xFFFF5555; + public static final int GREEN_ARGB = 0xFF55FF55; + public static final int BLUE_ARGB = 0xFF0000AA; + public static final int GOLD_ARGB = 0xFFFFAA00; + + public static ButtonWidget createPowerSwitchButton(final IGregTechTileEntity tileEntity) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(tileEntity, "fx_click"); + if (tileEntity.isAllowedToWork()) { + tileEntity.disableWorking(); + } else { + tileEntity.enableWorking(); + } + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (tileEntity.isAllowedToWork()) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_POWER_SWITCH_DISABLED); + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(174, 148) + .setSize(16, 16); + button.addTooltip("Power Switch") + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + public static ButtonWidget createInputSeparationButton(final IGregTechTileEntity tileEntity, + final IControllerWithOptionalFeatures mte, IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(tileEntity, "fx_click"); + mte.setInputSeparation(!mte.isInputSeparationEnabled()); + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (mte.isInputSeparationEnabled()) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_INPUT_SEPARATION); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(mte::isInputSeparationEnabled, mte::setInputSeparation), + builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(mte.getInputSeparationButtonPos()) + .setSize(16, 16); + return (ButtonWidget) button; + } + + public static ButtonWidget createBatchModeButton(final IGregTechTileEntity tileEntity, + final IControllerWithOptionalFeatures mte, IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(tileEntity, "fx_click"); + mte.setBatchMode(!mte.isBatchModeEnabled()); + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (mte.isBatchModeEnabled()) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_BATCH_MODE); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(mte::isBatchModeEnabled, mte::setBatchMode), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(mte.getBatchModeButtonPos()) + .setSize(16, 16); + return (ButtonWidget) button; + } + + public static ButtonWidget createLockToSingleRecipeButton(final IGregTechTileEntity tileEntity, + final IControllerWithOptionalFeatures mte, IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(tileEntity, "fx_click"); + mte.setRecipeLocking(!mte.isRecipeLockingEnabled()); + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (mte.isRecipeLockingEnabled()) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_RECIPE_LOCKED); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(mte::isRecipeLockingEnabled, mte::setRecipeLocking), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(mte.getRecipeLockingButtonPos()) + .setSize(16, 16); + return (ButtonWidget) button; + } + + public static ButtonWidget createStructureUpdateButton(final IGregTechTileEntity tileEntity, + final IControllerWithOptionalFeatures mte, IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(tileEntity, "fx_click"); + if (mte.getStructureUpdateTime() <= -20) { + mte.setStructureUpdateTime(1); + } + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (mte.getStructureUpdateTime() > -20) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_STRUCTURE_CHECK); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_STRUCTURE_CHECK_OFF); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.IntegerSyncer(mte::getStructureUpdateTime, mte::setStructureUpdateTime), + builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.structure_update")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(mte.getStructureUpdateButtonPos()) + .setSize(16, 16); + return (ButtonWidget) button; + } + + public static ButtonWidget createVoidExcessButton(final IGregTechTileEntity tileEntity, + final IControllerWithOptionalFeatures mte, IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(tileEntity, "fx_click"); + Set<VoidingMode> allowed = mte.getAllowedVoidingModes(); + switch (clickData.mouseButton) { + case 0 -> mte.setVoidingMode( + mte.getVoidingMode() + .nextInCollection(allowed)); + case 1 -> mte.setVoidingMode( + mte.getVoidingMode() + .previousInCollection(allowed)); + } + widget.notifyTooltipChange(); + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + switch (mte.getVoidingMode()) { + case VOID_NONE -> ret.add(TecTechUITextures.OVERLAY_BUTTON_VOIDING_OFF); + case VOID_ITEM -> ret.add(TecTechUITextures.OVERLAY_BUTTON_VOIDING_ITEMS); + case VOID_FLUID -> ret.add(TecTechUITextures.OVERLAY_BUTTON_VOIDING_FLUIDS); + case VOID_ALL -> ret.add(TecTechUITextures.OVERLAY_BUTTON_VOIDING_BOTH); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.IntegerSyncer( + () -> mte.getVoidingMode() + .ordinal(), + val -> mte.setVoidingMode(VoidingMode.fromOrdinal(val))), + builder) + .dynamicTooltip( + () -> Arrays.asList( + StatCollector.translateToLocal("GT5U.gui.button.voiding_mode"), + StatCollector.translateToLocal( + mte.getVoidingMode() + .getTransKey()))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(mte.getVoidingModeButtonPos()) + .setSize(16, 16); + return (ButtonWidget) button; + } + + public static ModularWindow createGeneralInfoWindow(Supplier<Boolean> inversionGetter, + Consumer<Boolean> inversionSetter) { + final Scrollable scrollable = new Scrollable().setVerticalScroll(); + final int WIDTH = 300; + final int HEIGHT = 300; + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + + builder.setDraggable(true); + scrollable.widget( + new TextWidget(EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.introduction")) + .setDefaultColor(EnumChatFormatting.DARK_PURPLE) + .setTextAlignment(Alignment.TopCenter) + .setPos(7, 13) + .setSize(280, 15)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.introductioninfotext")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 30) + .setSize(280, 50)) + .widget( + new TextWidget( + EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.tableofcontents")) + .setDefaultColor(EnumChatFormatting.AQUA) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 80) + .setSize(150, 15)) + .widget( + new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(150)) + .setBackground( + new Text(EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.fuel")) + .alignment(Alignment.CenterLeft) + .color(0x55ffff)) + .setPos(7, 95) + .setSize(150, 15)) + .widget( + new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(434)) + .setBackground( + new Text( + EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.modules")) + .alignment(Alignment.CenterLeft) + .color(0x55ffff)) + .setPos(7, 110) + .setSize(150, 15)) + .widget( + new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(1088)) + .setBackground( + new Text( + EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.upgrades")) + .alignment(Alignment.CenterLeft) + .color(0x55ffff)) + .setPos(7, 125) + .setSize(150, 15)) + .widget( + new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(1412)) + .setBackground( + new Text( + EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.milestones")) + .alignment(Alignment.CenterLeft) + .color(0x55ffff)) + .setPos(7, 140) + .setSize(150, 15)) + .widget( + TextWidget.dynamicText(() -> inversionInfoText(inversionGetter.get())) + .setDefaultColor(EnumChatFormatting.WHITE) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 155) + .setSize(150, 15)) + .widget(new ButtonWidget().setOnClick((clickData, widget) -> { + if (inversionGetter.get()) { + scrollable.setVerticalScrollOffset(1766); + } + }) + .setPlayClickSound(inversionGetter.get()) + .setPos(7, 155) + .setSize(150, 15) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(inversionGetter, inversionSetter), scrollable)) + .widget( + new TextWidget( + EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.fuel")) + .setDefaultColor(EnumChatFormatting.DARK_PURPLE) + .setTextAlignment(Alignment.TopCenter) + .setPos(127, 160) + .setSize(40, 15)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfotext")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 177) + .setSize(280, 250)) + .widget( + new TextWidget( + EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.modules")) + .setDefaultColor(EnumChatFormatting.DARK_PURPLE) + .setTextAlignment(Alignment.TopCenter) + .setPos(7, 440) + .setSize(280, 15)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.moduleinfotext")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 461) + .setSize(280, 620)) + .widget( + new TextWidget( + EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.upgrades")) + .setDefaultColor(EnumChatFormatting.DARK_PURPLE) + .setTextAlignment(Alignment.TopCenter) + .setPos(7, 1098) + .setSize(280, 15)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.upgradeinfotext")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 1115) + .setSize(280, 290)) + .widget( + new TextWidget( + EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.milestones")) + .setDefaultColor(EnumChatFormatting.DARK_PURPLE) + .setTextAlignment(Alignment.TopCenter) + .setPos(7, 1422) + .setSize(280, 15)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.milestoneinfotext")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 1439) + .setSize(280, 320)) + .widget( + TextWidget.dynamicText(() -> inversionHeaderText(inversionGetter.get())) + .setDefaultColor(EnumChatFormatting.WHITE) + .setTextAlignment(Alignment.TopCenter) + .setPos(7, 1776) + .setSize(280, 15)) + .widget( + TextWidget.dynamicText(() -> inversionInfoText(inversionGetter.get())) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 1793) + .setSize(280, 160)) + .widget( + new TextWidget("").setPos(7, 1965) + .setSize(10, 10)); + + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_GLOW_WHITE) + .setPos(0, 0) + .setSize(300, 300)) + .widget( + scrollable.setSize(292, 292) + .setPos(4, 4)) + .widget( + ButtonWidget.closeWindowButton(true) + .setPos(284, 4)); + + return builder.build(); + } + + private static Text inversionHeaderText(boolean inversion) { + return inversion + ? new Text( + EnumChatFormatting.BOLD + "§k2" + + EnumChatFormatting.RESET + + EnumChatFormatting.WHITE + + EnumChatFormatting.BOLD + + translateToLocal("gt.blockmachines.multimachine.FOG.inversion") + + EnumChatFormatting.BOLD + + "§k2") + : new Text(""); + } + + private static Text inversionInfoText(boolean inversion) { + return inversion ? new Text(translateToLocal("gt.blockmachines.multimachine.FOG.inversioninfotext")) + : new Text(""); + } + + public static void reopenWindow(Widget widget, int windowId) { + if (!widget.isClient()) { + ModularUIContext ctx = widget.getContext(); + if (ctx.isWindowOpen(windowId)) { + ctx.closeWindow(windowId); + } + ctx.openSyncedWindow(windowId); + } + } + + public enum StarColorRGBM { + + RED(EnumChatFormatting.RED, RED_ARGB, 0, 255, ForgeOfGodsStarColor.DEFAULT_RED), + GREEN(EnumChatFormatting.GREEN, GREEN_ARGB, 0, 255, ForgeOfGodsStarColor.DEFAULT_GREEN), + BLUE(EnumChatFormatting.DARK_BLUE, BLUE_ARGB, 0, 255, ForgeOfGodsStarColor.DEFAULT_BLUE), + GAMMA(EnumChatFormatting.GOLD, GOLD_ARGB, 0, 100, ForgeOfGodsStarColor.DEFAULT_GAMMA); + + private final String title; + private final EnumChatFormatting mcColor; + private final int muiColor; + private final float lowerBound, upperBound; + private final float defaultValue; + + StarColorRGBM(EnumChatFormatting mcColor, int muiColor, float lower, float upper, float defaultVal) { + this.title = "fog.cosmetics.color." + name().toLowerCase(); + this.mcColor = mcColor; + this.muiColor = muiColor; + this.lowerBound = lower; + this.upperBound = upper; + this.defaultValue = defaultVal; + } + + public String tooltip(float value) { + if (this == GAMMA) { + return String.format("%s%s: %.1f", mcColor, translateToLocal(title), value); + } + return String.format("%s%s: %d", mcColor, translateToLocal(title), (int) value); + } + } + + public static Widget createStarColorRGBMGroup(StarColorRGBM color, DoubleConsumer setter, DoubleSupplier getter) { + MultiChildWidget widget = new MultiChildWidget(); + widget.setSize(184, 16); + + // Title + widget.addChild( + new TextWidget(translateToLocal(color.title)).setDefaultColor(color.mcColor) + .setTextAlignment(Alignment.CenterLeft) + .setPos(0, 0) + .setSize(32, 16)); + + // Color slider + widget.addChild(new SliderWidget().setSetter(val -> { + int aux = (int) (val * 10); + setter.accept(aux / 10d); + }) + .setGetter(() -> (float) getter.getAsDouble()) + .setBounds(color.lowerBound, color.upperBound) + .setHandleSize(new Size(4, 0)) + .dynamicTooltip(() -> { + List<String> ret = new ArrayList<>(); + ret.add(color.tooltip((float) getter.getAsDouble())); + return ret; + }) + .setUpdateTooltipEveryTick(true) + .setSize(118, 8) + .setPos(32, 4)); + + // Color manual text box + Widget numberEntry = new NumericWidget().setSetter(setter) + .setGetter(getter) + .setBounds(color.lowerBound, color.upperBound) + .setDefaultValue(color.defaultValue) + .setTextAlignment(Alignment.Center) + .setTextColor(color.muiColor) + .setSize(32, 16) + .setPos(152, 0) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD); + + if (color == StarColorRGBM.GAMMA) { + numberEntry.addTooltip(translateToLocal("fog.cosmetics.onlydecimals")); + ((NumericWidget) numberEntry).setIntegerOnly(false); + } else { + numberEntry.addTooltip(translateToLocal("fog.cosmetics.onlyintegers")); + } + + return widget.addChild(numberEntry); + } + + public static Widget createStarColorButton(String text, String tooltip, + BiConsumer<Widget.ClickData, Widget> onClick) { + MultiChildWidget widget = new MultiChildWidget(); + widget.setSize(35, 15); + + widget.addChild( + new ButtonWidget().setOnClick(onClick) + .setSize(35, 15) + .setBackground(GTUITextures.BUTTON_STANDARD) + .addTooltip(translateToLocal(tooltip)) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(0, 0)); + + widget.addChild( + TextWidget.localised(text) + .setTextAlignment(Alignment.Center) + .setPos(0, 0) + .setSize(35, 15)); + + return widget; + } + + public static Widget createStarColorButton(Supplier<String> text, Supplier<String> tooltip, + BiConsumer<Widget.ClickData, Widget> onClick) { + MultiChildWidget widget = new MultiChildWidget(); + widget.setSize(35, 15); + + widget.addChild( + new ButtonWidget().setOnClick(onClick) + .setSize(35, 15) + .setBackground(GTUITextures.BUTTON_STANDARD) + .dynamicTooltip(() -> { + List<String> ret = new ArrayList<>(); + ret.add(translateToLocal(tooltip.get())); + return ret; + }) + .setUpdateTooltipEveryTick(true) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(0, 0)); + + widget.addChild( + new DynamicTextWidget(() -> new Text(translateToLocal(text.get()))).setTextAlignment(Alignment.Center) + .setPos(0, 0) + .setSize(35, 15)); + + return widget; + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEBaseModule.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEBaseModule.java new file mode 100644 index 0000000000..8b432d2ce8 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEBaseModule.java @@ -0,0 +1,586 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.processInitialSettings; +import static net.minecraft.util.StatCollector.translateToLocal; +import static tectech.thing.casing.TTCasingsContainer.GodforgeCasings; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.common.util.ForgeDirection; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.Text; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.math.Size; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.Scrollable; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.GTValues; +import gregtech.api.enums.Textures; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.RecipeMaps; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTStructureUtility; +import tectech.TecTech; +import tectech.thing.gui.TecTechUITextures; +import tectech.thing.metaTileEntity.multi.base.TTMultiblockBase; + +public class MTEBaseModule extends TTMultiblockBase { + + protected final int tier = getTier(); + protected boolean isConnected = false; + protected double overclockTimeFactor = 2d; + protected boolean isUpgrade83Unlocked = false; + protected boolean isMultiStepPlasmaCapable = false; + protected boolean isMagmatterCapable = false; + private boolean isVoltageConfigUnlocked = false; + private boolean isInversionUnlocked = false; + protected UUID userUUID; + protected int machineHeat = 0; + protected int overclockHeat = 0; + protected int maximumParallel = 0; + protected int plasmaTier = 0; + protected double processingSpeedBonus = 0; + protected double energyDiscount = 0; + protected long processingVoltage = 2_000_000_000; + protected BigInteger powerTally = BigInteger.ZERO; + protected long recipeTally = 0; + private static Textures.BlockIcons.CustomIcon ScreenON; + private static Textures.BlockIcons.CustomIcon ScreenOFF; + + private static final String STRUCTURE_PIECE_MAIN = "main"; + private static final int VOLTAGE_WINDOW_ID = 9; + private static final int GENERAL_INFO_WINDOW_ID = 10; + private static final int TEXTURE_INDEX = 960; + + public MTEBaseModule(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTEBaseModule(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTEBaseModule(mName); + } + + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + if (aBaseMetaTileEntity.isServerSide() && isConnected) { + super.onPostTick(aBaseMetaTileEntity, aTick); + if (mEfficiency < 0) mEfficiency = 0; + } + } + + @Override + public RecipeMap<?> getRecipeMap() { + return RecipeMaps.blastFurnaceRecipes; + } + + @Override + public boolean drainEnergyInput(long EUtEffective, long Amperes) { + long EU_drain = EUtEffective * Amperes; + if (EU_drain == 0L) { + return true; + } else { + if (EU_drain > 0L) { + EU_drain = -EU_drain; + } + return addEUToGlobalEnergyMap(userUUID, EU_drain); + } + } + + public void connect() { + isConnected = true; + } + + public void disconnect() { + isConnected = false; + } + + public void setHeat(int heat) { + machineHeat = heat; + } + + public int getHeat() { + return machineHeat; + } + + public void setHeatForOC(int heat) { + overclockHeat = heat; + } + + public int getHeatForOC() { + return overclockHeat; + } + + public void setMaxParallel(int parallel) { + maximumParallel = parallel; + } + + public int getMaxParallel() { + return maximumParallel; + } + + public void setSpeedBonus(double bonus) { + processingSpeedBonus = bonus; + } + + public double getSpeedBonus() { + return processingSpeedBonus; + } + + public void setEnergyDiscount(double discount) { + energyDiscount = discount; + } + + public double getEnergyDiscount() { + return energyDiscount; + } + + public void setUpgrade83(boolean unlocked) { + isUpgrade83Unlocked = unlocked; + } + + public void setOverclockTimeFactor(double factor) { + overclockTimeFactor = factor; + } + + public double getOverclockTimeFactor() { + return overclockTimeFactor; + } + + public void setMultiStepPlasma(boolean isCapable) { + isMultiStepPlasmaCapable = isCapable; + } + + public void setProcessingVoltage(long Voltage) { + processingVoltage = Voltage; + } + + public long getProcessingVoltage() { + return processingVoltage; + } + + public void setMagmatterCapable(boolean isCapable) { + isMagmatterCapable = isCapable; + } + + public double getHeatEnergyDiscount() { + return isUpgrade83Unlocked ? 0.92 : 0.95; + } + + public void setPlasmaTier(int tier) { + plasmaTier = tier; + } + + public int getPlasmaTier() { + return plasmaTier; + } + + public void setVoltageConfig(boolean unlocked) { + isVoltageConfigUnlocked = unlocked; + } + + public void setInversionConfig(boolean inversion) { + isInversionUnlocked = inversion; + } + + public void setPowerTally(BigInteger amount) { + powerTally = amount; + } + + public BigInteger getPowerTally() { + return powerTally; + } + + public void addToPowerTally(BigInteger amount) { + powerTally = powerTally.add(amount); + } + + public void setRecipeTally(long amount) { + recipeTally = amount; + } + + public long getRecipeTally() { + return recipeTally; + } + + public void addToRecipeTally(long amount) { + recipeTally += amount; + } + + public int getTier() { + return tier; + } + + @Override + public long getMaxInputVoltage() { + return GTValues.V[tier]; + } + + @Override + public IStructureDefinition<? extends TTMultiblockBase> getStructure_EM() { + if (this instanceof MTESmeltingModule) { + return getStructureDefinition(GregTechAPI.sBlockCasings5, 12); + } + return getStructureDefinition(GodforgeCasings, 8); + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + structureBuild_EM(STRUCTURE_PIECE_MAIN, 3, 3, 0, stackSize, hintsOnly); + } + + @Override + public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + + if (!structureCheck_EM(STRUCTURE_PIECE_MAIN, 3, 3, 0)) { + return false; + } + + if (this instanceof MTEExoticModule) { + if (mOutputHatches.isEmpty()) { + return false; + } + return !mOutputBusses.isEmpty(); + } + + return true; + } + + @Override + public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + super.onPreTick(aBaseMetaTileEntity, aTick); + + if (aBaseMetaTileEntity.isServerSide() && (aTick == 1)) { + userUUID = processInitialSettings(aBaseMetaTileEntity); + } + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + final DynamicPositionedColumn screenElements = new DynamicPositionedColumn(); + final SlotWidget inventorySlot = new SlotWidget(inventoryHandler, 1); + drawTexts(screenElements, inventorySlot); + + buildContext.addSyncedWindow(VOLTAGE_WINDOW_ID, this::createVoltageWindow); + buildContext.addSyncedWindow(GENERAL_INFO_WINDOW_ID, this::createGeneralInfoWindow); + + builder.widget( + new DrawableWidget().setSize(18, 18) + .setPos(172, 67) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.clickhere")) + .setTooltipShowUpDelay(TOOLTIP_DELAY)); + + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_SCREEN_BLUE) + .setPos(4, 4) + .setSize(190, 85)) + .widget( + inventorySlot.setPos(173, 167) + .setBackground(getGUITextureSet().getItemSlot(), TecTechUITextures.OVERLAY_SLOT_MESH)) + .widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_HEAT_SINK_SMALL) + .setPos(173, 185) + .setSize(18, 6)) + .widget( + new Scrollable().setVerticalScroll() + .widget(screenElements.setPos(10, 0)) + .setPos(0, 7) + .setSize(190, 79)) + .widget( + TextWidget.dynamicText(this::connectionStatus) + .setDefaultColor(EnumChatFormatting.BLACK) + .setPos(75, 94) + .setSize(100, 10)) + .widget( + new ButtonWidget().setOnClick( + (data, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(GENERAL_INFO_WINDOW_ID); + }) + .setSize(18, 18) + .setPos(172, 67) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget(createPowerSwitchButton(builder)) + .widget(createVoltageButton(builder)) + .widget(createStructureUpdateButton(builder)); + + if (supportsVoidProtection()) builder.widget(createVoidExcessButton(builder)); + if (supportsInputSeparation()) builder.widget(createInputSeparationButton(builder)); + if (supportsBatchMode()) builder.widget(createBatchModeButton(builder)); + if (supportsSingleRecipeLocking()) builder.widget(createLockToSingleRecipeButton(builder)); + } + + protected Widget createVoltageButton(IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isVoltageConfigUnlocked) { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + if (!widget.isClient()) { + widget.getContext() + .openSyncedWindow(VOLTAGE_WINDOW_ID); + } + } + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (isVoltageConfigUnlocked) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_POWER_PASS_ON); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_POWER_PASS_DISABLED); + } + return ret.toArray(new IDrawable[0]); + }) + .addTooltip(translateToLocal("fog.button.voltageconfig.tooltip.01")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(174, 112) + .setSize(16, 16) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> isVoltageConfigUnlocked, val -> isVoltageConfigUnlocked = val), + builder); + if (!isVoltageConfigUnlocked) { + button.addTooltip(EnumChatFormatting.GRAY + translateToLocal("fog.button.voltageconfig.tooltip.02")); + } + return button; + } + + protected ModularWindow createVoltageWindow(final EntityPlayer player) { + final int WIDTH = 158; + final int HEIGHT = 52; + final int PARENT_WIDTH = getGUIWidth(); + final int PARENT_HEIGHT = getGUIHeight(); + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.setPos( + (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) + .add( + Alignment.BottomRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT)) + .add(WIDTH - 3, 0) + .subtract(0, 10))); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.voltageinfo") + .setPos(3, 4) + .setSize(150, 20)) + .widget( + new NumericWidget().setSetter(val -> processingVoltage = (long) val) + .setGetter(() -> processingVoltage) + .setBounds(2_000_000_000, Long.MAX_VALUE) + .setDefaultValue(2_000_000_000) + .setScrollValues(1, 4, 64) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setSize(150, 18) + .setPos(4, 25) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD) + .attachSyncer( + new FakeSyncWidget.LongSyncer(this::getProcessingVoltage, this::setProcessingVoltage), + builder)); + return builder.build(); + } + + protected ModularWindow createGeneralInfoWindow(final EntityPlayer player) { + return ForgeOfGodsUI.createGeneralInfoWindow(() -> isInversionUnlocked, val -> isInversionUnlocked = val); + } + + @Override + public ButtonWidget createPowerSwitchButton(IWidgetBuilder<?> builder) { + return ForgeOfGodsUI.createPowerSwitchButton(getBaseMetaTileEntity()); + } + + @Override + public ButtonWidget createInputSeparationButton(IWidgetBuilder<?> builder) { + return ForgeOfGodsUI.createInputSeparationButton(getBaseMetaTileEntity(), this, builder); + } + + @Override + public ButtonWidget createBatchModeButton(IWidgetBuilder<?> builder) { + return ForgeOfGodsUI.createBatchModeButton(getBaseMetaTileEntity(), this, builder); + } + + @Override + public ButtonWidget createLockToSingleRecipeButton(IWidgetBuilder<?> builder) { + return ForgeOfGodsUI.createLockToSingleRecipeButton(getBaseMetaTileEntity(), this, builder); + } + + @Override + public ButtonWidget createStructureUpdateButton(IWidgetBuilder<?> builder) { + return ForgeOfGodsUI.createStructureUpdateButton(getBaseMetaTileEntity(), this, builder); + } + + @Override + public ButtonWidget createVoidExcessButton(IWidgetBuilder<?> builder) { + return ForgeOfGodsUI.createVoidExcessButton(getBaseMetaTileEntity(), this, builder); + } + + @Override + public void addGregTechLogo(ModularWindow.Builder builder) { + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_LOGO) + .setSize(18, 18) + .setPos(172, 67)); + } + + @Override + public boolean supportsInputSeparation() { + return true; + } + + @Override + public boolean supportsBatchMode() { + return true; + } + + @Override + public boolean supportsVoidProtection() { + return true; + } + + @Override + public boolean supportsSingleRecipeLocking() { + return true; + } + + @Override + public boolean isSimpleMachine() { + return true; + } + + @Override + public boolean willExplodeInRain() { + return false; + } + + private static IStructureDefinition<MTEBaseModule> getStructureDefinition(Block coilBlock, int meta) { + return StructureDefinition.<MTEBaseModule>builder() + .addShape( + STRUCTURE_PIECE_MAIN, + new String[][] { { " ", " BBB ", " BBBBB ", " BB~BB ", " BBBBB ", " BBB ", " " }, + { " CCC ", " CFFFC ", "CFFFFFC", "CFFFFFC", "CFFFFFC", " CFFFC ", " CCC " }, + { " ", " ", " E ", " EAE ", " E ", " ", " " }, + { " ", " ", " E ", " EAE ", " E ", " ", " " }, + { " ", " ", " E ", " EAE ", " E ", " ", " " }, + { " ", " ", " E ", " EAE ", " E ", " ", " " }, + { " ", " ", " E ", " EAE ", " E ", " ", " " }, + { " ", " ", " ", " D ", " ", " ", " " }, + { " ", " ", " ", " D ", " ", " ", " " }, + { " ", " ", " ", " D ", " ", " ", " " }, + { " ", " ", " ", " D ", " ", " ", " " }, + { " ", " ", " ", " D ", " ", " ", " " }, + { " ", " ", " ", " G ", " ", " ", " " } }) + .addElement('A', ofBlock(coilBlock, meta)) + .addElement( + 'B', + GTStructureUtility + .ofHatchAdderOptional(MTEBaseModule::addClassicToMachineList, TEXTURE_INDEX, 1, GodforgeCasings, 0)) + .addElement('C', ofBlock(GodforgeCasings, 0)) + .addElement('D', ofBlock(GodforgeCasings, 1)) + .addElement('E', ofBlock(GodforgeCasings, 2)) + .addElement('F', ofBlock(GodforgeCasings, 3)) + .addElement('G', ofBlock(GodforgeCasings, 4)) + .build(); + } + + private Text connectionStatus() { + String status = EnumChatFormatting.RED + + translateToLocal("gt.blockmachines.multimachine.FOG.modulestatus.false"); + if (isConnected) { + status = EnumChatFormatting.GREEN + translateToLocal("gt.blockmachines.multimachine.FOG.modulestatus.true"); + } + return new Text(translateToLocal("gt.blockmachines.multimachine.FOG.modulestatus") + " " + status); + } + + @Override + public void saveNBTData(NBTTagCompound NBT) { + NBT.setBoolean("isConnected", isConnected); + NBT.setBoolean("isVoltageConfigUnlocked", isVoltageConfigUnlocked); + NBT.setLong("processingVoltage", processingVoltage); + NBT.setLong("recipeTally", recipeTally); + NBT.setByteArray("powerTally", powerTally.toByteArray()); + super.saveNBTData(NBT); + } + + @Override + public void loadNBTData(final NBTTagCompound NBT) { + isConnected = NBT.getBoolean("isConnected"); + isVoltageConfigUnlocked = NBT.getBoolean("isVoltageConfigUnlocked"); + processingVoltage = NBT.getLong("processingVoltage"); + recipeTally = NBT.getLong("recipeTally"); + powerTally = new BigInteger(NBT.getByteArray("powerTally")); + super.loadNBTData(NBT); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IIconRegister aBlockIconRegister) { + ScreenON = new Textures.BlockIcons.CustomIcon("iconsets/GODFORGE_MODULE_ACTIVE"); + ScreenOFF = new Textures.BlockIcons.CustomIcon("iconsets/SCREEN_OFF"); + super.registerIcons(aBlockIconRegister); + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean aActive, boolean aRedstone) { + if (side == facing) { + if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX), + TextureFactory.builder() + .addIcon(ScreenON) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(ScreenON) + .extFacing() + .glow() + .build() }; + return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX), TextureFactory.builder() + .addIcon(ScreenOFF) + .extFacing() + .build() }; + } + return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX) }; + } + + @Override + public boolean getDefaultHasMaintenanceChecks() { + return false; + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEExoticModule.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEExoticModule.java new file mode 100644 index 0000000000..d30f9402d9 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEExoticModule.java @@ -0,0 +1,701 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.api.util.GTRecipeBuilder.INGOTS; +import static gregtech.api.util.GTRecipeBuilder.SECONDS; +import static gregtech.api.util.GTUtility.formatNumbers; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static net.minecraft.util.EnumChatFormatting.GREEN; +import static net.minecraft.util.EnumChatFormatting.RED; +import static net.minecraft.util.EnumChatFormatting.RESET; +import static net.minecraft.util.EnumChatFormatting.YELLOW; +import static net.minecraft.util.StatCollector.translateToLocal; +import static tectech.loader.recipe.Godforge.exoticModuleMagmatterItemMap; +import static tectech.loader.recipe.Godforge.exoticModulePlasmaFluidMap; +import static tectech.loader.recipe.Godforge.exoticModulePlasmaItemMap; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.oredict.OreDictionary; + +import org.apache.commons.lang3.ArrayUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.ImmutableList; +import com.gtnewhorizons.modularui.api.ModularUITextures; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; +import com.gtnewhorizons.modularui.api.fluids.FluidTanksHandler; +import com.gtnewhorizons.modularui.api.fluids.IFluidTanksHandler; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.math.Size; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; + +import gregtech.api.enums.MaterialsUEVplus; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.enums.TierEU; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.recipe.check.SimpleCheckRecipeResult; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTStreamUtil; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.OverclockCalculator; +import tectech.TecTech; +import tectech.recipe.TecTechRecipeMaps; +import tectech.thing.CustomItemList; +import tectech.thing.gui.TecTechUITextures; +import tectech.util.GodforgeMath; + +public class MTEExoticModule extends MTEBaseModule { + + private int numberOfFluids = 0; + private int numberOfItems = 0; + private long ticker = 0; + private long EUt = 0; + private long actualParallel = 0; + private boolean recipeInProgress = false; + private boolean recipeRegenerated = false; + private boolean magmatterMode = false; + private FluidStack[] randomizedFluidInput = new FluidStack[] {}; + private ItemStack[] randomizedItemInput = new ItemStack[] {}; + private GTRecipe plasmaRecipe = null; + private BigInteger powerForRecipe = BigInteger.ZERO; + private static final int NUMBER_OF_INPUTS = 7; + private static final int INPUT_LIST_WINDOW_ID = 11; + + public MTEExoticModule(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTEExoticModule(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTEExoticModule(mName); + } + + @Override + protected ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @NotNull + @Override + protected Stream<GTRecipe> findRecipeMatches(@Nullable RecipeMap<?> map) { + if (!recipeInProgress) { + if (magmatterMode) { + plasmaRecipe = generateMagmatterRecipe(); + } else { + plasmaRecipe = generateQuarkGluonRecipe(); + } + } + return GTStreamUtil.ofNullable(plasmaRecipe); + } + + @NotNull + @Override + protected CheckRecipeResult validateRecipe(@Nonnull GTRecipe recipe) { + if (!recipeInProgress || recipeRegenerated) { + powerForRecipe = BigInteger.valueOf(getProcessingVoltage()) + .multiply(BigInteger.valueOf(recipe.mDuration * actualParallel)); + if (getUserEU(userUUID).compareTo(powerForRecipe) < 0) { + plasmaRecipe = null; + return CheckRecipeResultRegistry.insufficientStartupPower(powerForRecipe); + } + + if (numberOfFluids != 0) { + for (FluidStack fluidStack : randomizedFluidInput) { + dumpFluid( + mOutputHatches, + new FluidStack(fluidStack.getFluid(), fluidStack.amount / 1000), + false); + } + } + + if (numberOfItems != 0) { + for (ItemStack itemStack : randomizedItemInput) { + addOutput(itemStack); + } + } + + recipeInProgress = true; + recipeRegenerated = false; + } + + for (FluidStack stack : recipe.mFluidInputs) { + if (!ArrayUtils.contains(inputFluids, stack)) { + return SimpleCheckRecipeResult.ofFailure("waiting_for_inputs"); + } + } + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @NotNull + @Override + protected CheckRecipeResult onRecipeStart(@Nonnull GTRecipe recipe) { + EUt = calculatedEut; + powerForRecipe = BigInteger.valueOf(EUt) + .multiply(BigInteger.valueOf(duration * actualParallel)); + + if (!addEUToGlobalEnergyMap(userUUID, powerForRecipe.negate())) { + return CheckRecipeResultRegistry.insufficientStartupPower(powerForRecipe); + } + + addToPowerTally(powerForRecipe); + addToRecipeTally(calculatedParallels); + setCalculatedEut(0); + plasmaRecipe = null; + recipeInProgress = false; + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @Nonnull + @Override + protected OverclockCalculator createOverclockCalculator(@Nonnull GTRecipe recipe) { + return super.createOverclockCalculator(recipe).setEUt(getProcessingVoltage()) + .setDurationDecreasePerOC(getOverclockTimeFactor()); + } + + }; + } + + @Override + protected void setProcessingLogicPower(ProcessingLogic logic) { + logic.setAvailableVoltage(Long.MAX_VALUE); + logic.setAvailableAmperage(Integer.MAX_VALUE); + logic.setAmperageOC(false); + logic.setSpeedBonus(getSpeedBonus()); + logic.setEuModifier(getEnergyDiscount()); + } + + @Override + public RecipeMap<?> getRecipeMap() { + return TecTechRecipeMaps.godforgeExoticMatterRecipes; + } + + private GTRecipe generateQuarkGluonRecipe() { + actualParallel = getMaxParallel(); + numberOfFluids = GodforgeMath.getRandomIntInRange(0, NUMBER_OF_INPUTS); + numberOfItems = NUMBER_OF_INPUTS - numberOfFluids; + randomizedFluidInput = getRandomFluidInputs(exoticModulePlasmaFluidMap, numberOfFluids); + randomizedItemInput = getRandomItemInputs(exoticModulePlasmaItemMap, numberOfItems); + + if (numberOfFluids != 0) { + for (FluidStack fluidStack : randomizedFluidInput) { + fluidStack.amount = 1000 * GodforgeMath.getRandomIntInRange(1, 64); + } + } + + if (numberOfItems != 0) { + for (ItemStack itemStack : randomizedItemInput) { + itemStack.stackSize = 9 * GodforgeMath.getRandomIntInRange(1, 7); + } + } + + return new GTRecipe( + false, + null, + null, + null, + null, + ArrayUtils + .addAll(convertItemToPlasma(randomizedItemInput, 1), convertFluidToPlasma(randomizedFluidInput, 1)), + new FluidStack[] { MaterialsUEVplus.QuarkGluonPlasma.getFluid(1000 * actualParallel) }, + 10 * SECONDS, + (int) TierEU.RECIPE_MAX, + 0); + } + + private GTRecipe generateMagmatterRecipe() { + actualParallel = getMaxParallel(); + randomizedItemInput = getRandomItemInputs(exoticModuleMagmatterItemMap, 1); + numberOfItems = 1; + numberOfFluids = 2; + int timeAmount = GodforgeMath.getRandomIntInRange(1, 50); + int spaceAmount = GodforgeMath.getRandomIntInRange(51, 100); + randomizedFluidInput = new FluidStack[] { MaterialsUEVplus.Time.getMolten(timeAmount * 1000L), + MaterialsUEVplus.Space.getMolten(spaceAmount * 1000L) }; + + return new GTRecipe( + false, + null, + null, + null, + null, + ArrayUtils.addAll( + convertItemToPlasma(randomizedItemInput, spaceAmount - timeAmount), + MaterialsUEVplus.Time.getMolten(timeAmount), + MaterialsUEVplus.Space.getMolten(spaceAmount)), + new FluidStack[] { MaterialsUEVplus.MagMatter.getMolten(576 * actualParallel) }, + 10 * SECONDS, + (int) TierEU.RECIPE_MAX, + 0); + } + + private FluidStack[] getRandomFluidInputs(HashMap<FluidStack, Integer> fluidMap, int numberOfFluids) { + int cumulativeWeight = 0; + + List<Map.Entry<FluidStack, Integer>> fluidEntryList = new ArrayList<>(fluidMap.entrySet()); + + List<Integer> cumulativeWeights = new ArrayList<>(); + for (Map.Entry<FluidStack, Integer> entry : fluidEntryList) { + cumulativeWeight += entry.getValue(); + cumulativeWeights.add(cumulativeWeight); + } + + List<FluidStack> pickedFluids = new ArrayList<>(); + for (int i = 0; i < numberOfFluids; i++) { + int randomWeight = GodforgeMath.getRandomIntInRange(1, cumulativeWeight); + // Find the corresponding FluidStack based on randomWeight + for (int j = 0; j < cumulativeWeights.size(); j++) { + if (randomWeight <= cumulativeWeights.get(j)) { + FluidStack pickedFluid = fluidEntryList.get(j) + .getKey(); + // prevent duplicates + if (pickedFluids.contains(pickedFluid)) { + i--; + break; + } + pickedFluids.add(pickedFluid); + break; + } + } + } + + return pickedFluids.toArray(new FluidStack[0]); + + } + + private ItemStack[] getRandomItemInputs(HashMap<ItemStack, Integer> itemMap, int numberOfItems) { + int cumulativeWeight = 0; + + List<Map.Entry<ItemStack, Integer>> itemEntryList = new ArrayList<>(itemMap.entrySet()); + + List<Integer> cumulativeWeights = new ArrayList<>(); + for (Map.Entry<ItemStack, Integer> entry : itemEntryList) { + cumulativeWeight += entry.getValue(); + cumulativeWeights.add(cumulativeWeight); + } + + List<ItemStack> pickedItems = new ArrayList<>(); + for (int i = 0; i < numberOfItems; i++) { + int randomWeight = GodforgeMath.getRandomIntInRange(1, cumulativeWeight); + // Find the corresponding ItemStack based on randomWeight + for (int j = 0; j < cumulativeWeights.size(); j++) { + if (randomWeight <= cumulativeWeights.get(j)) { + ItemStack pickedItem = itemEntryList.get(j) + .getKey(); + // prevent duplicates + if (pickedItems.contains(pickedItem)) { + i--; + break; + } + pickedItems.add(pickedItem); + break; + } + } + } + return pickedItems.toArray(new ItemStack[0]); + + } + + private FluidStack[] convertItemToPlasma(ItemStack[] items, long multiplier) { + List<FluidStack> plasmas = new ArrayList<>(); + + for (ItemStack itemStack : items) { + String dict = OreDictionary.getOreName(OreDictionary.getOreIDs(itemStack)[0]); + // substring 8 because dustTiny is 8 characters long and there is no other possible oreDict + String strippedOreDict = dict.substring(8); + plasmas.add( + FluidRegistry.getFluidStack( + "plasma." + strippedOreDict.toLowerCase(), + (int) (INGOTS * multiplier * itemStack.stackSize))); + } + + return plasmas.toArray(new FluidStack[0]); + } + + private FluidStack[] convertFluidToPlasma(FluidStack[] fluids, long multiplier) { + List<FluidStack> plasmas = new ArrayList<>(); + + for (FluidStack fluidStack : fluids) { + String[] fluidName = fluidStack.getUnlocalizedName() + .split("\\."); + plasmas.add( + FluidRegistry.getFluidStack( + "plasma." + fluidName[fluidName.length - 1], + (int) (multiplier * fluidStack.amount))); + } + + return plasmas.toArray(new FluidStack[0]); + } + + @Override + public boolean supportsSingleRecipeLocking() { + return false; + } + + @Override + public boolean supportsBatchMode() { + return false; + } + + @Override + public void saveNBTData(NBTTagCompound NBT) { + + NBT.setBoolean("recipeInProgress", recipeInProgress); + NBT.setBoolean("magmatterMode", magmatterMode); + NBT.setLong("maxParallel", actualParallel); + + // Store damage values/stack sizes of input plasmas + NBTTagCompound fluidStackListNBTTag = new NBTTagCompound(); + + if (plasmaRecipe != null) { + fluidStackListNBTTag.setLong("numberOfPlasmas", plasmaRecipe.mFluidInputs.length); + + int index = 0; + for (FluidStack stack : plasmaRecipe.mFluidInputs) { + // Save fluid amount to NBT + fluidStackListNBTTag.setLong(index + "fluidAmount", stack.amount); + + // Save FluidStack to NBT + NBT.setTag(index + "fluidStack", stack.writeToNBT(new NBTTagCompound())); + + index++; + } + } else { + fluidStackListNBTTag.setLong("numberOfPlasmas", 0); + } + + NBT.setTag("inputPlasmas", fluidStackListNBTTag); + super.saveNBTData(NBT); + } + + @Override + public void loadNBTData(final NBTTagCompound NBT) { + + recipeInProgress = NBT.getBoolean("recipeInProgress"); + magmatterMode = NBT.getBoolean("magmatterMode"); + actualParallel = NBT.getLong("maxParallel"); + + // Load damage values/fluid amounts of input plasmas and convert back to fluids + NBTTagCompound tempFluidTag = NBT.getCompoundTag("inputPlasmas"); + + long numberOfPlasmas = tempFluidTag.getLong("numberOfPlasmas"); + if (numberOfPlasmas > 0) { + + FluidStack[] stacks = new FluidStack[(int) numberOfPlasmas]; + for (int i = 0; i < numberOfPlasmas; i++) { + // Load fluid amount from NBT + int amount = tempFluidTag.getInteger(i + "fluidAmount"); + + // Load FluidStack from NBT + FluidStack stack = FluidStack.loadFluidStackFromNBT(NBT.getCompoundTag(i + "fluidStack")); + + stacks[i] = new FluidStack(stack, amount); + } + + FluidStack outputFluid; + if (magmatterMode) { + outputFluid = MaterialsUEVplus.MagMatter.getMolten(576L * actualParallel); + } else { + outputFluid = MaterialsUEVplus.QuarkGluonPlasma.getFluid(1000L * actualParallel); + } + + plasmaRecipe = new GTRecipe( + false, + null, + null, + null, + null, + stacks, + new FluidStack[] { outputFluid }, + 10 * SECONDS, + (int) TierEU.RECIPE_MAX, + 0); + } + + super.loadNBTData(NBT); + } + + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + super.onPostTick(aBaseMetaTileEntity, aTick); + ticker++; + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + builder.widget( + new DrawableWidget().setPos(8, 69) + .setSize(16, 16) + .addTooltip(translateToLocal("fog.button.exoticinputs.tooltip")) + .setTooltipShowUpDelay(TOOLTIP_DELAY)); + super.addUIWidgets(builder, buildContext); + buildContext.addSyncedWindow(INPUT_LIST_WINDOW_ID, this::createInputListWindow); + builder.widget(createMagmatterSwitch(builder)); + builder.widget(createExpectedInputsButton()); + builder.widget( + new DrawableWidget().setDrawable(ModularUITextures.ICON_INFO) + .setPos(8, 69) + .setSize(16, 16)); + + } + + protected ModularWindow createInputListWindow(final EntityPlayer player) { + final int WIDTH = 100; + final int HEIGHT = 60; + final int PARENT_WIDTH = getGUIWidth(); + final int PARENT_HEIGHT = getGUIHeight(); + final Pos2d[] slotPositions = new Pos2d[] { new Pos2d(23, 35), new Pos2d(41, 35), new Pos2d(59, 35), + new Pos2d(14, 17), new Pos2d(32, 17), new Pos2d(50, 17), new Pos2d(68, 17) }; + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.setPos( + (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) + .add(Alignment.TopLeft.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT))) + .subtract(100, -47)); + + IFluidTanksHandler tanksHandler = new FluidTanksHandler(7, 128000); + for (int i = 0; i < 7; i++) { + if (plasmaRecipe != null && i < plasmaRecipe.mFluidInputs.length) { + FluidStack plasma = plasmaRecipe.mFluidInputs[i]; + tanksHandler.setFluidInTank(i, plasma.getFluid(), plasma.amount); + } + builder.widget( + new DrawableWidget().setDrawable(ModularUITextures.FLUID_SLOT) + .setSize(18, 18) + .setPos(slotPositions[i])) + .widget( + new FluidSlotWidget(tanksHandler, i).setInteraction(false, false) + .setSize(18, 18) + .setPos(slotPositions[i]) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> recipeInProgress, val -> recipeInProgress = val), + builder, + (widget, val) -> widget.checkNeedsRebuild())); + } + + builder.widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.expectedinputs")) + .setDefaultColor(EnumChatFormatting.BLACK) + .setTextAlignment(Alignment.Center) + .setSize(100, 9) + .setPos(0, 6)); + + builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient() && ticker > 1200) { + + if (magmatterMode) { + plasmaRecipe = generateMagmatterRecipe(); + } else { + plasmaRecipe = generateQuarkGluonRecipe(); + } + recipeRegenerated = true; + + for (int i = 0; i < 7; i++) { + if (i < plasmaRecipe.mFluidInputs.length) { + FluidStack plasma = plasmaRecipe.mFluidInputs[i]; + tanksHandler.setFluidInTank(i, plasma.getFluid(), plasma.amount); + } + } + ticker = 0; + ForgeOfGodsUI.reopenWindow(widget, INPUT_LIST_WINDOW_ID); + } + }) + .setPlayClickSound(true) + .setBackground(TecTechUITextures.OVERLAY_CYCLIC_BLUE) + .dynamicTooltip(this::refreshTooltip) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(16, 16) + .setPos(5, 37) + .attachSyncer( + new FakeSyncWidget.LongSyncer(() -> ticker, val -> ticker = val), + builder, + (widget, val) -> widget.notifyTooltipChange())); + + return builder.build(); + } + + private Widget createExpectedInputsButton() { + return new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient()) { + widget.getContext() + .openSyncedWindow(INPUT_LIST_WINDOW_ID); + } + }) + .setPlayClickSound(true) + .setSize(16, 16) + .setPos(8, 69); + } + + protected ButtonWidget createMagmatterSwitch(IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isMagmatterCapable) { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + magmatterMode = !magmatterMode; + widget.notifyTooltipChange(); + } + }) + .setPlayClickSound(false) + .setBackground( + () -> new IDrawable[] { TecTechUITextures.BUTTON_CELESTIAL_32x32, + new ItemDrawable( + isMagmatterCapable && isMagmatterModeOn() + ? GTOreDictUnificator.get(OrePrefixes.dust, MaterialsUEVplus.MagMatter, 1) + : CustomItemList.Godforge_FakeItemQGP.get(1)) + + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(this::isMagmatterModeOn, this::setMagmatterMode), builder) + .dynamicTooltip(() -> { + List<String> ret = new ArrayList<>(); + if (!isMagmatterModeOn()) { + ret.add(translateToLocal("fog.button.magmattermode.tooltip.01")); + } + if (isMagmatterCapable && isMagmatterModeOn()) { + ret.add(translateToLocal("fog.button.magmattermode.tooltip.02")); + } + if (!isMagmatterCapable) { + ret.add(EnumChatFormatting.GRAY + translateToLocal("fog.button.magmattermode.tooltip.03")); + } + return ret; + }) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(16, 16) + .setPos(174, 91) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> isMagmatterCapable, this::setMagmatterCapable), + builder); + return (ButtonWidget) button; + } + + private List<String> refreshTooltip() { + if (ticker > 1200) { + return ImmutableList.of(translateToLocal("fog.button.reciperefresh.tooltip")); + } + + return ImmutableList.of( + translateToLocal("fog.button.refreshtimer.tooltip") + " " + + (int) Math.ceil((1200 - ticker) / 20d) + + " " + + translateToLocal("fog.button.seconds")); + } + + public boolean isMagmatterModeOn() { + return magmatterMode; + } + + private void setMagmatterMode(boolean enabled) { + magmatterMode = enabled; + } + + @Override + public void setMagmatterCapable(boolean isCapable) { + if (!isCapable && isMagmatterCapable) { + // only set when it previously was capable + setMagmatterMode(false); + } + super.setMagmatterCapable(isCapable); + } + + @Override + protected boolean filtersFluid() { + return false; + } + + @Override + public MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Exotic Matter Producer") + .addInfo("This is a module of the Godforge.") + .addInfo("Must be part of a Godforge to function.") + .addInfo("Used for ultra high temperature matter degeneration.") + .addSeparator(EnumChatFormatting.AQUA, 75) + .addInfo("The fourth and final module of the Godforge, this module breaks apart the very") + .addInfo("building blocks of matter, producing exotic mixtures in the process. Quark-Gluon Plasma") + .addInfo("can be manufactured right away, but production of Magnetic Monopole Matter (Magmatter)") + .addInfo("requires a fully upgraded Godforge.") + .addInfo("This module is specialized towards acquisition of unique materials.") + .beginStructureBlock(7, 7, 13, false) + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Singularity Reinforced Stellar Shielding Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Boundless Gravitationally Severed Structure Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Harmonic Phonon Transmission Conduit") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Celestial Matter Guidance Casing") + .addStructureInfo(EnumChatFormatting.GOLD + "1" + EnumChatFormatting.GRAY + " Stellar Energy Siphon Casing") + .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Output Hatch") + .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Output Bus") + .toolTipFinisher(EnumChatFormatting.AQUA, 75); + return tt; + } + + @Override + public String[] getInfoData() { + ArrayList<String> str = new ArrayList<>(); + str.add( + "Progress: " + GREEN + + formatNumbers(mProgresstime / 20) + + RESET + + " s / " + + YELLOW + + formatNumbers(mMaxProgresstime / 20) + + RESET + + " s"); + str.add( + "Currently using: " + RED + + (getBaseMetaTileEntity().isActive() ? formatNumbers(EUt * actualParallel) : "0") + + RESET + + " EU/t"); + str.add(YELLOW + "Max Parallel: " + RESET + formatNumbers(getMaxParallel())); + str.add( + YELLOW + "Current Parallel: " + + RESET + + (getBaseMetaTileEntity().isActive() ? formatNumbers(getMaxParallel()) : "0")); + str.add(YELLOW + "Recipe time multiplier: " + RESET + formatNumbers(getSpeedBonus())); + str.add(YELLOW + "Energy multiplier: " + RESET + formatNumbers(getEnergyDiscount())); + str.add(YELLOW + "Recipe time divisor per non-perfect OC: " + RESET + formatNumbers(getOverclockTimeFactor())); + return str.toArray(new String[0]); + } + +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEForgeOfGods.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEForgeOfGods.java new file mode 100644 index 0000000000..c7d52215c9 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEForgeOfGods.java @@ -0,0 +1,4092 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static gregtech.api.enums.Mods.Avaritia; +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.api.util.GTModHandler.getModItem; +import static gregtech.api.util.GTRecipeBuilder.SECONDS; +import static gregtech.api.util.GTUtility.filterValidMTEs; +import static gregtech.api.util.GTUtility.formatNumbers; +import static java.lang.Math.floor; +import static java.lang.Math.log; +import static java.lang.Math.max; +import static net.minecraft.util.StatCollector.translateToLocal; +import static tectech.loader.recipe.Godforge.godforgeUpgradeMats; +import static tectech.thing.casing.TTCasingsContainer.GodforgeCasings; +import static tectech.thing.casing.TTCasingsContainer.forgeOfGodsRenderBlock; +import static tectech.util.GodforgeMath.allowModuleConnection; +import static tectech.util.GodforgeMath.calculateEnergyDiscountForModules; +import static tectech.util.GodforgeMath.calculateFuelConsumption; +import static tectech.util.GodforgeMath.calculateMaxFuelFactor; +import static tectech.util.GodforgeMath.calculateMaxHeatForModules; +import static tectech.util.GodforgeMath.calculateMaxParallelForModules; +import static tectech.util.GodforgeMath.calculateProcessingVoltageForModules; +import static tectech.util.GodforgeMath.calculateSpeedBonusForModules; +import static tectech.util.GodforgeMath.calculateStartupFuelConsumption; +import static tectech.util.GodforgeMath.queryMilestoneStats; +import static tectech.util.GodforgeMath.setMiscModuleParameters; +import static tectech.util.TTUtility.toExponentForm; + +import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; + +import com.google.common.collect.ImmutableList; +import com.google.common.math.LongMath; +import com.google.common.primitives.Booleans; +import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable; +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizons.modularui.api.ModularUITextures; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.Text; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.drawable.shapes.Rectangle; +import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; +import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.math.MainAxisAlignment; +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.math.Size; +import com.gtnewhorizons.modularui.api.screen.ModularUIContext; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedRow; +import com.gtnewhorizons.modularui.common.widget.DynamicTextWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.FluidNameHolderWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.ProgressBar; +import com.gtnewhorizons.modularui.common.widget.Scrollable; +import com.gtnewhorizons.modularui.common.widget.SlotGroup; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; + +import blockrenderer6343.client.world.ClientFakePlayer; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.enums.Materials; +import gregtech.api.enums.MaterialsUEVplus; +import gregtech.api.enums.Mods; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.Textures; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.IHatchElement; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.implementations.MTEHatchInput; +import gregtech.api.metatileentity.implementations.MTEHatchInputBus; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.HatchElementBuilder; +import gregtech.api.util.IGTHatchAdder; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.common.tileentities.machines.MTEHatchInputBusME; +import gregtech.common.tileentities.machines.MTEHatchOutputBusME; +import tectech.TecTech; +import tectech.loader.ConfigHandler; +import tectech.thing.block.BlockGodforgeGlass; +import tectech.thing.block.TileEntityForgeOfGods; +import tectech.thing.gui.TecTechUITextures; +import tectech.thing.metaTileEntity.multi.base.TTMultiblockBase; +import tectech.thing.metaTileEntity.multi.godforge.ForgeOfGodsUI.StarColorRGBM; +import tectech.thing.metaTileEntity.multi.godforge.color.ForgeOfGodsStarColor; +import tectech.thing.metaTileEntity.multi.godforge.color.StarColorSetting; +import tectech.thing.metaTileEntity.multi.godforge.color.StarColorStorage; + +public class MTEForgeOfGods extends TTMultiblockBase implements IConstructable, ISurvivalConstructable { + + private static Textures.BlockIcons.CustomIcon ScreenON; + + private int fuelConsumptionFactor = 1; + private int selectedFuelType = 0; + private int internalBattery = 0; + private int maxBatteryCharge = 100; + private int gravitonShardsAvailable = 0; + private int gravitonShardsSpent = 0; + private int ringAmount = 1; + private int stellarFuelAmount = 0; + private int neededStartupFuel = 0; + private long fuelConsumption = 0; + private long totalRecipesProcessed = 0; + private long totalFuelConsumed = 0; + private float totalExtensionsBuilt = 0; + private float powerMilestonePercentage = 0; + private float recipeMilestonePercentage = 0; + private float fuelMilestonePercentage = 0; + private float structureMilestonePercentage = 0; + private float invertedPowerMilestonePercentage = 0; + private float invertedRecipeMilestonePercentage = 0; + private float invertedFuelMilestonePercentage = 0; + private float invertedStructureMilestonePercentage = 0; + private BigInteger totalPowerConsumed = BigInteger.ZERO; + private boolean batteryCharging = false; + private boolean inversion = false; + private boolean gravitonShardEjection = false; + private FormattingMode formattingMode = FormattingMode.NONE; + private boolean isRenderActive = false; + private boolean secretUpgrade = false; + private final ItemStack[] storedUpgradeWindowItems = new ItemStack[16]; + public ArrayList<MTEBaseModule> moduleHatches = new ArrayList<>(); + protected ItemStackHandler inputSlotHandler = new ItemStackHandler(16); + + // Star cosmetics fields + // actual star cosmetics + private final StarColorStorage starColors = new StarColorStorage(); + private String selectedStarColor = ForgeOfGodsStarColor.DEFAULT.getName(); + private int rotationSpeed = 5; + private int starSize = 20; + // editing star color + private ForgeOfGodsStarColor newStarColor = starColors.newTemplateColor(); + private int starColorR, starColorG, starColorB; + private float starGamma; + private int editingStarIndex; // editing a full color preset + private int editingColorIndex; // editing a single color in a preset + private ForgeOfGodsStarColor importedStarColor; + + private static final int FUEL_CONFIG_WINDOW_ID = 9; + private static final int UPGRADE_TREE_WINDOW_ID = 10; + private static final int INDIVIDUAL_UPGRADE_WINDOW_ID = 11; + private static final int BATTERY_CONFIG_WINDOW_ID = 12; + private static final int MILESTONE_WINDOW_ID = 13; + private static final int INDIVIDUAL_MILESTONE_WINDOW_ID = 14; + private static final int MANUAL_INSERTION_WINDOW_ID = 15; + private static final int GENERAL_INFO_WINDOW_ID = 16; + private static final int SPECIAL_THANKS_WINDOW_ID = 17; + private static final int STAR_COSMETICS_WINDOW_ID = 18; + private static final int STAR_CUSTOM_COLOR_WINDOW_ID = 19; + private static final int STAR_CUSTOM_COLOR_IMPORT_WINDOW_ID = 20; + private static final int TEXTURE_INDEX = 960; + private static final int[] FIRST_SPLIT_UPGRADES = new int[] { 12, 13, 14 }; + private static final Integer[] UPGRADE_MATERIAL_ID_CONVERSION = { 0, 5, 7, 11, 26, 29, 30 }; + private static final long POWER_MILESTONE_CONSTANT = LongMath.pow(10, 15); + private static final long RECIPE_MILESTONE_CONSTANT = LongMath.pow(10, 7); + private static final long FUEL_MILESTONE_CONSTANT = 10_000; + private static final long RECIPE_MILESTONE_T7_CONSTANT = RECIPE_MILESTONE_CONSTANT * LongMath.pow(6, 6); + private static final long FUEL_MILESTONE_T7_CONSTANT = FUEL_MILESTONE_CONSTANT * LongMath.pow(3, 6); + private static final BigInteger POWER_MILESTONE_T7_CONSTANT = BigInteger.valueOf(POWER_MILESTONE_CONSTANT) + .multiply(BigInteger.valueOf(LongMath.pow(9, 6))); + private static final double POWER_LOG_CONSTANT = Math.log(9); + private static final double RECIPE_LOG_CONSTANT = Math.log(6); + private static final double FUEL_LOG_CONSTANT = Math.log(3); + protected static final String STRUCTURE_PIECE_MAIN = "main"; + protected static final String STRUCTURE_PIECE_SHAFT = "beam_shaft"; + protected static final String STRUCTURE_PIECE_FIRST_RING = "first_ring"; + protected static final String STRUCTURE_PIECE_FIRST_RING_AIR = "first_ring_air"; + protected static final String STRUCTURE_PIECE_SECOND_RING = "second_ring"; + protected static final String STRUCTURE_PIECE_SECOND_RING_AIR = "second_ring_air"; + protected static final String STRUCTURE_PIECE_THIRD_RING = "third_ring"; + protected static final String STRUCTURE_PIECE_THIRD_RING_AIR = "third_ring_air"; + private static final String SCANNER_INFO_BAR = EnumChatFormatting.BLUE.toString() + EnumChatFormatting.STRIKETHROUGH + + "--------------------------------------------"; + private static final ItemStack STELLAR_FUEL = Avaritia.isModLoaded() ? getModItem(Avaritia.ID, "Resource", 1, 8) + : GTOreDictUnificator.get(OrePrefixes.block, Materials.Neutronium, 1); + + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + // 1000 blocks max per placement. + int realBudget = elementBudget >= 1000 ? elementBudget : Math.min(1000, elementBudget * 5); + int built = 0; + + if (Mods.BlockRenderer6343.isModLoaded() && env.getActor() instanceof ClientFakePlayer) { + built = survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 63, 14, 1, elementBudget, env, false, true); + if (stackSize.stackSize > 1) { + built += survivialBuildPiece( + STRUCTURE_PIECE_SECOND_RING, + stackSize, + 55, + 11, + -67, + realBudget, + env, + false, + true); + } + if (stackSize.stackSize > 2) { + built += survivialBuildPiece( + STRUCTURE_PIECE_THIRD_RING, + stackSize, + 47, + 13, + -76, + realBudget, + env, + false, + true); + } + return built; + } + + survivialBuildPiece(STRUCTURE_PIECE_SHAFT, stackSize, 63, 14, 1, realBudget, env, false, true); + + if (stackSize.stackSize > 0 && ringAmount < 1) { + built += survivialBuildPiece( + STRUCTURE_PIECE_FIRST_RING, + stackSize, + 63, + 14, + -59, + realBudget, + env, + false, + true); + } + + if (stackSize.stackSize > 1 && ringAmount < 2) { + built += survivialBuildPiece( + STRUCTURE_PIECE_SECOND_RING, + stackSize, + 55, + 11, + -67, + realBudget, + env, + false, + true); + } + + if (stackSize.stackSize > 2 && ringAmount < 3) { + built += survivialBuildPiece( + STRUCTURE_PIECE_THIRD_RING, + stackSize, + 47, + 13, + -76, + realBudget, + env, + false, + true); + } + return built; + } + + @Override + public IStructureDefinition<MTEForgeOfGods> getStructure_EM() { + return STRUCTURE_DEFINITION; + } + + public static final IStructureDefinition<MTEForgeOfGods> STRUCTURE_DEFINITION = IStructureDefinition + .<MTEForgeOfGods>builder() + .addShape(STRUCTURE_PIECE_MAIN, ForgeOfGodsStructureString.MAIN_STRUCTURE) + .addShape(STRUCTURE_PIECE_SHAFT, ForgeOfGodsStructureString.BEAM_SHAFT) + .addShape(STRUCTURE_PIECE_FIRST_RING, ForgeOfGodsStructureString.FIRST_RING) + .addShape(STRUCTURE_PIECE_FIRST_RING_AIR, ForgeOfGodsStructureString.FIRST_RING_AIR) + .addShape(STRUCTURE_PIECE_SECOND_RING, ForgeOfGodsRingsStructureString.SECOND_RING) + .addShape(STRUCTURE_PIECE_SECOND_RING_AIR, ForgeOfGodsRingsStructureString.SECOND_RING_AIR) + .addShape(STRUCTURE_PIECE_THIRD_RING, ForgeOfGodsRingsStructureString.THIRD_RING) + .addShape(STRUCTURE_PIECE_THIRD_RING_AIR, ForgeOfGodsRingsStructureString.THIRD_RING_AIR) + .addElement('A', classicHatches(TEXTURE_INDEX + 3, 1, GodforgeCasings, 3)) + .addElement('B', ofBlock(GodforgeCasings, 0)) + .addElement('C', ofBlock(GodforgeCasings, 1)) + .addElement('D', ofBlock(GodforgeCasings, 2)) + .addElement('E', ofBlock(GodforgeCasings, 3)) + .addElement('F', ofBlock(GodforgeCasings, 4)) + .addElement('G', ofBlock(GodforgeCasings, 5)) + .addElement('H', ofBlock(BlockGodforgeGlass.INSTANCE, 0)) + .addElement('I', ofBlock(GodforgeCasings, 7)) + .addElement( + 'J', + HatchElementBuilder.<MTEForgeOfGods>builder() + .atLeast(moduleElement.Module) + .casingIndex(TEXTURE_INDEX) + .dot(2) + .buildAndChain(GodforgeCasings, 0)) + .addElement('K', ofBlock(GodforgeCasings, 6)) + .addElement('L', ofBlock(Blocks.air, 0)) + .build(); + + public MTEForgeOfGods(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTEForgeOfGods(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTEForgeOfGods(mName); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IIconRegister aBlockIconRegister) { + ScreenON = new Textures.BlockIcons.CustomIcon("iconsets/GODFORGE_CONTROLLER"); + super.registerIcons(aBlockIconRegister); + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean aActive, boolean aRedstone) { + if (side == facing) { + return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX + 1), + TextureFactory.builder() + .addIcon(ScreenON) + .extFacing() + .build(), + TextureFactory.builder() + .addIcon(ScreenON) + .extFacing() + .glow() + .build() }; + } + return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX + 1) }; + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + structureBuild_EM(STRUCTURE_PIECE_MAIN, 63, 14, 1, stackSize, hintsOnly); + if (stackSize.stackSize > 1) { + buildPiece(STRUCTURE_PIECE_SECOND_RING, stackSize, hintsOnly, 55, 11, -67); + } + if (stackSize.stackSize > 2) { + buildPiece(STRUCTURE_PIECE_THIRD_RING, stackSize, hintsOnly, 47, 13, -76); + } + } + + private final ArrayList<FluidStack> validFuelList = new ArrayList<>() { + + { + add(MaterialsUEVplus.DimensionallyTranscendentResidue.getFluid(1)); + add(MaterialsUEVplus.RawStarMatter.getFluid(1)); + add(MaterialsUEVplus.MagnetohydrodynamicallyConstrainedStarMatter.getMolten(1)); + } + }; + + @Override + public boolean checkMachine_EM(IGregTechTileEntity iGregTechTileEntity, ItemStack itemStack) { + + moduleHatches.clear(); + // Check structure of multi + if (isRenderActive) { + if (!structureCheck_EM(STRUCTURE_PIECE_SHAFT, 63, 14, 1) + || !structureCheck_EM(STRUCTURE_PIECE_FIRST_RING_AIR, 63, 14, -59)) { + destroyRenderer(); + return false; + } + } else if (!structureCheck_EM(STRUCTURE_PIECE_MAIN, 63, 14, 1)) { + return false; + } + + if (internalBattery != 0 && !isRenderActive) { + createRenderer(); + } + // Check there is 1 input bus + if (mInputBusses.size() != 1) { + return false; + } + + // Check there is 1 me output bus + { + if (mOutputBusses.size() != 1) { + return false; + } + + if (!(mOutputBusses.get(0) instanceof MTEHatchOutputBusME)) { + return false; + } + } + // Make sure there are no energy hatches + { + if (!mEnergyHatches.isEmpty()) { + return false; + } + + if (!mExoticEnergyHatches.isEmpty()) { + return false; + } + } + + // Make sure there is 1 input hatch + if (mInputHatches.size() != 1) { + return false; + } + + if (isUpgradeActive(26)) { + if (checkPiece(STRUCTURE_PIECE_SECOND_RING, 55, 11, -67)) { + ringAmount = 2; + destroySecondRing(); + updateRenderer(); + } + if (isRenderActive && ringAmount >= 2 && !checkPiece(STRUCTURE_PIECE_SECOND_RING_AIR, 55, 11, -67)) { + destroyRenderer(); + } + } else { + if (ringAmount == 3) { + buildThirdRing(); + } + if (ringAmount >= 2) { + ringAmount = 1; + updateRenderer(); + buildSecondRing(); + } + } + + if (isUpgradeActive(29)) { + if (checkPiece(STRUCTURE_PIECE_THIRD_RING, 47, 13, -76)) { + ringAmount = 3; + destroyThirdRing(); + updateRenderer(); + } + if (isRenderActive && ringAmount == 3 && !checkPiece(STRUCTURE_PIECE_THIRD_RING_AIR, 47, 13, -76)) { + destroyRenderer(); + } + } else { + if (ringAmount == 3) { + ringAmount = 2; + updateRenderer(); + buildThirdRing(); + } + } + + return true; + } + + int ticker = 0; + + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + super.onPostTick(aBaseMetaTileEntity, aTick); + if (aBaseMetaTileEntity.isServerSide()) { + ticker++; + // Check and drain fuel + if (ticker % (5 * SECONDS) == 0) { + ticker = 0; + startRecipeProcessing(); + + int maxModuleCount = 8; + if (upgrades[26]) { + maxModuleCount += 4; + } + if (upgrades[29]) { + maxModuleCount += 4; + } + + boolean isFinalUpgradeUnlocked = upgrades[30]; + + if (!mInputBusses.isEmpty()) { + if (internalBattery == 0 || isFinalUpgradeUnlocked) { + MTEHatchInputBus inputBus = mInputBusses.get(0); + ItemStack[] inputBusInventory = inputBus.getRealInventory(); + ItemStack itemToAbsorb = STELLAR_FUEL; + if (isFinalUpgradeUnlocked && internalBattery != 0) { + itemToAbsorb = GTOreDictUnificator.get(OrePrefixes.gem, MaterialsUEVplus.GravitonShard, 1); + } + if (inputBusInventory != null) { + for (int i = 0; i < inputBusInventory.length; i++) { + ItemStack itemStack = inputBusInventory[i]; + if (itemStack != null && itemStack.isItemEqual(itemToAbsorb)) { + int stacksize = itemStack.stackSize; + if (inputBus instanceof MTEHatchInputBusME meBus) { + ItemStack realItem = meBus.getRealInventory()[i + 16]; + if (realItem == null) { + break; + } + stacksize = realItem.stackSize; + } + inputBus.decrStackSize(i, stacksize); + if (internalBattery == 0) { + stellarFuelAmount += stacksize; + } else { + gravitonShardsAvailable += stacksize; + } + inputBus.updateSlots(); + } + } + } + if (internalBattery == 0) { + neededStartupFuel = calculateStartupFuelConsumption(this); + if (stellarFuelAmount >= neededStartupFuel) { + stellarFuelAmount -= neededStartupFuel; + increaseBattery(neededStartupFuel); + createRenderer(); + } + } + } + } + + if (internalBattery != 0) { + drainFuel(); + } + + determineCompositionMilestoneLevel(); + checkInversionStatus(); + determineMilestoneProgress(); + if (!ConfigHandler.debug.DEBUG_MODE) { + determineGravitonShardAmount(); + } + if (upgrades[30] && gravitonShardEjection) { + ejectGravitonShards(); + } + + // Do module calculations and checks + if (!moduleHatches.isEmpty() && internalBattery > 0 && moduleHatches.size() <= maxModuleCount) { + for (MTEBaseModule module : moduleHatches) { + if (allowModuleConnection(module, this)) { + module.connect(); + calculateMaxHeatForModules(module, this); + calculateSpeedBonusForModules(module, this); + calculateMaxParallelForModules(module, this); + calculateEnergyDiscountForModules(module, this); + setMiscModuleParameters(module, this); + queryMilestoneStats(module, this); + if (!upgrades[28]) { + calculateProcessingVoltageForModules(module, this); + } + } else { + module.disconnect(); + } + } + } else if (moduleHatches.size() > maxModuleCount) { + for (MTEBaseModule module : moduleHatches) { + module.disconnect(); + } + } + if (mEfficiency < 0) mEfficiency = 0; + endRecipeProcessing(); + } + } + } + + private void drainFuel() { + fuelConsumption = (long) Math.max(calculateFuelConsumption(this) * 5 * (batteryCharging ? 2 : 1), 1); + if (fuelConsumption >= Integer.MAX_VALUE) { + reduceBattery(fuelConsumptionFactor); + return; + } + + FluidStack fuelToDrain = new FluidStack(validFuelList.get(selectedFuelType), (int) fuelConsumption); + for (MTEHatchInput hatch : filterValidMTEs(mInputHatches)) { + FluidStack drained = hatch.drain(ForgeDirection.UNKNOWN, fuelToDrain, true); + if (drained == null) { + continue; + } + + fuelToDrain.amount -= drained.amount; + + if (fuelToDrain.amount == 0) { + totalFuelConsumed += getFuelFactor(); + if (batteryCharging) { + increaseBattery(fuelConsumptionFactor); + } + return; + } + } + reduceBattery(fuelConsumptionFactor); + } + + public boolean addModuleToMachineList(IGregTechTileEntity tileEntity, int baseCasingIndex) { + if (tileEntity == null) { + return false; + } + IMetaTileEntity metaTileEntity = tileEntity.getMetaTileEntity(); + if (metaTileEntity == null) { + return false; + } + if (metaTileEntity instanceof MTEBaseModule) { + return moduleHatches.add((MTEBaseModule) metaTileEntity); + } + return false; + } + + public enum moduleElement implements IHatchElement<MTEForgeOfGods> { + + Module(MTEForgeOfGods::addModuleToMachineList, MTEBaseModule.class) { + + @Override + public long count(MTEForgeOfGods tileEntity) { + return tileEntity.moduleHatches.size(); + } + }; + + private final List<Class<? extends IMetaTileEntity>> mteClasses; + private final IGTHatchAdder<MTEForgeOfGods> adder; + + @SafeVarargs + moduleElement(IGTHatchAdder<MTEForgeOfGods> adder, Class<? extends IMetaTileEntity>... mteClasses) { + this.mteClasses = Collections.unmodifiableList(Arrays.asList(mteClasses)); + this.adder = adder; + } + + @Override + public List<? extends Class<? extends IMetaTileEntity>> mteClasses() { + return mteClasses; + } + + public IGTHatchAdder<? super MTEForgeOfGods> adder() { + return adder; + } + } + + private TileEntityForgeOfGods getRenderer() { + IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); + + int x = gregTechTileEntity.getXCoord(); + int y = gregTechTileEntity.getYCoord(); + int z = gregTechTileEntity.getZCoord(); + + double xOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetX; + double zOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetZ; + double yOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetY; + + TileEntity tile = this.getBaseMetaTileEntity() + .getWorld() + .getTileEntity((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset)); + + if (tile instanceof TileEntityForgeOfGods forgeTile) { + return forgeTile; + } + return null; + } + + private void updateRenderer() { + TileEntityForgeOfGods tile = getRenderer(); + if (tile == null) return; + + tile.setRingCount(ringAmount); + tile.setStarRadius(starSize); + tile.setRotationSpeed(rotationSpeed); + tile.setColor(starColors.getByName(selectedStarColor)); + + tile.updateToClient(); + } + + private void createRenderer() { + + IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); + + int x = gregTechTileEntity.getXCoord(); + int y = gregTechTileEntity.getYCoord(); + int z = gregTechTileEntity.getZCoord(); + + double xOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetX; + double zOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetZ; + double yOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetY; + + this.getBaseMetaTileEntity() + .getWorld() + .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air); + this.getBaseMetaTileEntity() + .getWorld() + .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), forgeOfGodsRenderBlock); + TileEntityForgeOfGods rendererTileEntity = (TileEntityForgeOfGods) this.getBaseMetaTileEntity() + .getWorld() + .getTileEntity((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset)); + + switch (ringAmount) { + case 2 -> { + destroyFirstRing(); + destroySecondRing(); + } + case 3 -> { + destroyFirstRing(); + destroySecondRing(); + destroyThirdRing(); + } + default -> { + destroyFirstRing(); + } + } + + rendererTileEntity.setRenderRotation(getRotation(), getDirection()); + updateRenderer(); + + isRenderActive = true; + } + + private void destroyRenderer() { + + IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); + + int x = gregTechTileEntity.getXCoord(); + int y = gregTechTileEntity.getYCoord(); + int z = gregTechTileEntity.getZCoord(); + + double xOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetX; + double zOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetZ; + double yOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetY; + + this.getBaseMetaTileEntity() + .getWorld() + .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air); + + switch (ringAmount) { + case 2 -> { + buildFirstRing(); + buildSecondRing(); + } + case 3 -> { + buildFirstRing(); + buildSecondRing(); + buildThirdRing(); + } + default -> { + buildFirstRing(); + } + } + + isRenderActive = false; + } + + private void destroyFirstRing() { + buildPiece(STRUCTURE_PIECE_FIRST_RING_AIR, null, false, 63, 14, -59); + } + + private void destroySecondRing() { + buildPiece(STRUCTURE_PIECE_SECOND_RING_AIR, null, false, 55, 11, -67); + } + + private void destroyThirdRing() { + buildPiece(STRUCTURE_PIECE_THIRD_RING_AIR, null, false, 47, 13, -76); + } + + private void buildFirstRing() { + buildPiece(STRUCTURE_PIECE_FIRST_RING, null, false, 63, 14, -59); + } + + private void buildSecondRing() { + buildPiece(STRUCTURE_PIECE_SECOND_RING, null, false, 55, 11, -67); + } + + private void buildThirdRing() { + buildPiece(STRUCTURE_PIECE_THIRD_RING, null, false, 47, 13, -76); + } + + @Override + public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { + if (!ConfigHandler.debug.DEBUG_MODE) return; + if (isRenderActive) { + destroyRenderer(); + isRenderActive = false; + } else { + ringAmount = 3; + createRenderer(); + isRenderActive = true; + } + } + + @Override + public void onBlockDestroyed() { + super.onBlockDestroyed(); + if (isRenderActive) { + destroyRenderer(); + } + } + + @Override + public String[] getInfoData() { + ArrayList<String> str = new ArrayList<>(Arrays.asList(super.getInfoData())); + str.add(SCANNER_INFO_BAR); + str.add("Number of Rings: " + EnumChatFormatting.GOLD + ringAmount); + str.add("Total Upgrades Unlocked: " + EnumChatFormatting.GOLD + getTotalActiveUpgrades()); + str.add("Connected Modules: " + EnumChatFormatting.GOLD + moduleHatches.size()); + str.add(SCANNER_INFO_BAR); + return str.toArray(new String[0]); + } + + @Override + public void onRemoval() { + if (moduleHatches != null && !moduleHatches.isEmpty()) { + for (MTEBaseModule module : moduleHatches) { + module.disconnect(); + } + } + super.onRemoval(); + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + buildContext.addSyncedWindow(UPGRADE_TREE_WINDOW_ID, this::createUpgradeTreeWindow); + buildContext.addSyncedWindow(INDIVIDUAL_UPGRADE_WINDOW_ID, this::createIndividualUpgradeWindow); + buildContext.addSyncedWindow(FUEL_CONFIG_WINDOW_ID, this::createFuelConfigWindow); + buildContext.addSyncedWindow(BATTERY_CONFIG_WINDOW_ID, this::createBatteryWindow); + buildContext.addSyncedWindow(MILESTONE_WINDOW_ID, this::createMilestoneWindow); + buildContext.addSyncedWindow(INDIVIDUAL_MILESTONE_WINDOW_ID, this::createIndividualMilestoneWindow); + buildContext.addSyncedWindow(MANUAL_INSERTION_WINDOW_ID, this::createManualInsertionWindow); + buildContext.addSyncedWindow(GENERAL_INFO_WINDOW_ID, this::createGeneralInfoWindow); + buildContext.addSyncedWindow(SPECIAL_THANKS_WINDOW_ID, this::createSpecialThanksWindow); + buildContext.addSyncedWindow(STAR_COSMETICS_WINDOW_ID, this::createStarCosmeticsWindow); + buildContext.addSyncedWindow(STAR_CUSTOM_COLOR_WINDOW_ID, this::createStarCustomColorWindow); + buildContext.addSyncedWindow(STAR_CUSTOM_COLOR_IMPORT_WINDOW_ID, this::createStarColorImportWindow); + + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_SCREEN_BLUE) + .setPos(4, 4) + .setSize(190, 85)) + .widget( + new ButtonWidget().setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(UPGRADE_TREE_WINDOW_ID); + }) + .setSize(16, 16) + .setBackground(() -> { + List<UITexture> button = new ArrayList<>(); + button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + button.add(TecTechUITextures.OVERLAY_BUTTON_ARROW_BLUE_UP); + return button.toArray(new IDrawable[0]); + }) + .addTooltip("Path of Celestial Transcendence") + .setPos(174, 167) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_HEAT_SINK_16x8) + .setPos(174, 183) + .setSize(16, 8)) + .widget(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient()) { + widget.getContext() + .openSyncedWindow(FUEL_CONFIG_WINDOW_ID); + } + }) + .setSize(16, 16) + .setBackground(() -> { + List<UITexture> button = new ArrayList<>(); + button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + button.add(TecTechUITextures.OVERLAY_BUTTON_HEAT_ON); + return button.toArray(new IDrawable[0]); + }) + .addTooltip(translateToLocal("fog.button.fuelconfig.tooltip")) + .setPos(174, 110) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget( + TextWidget.dynamicText(this::storedFuel) + .setDefaultColor(EnumChatFormatting.WHITE) + .setPos(6, 8) + .setSize(74, 34)) + .widget(createPowerSwitchButton()) + .widget(createBatteryButton(builder)) + .widget(createEjectionSwitch(builder)) + .widget(new FakeSyncWidget.BooleanSyncer(() -> getBaseMetaTileEntity().isAllowedToWork(), val -> { + if (val) { + getBaseMetaTileEntity().enableWorking(); + } else { + getBaseMetaTileEntity().disableWorking(); + } + })) + .widget(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient()) { + checkMachine_EM(this.getBaseMetaTileEntity(), null); + } + }) + .setSize(16, 16) + .setBackground(() -> { + List<UITexture> button = new ArrayList<>(); + button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + button.add(TecTechUITextures.OVERLAY_CYCLIC_BLUE); + return button.toArray(new IDrawable[0]); + }) + .addTooltip(translateToLocal("fog.button.structurecheck.tooltip")) + .setPos(8, 91) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient()) { + widget.getContext() + .openSyncedWindow(MILESTONE_WINDOW_ID); + } + }) + .setSize(16, 16) + .setBackground(() -> { + List<UITexture> button = new ArrayList<>(); + button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + button.add(TecTechUITextures.OVERLAY_BUTTON_FLAG); + return button.toArray(new IDrawable[0]); + + }) + .addTooltip(translateToLocal("fog.button.milestones.tooltip")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(174, 91)) + .widget( + new ButtonWidget().setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(GENERAL_INFO_WINDOW_ID); + }) + .setSize(18, 18) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.clickhere")) + .setPos(172, 67) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget( + new ButtonWidget().setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(SPECIAL_THANKS_WINDOW_ID); + }) + .setSize(16, 16) + .addTooltip(translateToLocal("fog.button.thanks.tooltip")) + .setBackground(TecTechUITextures.OVERLAY_BUTTON_HEART) + .setPos(8, 69) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget( + new ButtonWidget().setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(STAR_COSMETICS_WINDOW_ID); + }) + .setSize(16, 16) + .addTooltip(translateToLocal("fog.button.color.tooltip")) + .setBackground(() -> { + List<UITexture> button = new ArrayList<>(); + button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + button.add(TecTechUITextures.OVERLAY_BUTTON_RAINBOW_SPIRAL); + return button.toArray(new IDrawable[0]); + }) + .setPos(152, 91) + .setTooltipShowUpDelay(TOOLTIP_DELAY)); + } + + @Override + public void addGregTechLogo(ModularWindow.Builder builder) { + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_LOGO) + .setSize(18, 18) + .setPos(172, 67)); + } + + @Override + protected ButtonWidget createPowerSwitchButton() { + return ForgeOfGodsUI.createPowerSwitchButton(getBaseMetaTileEntity()); + } + + protected ButtonWidget createEjectionSwitch(IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (upgrades[30]) { + gravitonShardEjection = !gravitonShardEjection; + } + }) + .setPlayClickSound(upgrades[30]) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + if (!upgrades[30]) { + return ret.toArray(new IDrawable[0]); + } + if (gravitonShardEjection) { + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + ret.add(TecTechUITextures.OVERLAY_EJECTION_ON); + } else { + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + ret.add(TecTechUITextures.OVERLAY_EJECTION_LOCKED); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> gravitonShardEjection, val -> gravitonShardEjection = val), + builder) + .setPos(26, 91) + .setSize(16, 16) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(() -> upgrades[30], val -> upgrades[30] = val), builder); + if (upgrades[30]) { + button.addTooltip(translateToLocal("fog.button.ejection.tooltip")); + button.setTooltipShowUpDelay(TOOLTIP_DELAY); + } + return (ButtonWidget) button; + } + + protected Widget createBatteryButton(IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + if (clickData.mouseButton == 0) { + batteryCharging = !batteryCharging; + } else if (clickData.mouseButton == 1 && !widget.isClient() && upgrades[8]) { + widget.getContext() + .openSyncedWindow(BATTERY_CONFIG_WINDOW_ID); + } + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (batteryCharging) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_BATTERY_ON); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_BATTERY_OFF); + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(174, 129) + .setSize(16, 16); + button.addTooltip(translateToLocal("fog.button.battery.tooltip.01")) + .addTooltip(EnumChatFormatting.GRAY + translateToLocal("fog.button.battery.tooltip.02")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> batteryCharging, val -> batteryCharging = val), + builder); + return button; + } + + protected ModularWindow createBatteryWindow(final EntityPlayer player) { + final int WIDTH = 78; + final int HEIGHT = 52; + final int PARENT_WIDTH = getGUIWidth(); + final int PARENT_HEIGHT = getGUIHeight(); + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.setPos( + (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) + .add( + Alignment.BottomRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT)) + .add(WIDTH - 3, 0) + .subtract(0, 10))); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.batteryinfo") + .setPos(3, 4) + .setSize(74, 20)) + .widget( + new NumericWidget().setSetter(val -> maxBatteryCharge = (int) val) + .setGetter(() -> maxBatteryCharge) + .setBounds(1, Integer.MAX_VALUE) + .setDefaultValue(100) + .setScrollValues(1, 4, 64) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setSize(70, 18) + .setPos(4, 25) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)); + return builder.build(); + } + + protected ModularWindow createFuelConfigWindow(final EntityPlayer player) { + final int WIDTH = 78; + final int HEIGHT = 130; + final int PARENT_WIDTH = getGUIWidth(); + final int PARENT_HEIGHT = getGUIHeight(); + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.setPos( + (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) + .add( + Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT)) + .add(WIDTH - 3, 0))); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.fuelconsumption") + .setPos(3, 2) + .setSize(74, 34)) + .widget( + new NumericWidget().setSetter(val -> fuelConsumptionFactor = (int) val) + .setGetter(() -> fuelConsumptionFactor) + .setBounds(1, calculateMaxFuelFactor(this)) + .setDefaultValue(1) + .setScrollValues(1, 4, 64) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setSize(70, 18) + .setPos(4, 35) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD) + .attachSyncer( + new FakeSyncWidget.ListSyncer<>( + () -> Booleans.asList(upgrades), + val -> upgrades = Booleans.toArray(val), + PacketBuffer::writeBoolean, + PacketBuffer::readBoolean), + builder, + (widget, val) -> ((NumericWidget) widget).setMaxValue(calculateMaxFuelFactor(this)))) + .widget( + new DrawableWidget().setDrawable(ModularUITextures.ICON_INFO) + .setPos(64, 24) + .setSize(10, 10) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.0")) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.1")) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.2")) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.3")) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.4")) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.5")) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.fueltype") + .setPos(3, 57) + .setSize(74, 24)) + .widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.fuelusage") + .setPos(3, 100) + .setSize(74, 20)) + .widget( + TextWidget.dynamicText(this::fuelUsage) + .setPos(3, 115) + .setSize(74, 15)) + .widget( + new MultiChildWidget().addChild( + new FluidNameHolderWidget( + () -> MaterialsUEVplus.DimensionallyTranscendentResidue.getFluid(1) + .getUnlocalizedName() + .substring(6), + (String) -> MaterialsUEVplus.DimensionallyTranscendentResidue.getFluid(1) + .getUnlocalizedName()) { + + @Override + public void buildTooltip(List<Text> tooltip) { + FluidStack fluid = createFluidStack(); + addFluidNameInfo(tooltip, fluid); + addAdditionalFluidInfo(tooltip, fluid); + } + }.setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(1, 1) + .setSize(16, 16)) + .addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + selectedFuelType = 0; + }) + .setBackground(() -> { + if (selectedFuelType == 0) { + return new IDrawable[] { TecTechUITextures.SLOT_OUTLINE_GREEN }; + } else { + return new IDrawable[] {}; + } + }) + .setSize(18, 18) + .attachSyncer(new FakeSyncWidget.IntegerSyncer(this::getFuelType, this::setFuelType), builder)) + + .setPos(6, 82) + .setSize(18, 18)) + .widget( + new MultiChildWidget().addChild( + new FluidNameHolderWidget( + () -> MaterialsUEVplus.RawStarMatter.getFluid(1) + .getUnlocalizedName() + .substring(6), + (String) -> MaterialsUEVplus.RawStarMatter.getFluid(1) + .getUnlocalizedName()) { + + @Override + public void buildTooltip(List<Text> tooltip) { + FluidStack fluid = createFluidStack(); + addFluidNameInfo(tooltip, fluid); + addAdditionalFluidInfo(tooltip, fluid); + } + }.setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(1, 1) + .setSize(16, 16)) + .addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + selectedFuelType = 1; + }) + .setBackground(() -> { + if (selectedFuelType == 1) { + return new IDrawable[] { TecTechUITextures.SLOT_OUTLINE_GREEN }; + } else { + return new IDrawable[] {}; + } + }) + .setSize(18, 18)) + .setPos(29, 82) + .setSize(18, 18) + .attachSyncer(new FakeSyncWidget.IntegerSyncer(this::getFuelType, this::setFuelType), builder)) + .widget( + new MultiChildWidget().addChild( + new FluidNameHolderWidget( + () -> MaterialsUEVplus.MagnetohydrodynamicallyConstrainedStarMatter.getMolten(1) + .getUnlocalizedName() + .substring(6), + (String) -> MaterialsUEVplus.MagnetohydrodynamicallyConstrainedStarMatter.getMolten(1) + .getUnlocalizedName()) { + + @Override + public void buildTooltip(List<Text> tooltip) { + FluidStack fluid = createFluidStack(); + addFluidNameInfo(tooltip, fluid); + addAdditionalFluidInfo(tooltip, fluid); + } + }.setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(1, 1) + .setSize(16, 16)) + .addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + selectedFuelType = 2; + }) + .setBackground(() -> { + if (selectedFuelType == 2) { + return new IDrawable[] { TecTechUITextures.SLOT_OUTLINE_GREEN }; + } else { + return new IDrawable[] {}; + } + }) + .setSize(18, 18)) + .setPos(52, 82) + .setSize(18, 18) + .attachSyncer(new FakeSyncWidget.IntegerSyncer(this::getFuelType, this::setFuelType), builder)); + + return builder.build(); + } + + private final int[] milestoneProgress = new int[] { 0, 0, 0, 0 }; + + protected ModularWindow createMilestoneWindow(final EntityPlayer player) { + final int WIDTH = 400; + final int HEIGHT = 300; + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(TecTechUITextures.BACKGROUND_SPACE); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.widget(createMilestoneButton(0, 80, 100, new Pos2d(62, 24))); + builder.widget(createMilestoneButton(1, 70, 98, new Pos2d(263, 25))); + builder.widget(createMilestoneButton(2, 100, 100, new Pos2d(52, 169))); + builder.widget(createMilestoneButton(3, 100, 100, new Pos2d(248, 169))); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.powermilestone") + .setDefaultColor(EnumChatFormatting.GOLD) + .setPos(77, 45) + .setSize(50, 30)); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.recipemilestone") + .setDefaultColor(EnumChatFormatting.GOLD) + .setPos(268, 45) + .setSize(60, 30)); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.fuelmilestone") + .setDefaultColor(EnumChatFormatting.GOLD) + .setPos(77, 190) + .setSize(50, 30)); + builder.widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG.purchasablemilestone") + .setDefaultColor(EnumChatFormatting.GOLD) + .setPos(268, 190) + .setSize(60, 30)); + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) + .setPos(37, 70) + .setSize(130, 7)) + .widget( + new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) + .setPos(233, 70) + .setSize(130, 7)) + .widget( + new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) + .setPos(37, 215) + .setSize(130, 7)) + .widget( + new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) + .setPos(233, 215) + .setSize(130, 7)); + builder.widget( + new ProgressBar().setProgress(() -> powerMilestonePercentage) + .setDirection(ProgressBar.Direction.RIGHT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RED, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(37, 70)) + .widget( + new ProgressBar().setProgress(() -> recipeMilestonePercentage) + .setDirection(ProgressBar.Direction.RIGHT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_PURPLE, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(233, 70)) + .widget( + new ProgressBar().setProgress(() -> fuelMilestonePercentage) + .setDirection(ProgressBar.Direction.RIGHT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BLUE, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(37, 215)) + .widget( + new ProgressBar().setProgress(() -> structureMilestonePercentage) + .setDirection(ProgressBar.Direction.RIGHT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RAINBOW, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(233, 215)) + .widget( + new ProgressBar().setProgress(() -> invertedPowerMilestonePercentage) + .setDirection(ProgressBar.Direction.LEFT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RED_INVERTED, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(37, 70)) + .widget( + new ProgressBar().setProgress(() -> invertedRecipeMilestonePercentage) + .setDirection(ProgressBar.Direction.LEFT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_PURPLE_INVERTED, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(233, 70)) + .widget( + new ProgressBar().setProgress(() -> invertedFuelMilestonePercentage) + .setDirection(ProgressBar.Direction.LEFT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BLUE_INVERTED, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(37, 215)) + .widget( + new ProgressBar().setProgress(() -> invertedStructureMilestonePercentage) + .setDirection(ProgressBar.Direction.LEFT) + .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RAINBOW_INVERTED, 130) + .setSynced(true, false) + .setSize(130, 7) + .setPos(233, 215)) + .widget( + ButtonWidget.closeWindowButton(true) + .setOnClick((data, widget) -> { + if (!widget.isClient()) { + widget.getWindow() + .closeWindow(); + widget.getContext() + .closeWindow(INDIVIDUAL_MILESTONE_WINDOW_ID); + } + }) + .setPos(382, 6)); + return builder.build(); + } + + protected ModularWindow createIndividualMilestoneWindow(final EntityPlayer player) { + final int WIDTH = 150; + final int HEIGHT = 150; + int symbol_width; + int symbol_height; + String milestoneType; + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + UITexture symbol; + switch (currentMilestoneID) { + case 1 -> { + symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CONVERSION; + symbol_width = 54; + symbol_height = 75; + milestoneType = "recipe"; + } + case 2 -> { + symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CATALYST; + symbol_width = 75; + symbol_height = 75; + milestoneType = "fuel"; + } + case 3 -> { + symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_COMPOSITION; + symbol_width = 75; + symbol_height = 75; + milestoneType = "purchasable"; + } + default -> { + symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CHARGE; + symbol_width = 60; + symbol_height = 75; + milestoneType = "power"; + } + } + + builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_WHITE); + builder.setDraggable(true); + builder.widget( + ButtonWidget.closeWindowButton(true) + .setPos(134, 4)) + .widget( + new DrawableWidget().setDrawable(symbol) + .setSize(symbol_width, symbol_height) + .setPos((WIDTH - symbol_width) / 2, (HEIGHT - symbol_height) / 2)) + .widget( + TextWidget.localised("gt.blockmachines.multimachine.FOG." + milestoneType + "milestone") + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setPos(0, 8) + .setSize(150, 15)) + .widget( + TextWidget.dynamicText(this::inversionStatusText) + .setDefaultColor(EnumChatFormatting.AQUA) + .setTextAlignment(Alignment.Center) + .setScale(0.8f) + .setPos(0, 120) + .setSize(150, 15)) + .widget( + TextWidget.dynamicText(() -> totalMilestoneProgress(currentMilestoneID)) + .setScale(0.7f) + .setDefaultColor(EnumChatFormatting.WHITE) + .setTextAlignment(Alignment.Center) + .setPos(5, 30) + .setSize(140, 30)) + .widget( + TextWidget.dynamicText(() -> currentMilestoneLevel(currentMilestoneID)) + .setScale(0.7f) + .setDefaultColor(EnumChatFormatting.WHITE) + .setTextAlignment(Alignment.Center) + .setPos(5, 50) + .setSize(140, 30)) + .widget( + TextWidget.dynamicText(() -> milestoneProgressText(currentMilestoneID)) + .setScale(0.7f) + .setDefaultColor(EnumChatFormatting.WHITE) + .setSize(140, 30) + .setPos(5, 70)) + .widget( + TextWidget.dynamicText(() -> gravitonShardAmountText(currentMilestoneID)) + .setScale(0.7f) + .setDefaultColor(EnumChatFormatting.WHITE) + .setSize(140, 30) + .setPos(5, 90)) + .widget(new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + if (clickData.mouseButton == 0) { + formattingMode = formattingMode.cycle(); + } + }) + .setSize(10, 10) + .addTooltip(translateToLocal("fog.button.formatting.tooltip")) + .setBackground(TecTechUITextures.OVERLAY_CYCLIC_BLUE) + .setPos(5, 135) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .attachSyncer( + new FakeSyncWidget.ByteSyncer( + () -> (byte) formattingMode.ordinal(), + val -> formattingMode = FormattingMode.VALUES[MathHelper + .clamp_int(val, 0, FormattingMode.VALUES.length - 1)]), + builder)); + + return builder.build(); + } + + private int currentMilestoneID = 0; + + private Widget createMilestoneButton(int milestoneID, int width, int height, Pos2d pos) { + return new ButtonWidget().setOnClick((clickData, widget) -> { + currentMilestoneID = milestoneID; + ForgeOfGodsUI.reopenWindow(widget, INDIVIDUAL_MILESTONE_WINDOW_ID); + }) + .setSize(width, height) + .setBackground(() -> switch (milestoneID) { + case 1 -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CONVERSION_GLOW }; + case 2 -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CATALYST_GLOW }; + case 3 -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_COMPOSITION_GLOW }; + default -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CHARGE_GLOW }; + }) + .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.milestoneinfo")) + .setPos(pos) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + } + + private int currentUpgradeID = 0; + private int currentColorCode = 0; + private int currentMilestoneBG = 0; + private int gravitonShardCost = 0; + private final int[][] prereqUpgrades = new int[31][]; + private int[] followupUpgrades = new int[] {}; + private boolean isUpradeSplitStart = false; + private boolean doesCurrentUpgradeRequireExtraMats = false; + private final boolean[] allPrereqRequired = new boolean[31]; + private boolean[] upgrades = new boolean[31]; + private boolean[] materialPaidUpgrades = new boolean[7]; + + protected ModularWindow createUpgradeTreeWindow(final EntityPlayer player) { + final Scrollable scrollable = new Scrollable().setVerticalScroll(); + final int PARENT_WIDTH = 300; + final int PARENT_HEIGHT = 300; + ModularWindow.Builder builder = ModularWindow.builder(PARENT_WIDTH, PARENT_HEIGHT); + + scrollable.widget(createUpgradeConnectorLine(new Pos2d(143, 71), 45, 0, 0, 0, 1)) + .widget(createUpgradeConnectorLine(new Pos2d(124, 124), 60, 27, 0, 1, 2)) + .widget(createUpgradeConnectorLine(new Pos2d(162, 124), 60, 333, 0, 1, 3)) + .widget(createUpgradeConnectorLine(new Pos2d(94, 184), 60, 27, 0, 2, 4)) + .widget(createUpgradeConnectorLine(new Pos2d(130, 184), 60, 336, 0, 2, 5)) + .widget(createUpgradeConnectorLine(new Pos2d(156, 184), 60, 24, 0, 3, 5)) + .widget(createUpgradeConnectorLine(new Pos2d(192, 184), 60, 333, 0, 3, 6)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 251), 45, 0, 0, 5, 7)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 311), 45, 0, 0, 7, 9)) + .widget(createUpgradeConnectorLine(new Pos2d(78, 250), 110, 5, 4, 4, 8)) + .widget(createUpgradeConnectorLine(new Pos2d(110, 290), 80, 40, 4, 7, 8)) + .widget(createUpgradeConnectorLine(new Pos2d(208, 250), 110, 355, 4, 6, 10)) + .widget(createUpgradeConnectorLine(new Pos2d(176, 290), 80, 320, 4, 7, 10)) + .widget(createUpgradeConnectorLine(new Pos2d(100, 355), 80, 313, 0, 8, 11)) + .widget(createUpgradeConnectorLine(new Pos2d(186, 355), 80, 47, 0, 10, 11)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 430), 48, 0, 2, 11, 13)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 490), 48, 0, 2, 13, 18)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 550), 48, 0, 2, 18, 21)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 610), 48, 0, 2, 21, 23)) + .widget(createUpgradeConnectorLine(new Pos2d(110, 410), 80, 40, 1, 11, 12)) + .widget(createUpgradeConnectorLine(new Pos2d(83, 490), 48, 0, 1, 12, 17)) + .widget(createUpgradeConnectorLine(new Pos2d(83, 550), 48, 0, 1, 17, 20)) + .widget(createUpgradeConnectorLine(new Pos2d(101, 590), 80, 320, 1, 20, 23)) + .widget(createUpgradeConnectorLine(new Pos2d(53, 536), 35, 45, 1, 17, 16)) + .widget(createUpgradeConnectorLine(new Pos2d(176, 410), 80, 320, 3, 11, 14)) + .widget(createUpgradeConnectorLine(new Pos2d(203, 490), 48, 0, 3, 14, 19)) + .widget(createUpgradeConnectorLine(new Pos2d(203, 550), 48, 0, 3, 19, 22)) + .widget(createUpgradeConnectorLine(new Pos2d(185, 590), 80, 40, 3, 22, 23)) + .widget(createUpgradeConnectorLine(new Pos2d(233, 476), 35, 315, 3, 14, 15)) + .widget(createUpgradeConnectorLine(new Pos2d(143, 670), 48, 0, 0, 23, 24)) + .widget(createUpgradeConnectorLine(new Pos2d(101, 707), 75, 62.3f, 0, 24, 25)) + .widget(createUpgradeConnectorLine(new Pos2d(53, 772), 78, 0, 0, 25, 26)) + .widget(createUpgradeConnectorLine(new Pos2d(95, 837), 75, 297.7f, 0, 26, 27)) + .widget(createUpgradeConnectorLine(new Pos2d(191, 837), 75, 62.3f, 0, 27, 28)) + .widget(createUpgradeConnectorLine(new Pos2d(233, 772), 78, 0, 0, 28, 29)) + .widget(createUpgradeConnectorLine(new Pos2d(191, 747), 75, 62.3f, 0, 29, 30)); + + scrollable + .widget( + createUpgradeBox( + 0, + 0, + 3, + new int[] {}, + false, + new int[] { 1 }, + false, + true, + 0, + new Pos2d(126, 56), + scrollable)) + .widget( + createUpgradeBox( + 1, + 0, + 1, + new int[] { 0 }, + false, + new int[] { 2, 3 }, + false, + false, + 1, + new Pos2d(126, 116), + scrollable)) + .widget( + createUpgradeBox( + 2, + 0, + 2, + new int[] { 1 }, + false, + new int[] { 4, 5 }, + false, + false, + 1, + new Pos2d(96, 176), + scrollable)) + .widget( + createUpgradeBox( + 3, + 0, + 2, + new int[] { 1 }, + false, + new int[] { 5, 6 }, + false, + false, + 1, + new Pos2d(156, 176), + scrollable)) + .widget( + createUpgradeBox( + 4, + 0, + 0, + new int[] { 2 }, + false, + new int[] { 8 }, + false, + false, + 1, + new Pos2d(66, 236), + scrollable)) + .widget( + createUpgradeBox( + 5, + 0, + 3, + new int[] { 2, 3 }, + false, + new int[] { 7 }, + false, + true, + 1, + new Pos2d(126, 236), + scrollable)) + .widget( + createUpgradeBox( + 6, + 0, + 1, + new int[] { 3 }, + false, + new int[] { 10 }, + false, + false, + 1, + new Pos2d(186, 236), + scrollable)) + .widget( + createUpgradeBox( + 7, + 0, + 3, + new int[] { 5 }, + false, + new int[] { 8, 9, 10 }, + false, + true, + 2, + new Pos2d(126, 296), + scrollable)) + .widget( + createUpgradeBox( + 8, + 4, + 0, + new int[] { 4, 7 }, + true, + new int[] { 11 }, + false, + false, + 2, + new Pos2d(56, 356), + scrollable)) + .widget( + createUpgradeBox( + 9, + 0, + 2, + new int[] { 7 }, + false, + new int[] {}, + false, + false, + 2, + new Pos2d(126, 356), + scrollable)) + .widget( + createUpgradeBox( + 10, + 4, + 1, + new int[] { 6, 7 }, + true, + new int[] { 11 }, + false, + false, + 2, + new Pos2d(196, 356), + scrollable)) + .widget( + createUpgradeBox( + 11, + 0, + 3, + new int[] { 8, 10 }, + false, + new int[] { 12, 13, 14 }, + false, + true, + 2, + new Pos2d(126, 416), + scrollable)) + .widget( + createUpgradeBox( + 12, + 1, + 2, + new int[] { 11 }, + false, + new int[] { 17 }, + true, + false, + 3, + new Pos2d(66, 476), + scrollable)) + .widget( + createUpgradeBox( + 13, + 2, + 1, + new int[] { 11 }, + false, + new int[] { 18 }, + true, + false, + 3, + new Pos2d(126, 476), + scrollable)) + .widget( + createUpgradeBox( + 14, + 3, + 0, + new int[] { 11 }, + false, + new int[] { 15, 19 }, + true, + false, + 3, + new Pos2d(186, 476), + scrollable)) + .widget( + createUpgradeBox( + 15, + 3, + 1, + new int[] { 14 }, + false, + new int[] {}, + false, + false, + 4, + new Pos2d(246, 496), + scrollable)) + .widget( + createUpgradeBox( + 16, + 1, + 1, + new int[] { 17 }, + false, + new int[] {}, + false, + false, + 4, + new Pos2d(6, 556), + scrollable)) + .widget( + createUpgradeBox( + 17, + 1, + 0, + new int[] { 12 }, + false, + new int[] { 16, 20 }, + false, + false, + 3, + new Pos2d(66, 536), + scrollable)) + .widget( + createUpgradeBox( + 18, + 2, + 1, + new int[] { 13 }, + false, + new int[] { 21 }, + false, + false, + 3, + new Pos2d(126, 536), + scrollable)) + .widget( + createUpgradeBox( + 19, + 3, + 0, + new int[] { 14 }, + false, + new int[] { 22 }, + false, + false, + 3, + new Pos2d(186, 536), + scrollable)) + .widget( + createUpgradeBox( + 20, + 1, + 0, + new int[] { 17 }, + false, + new int[] { 23 }, + false, + false, + 3, + new Pos2d(66, 596), + scrollable)) + .widget( + createUpgradeBox( + 21, + 2, + 1, + new int[] { 18 }, + false, + new int[] { 23 }, + false, + false, + 3, + new Pos2d(126, 596), + scrollable)) + .widget( + createUpgradeBox( + 22, + 3, + 1, + new int[] { 19 }, + false, + new int[] { 23 }, + false, + false, + 3, + new Pos2d(186, 596), + scrollable)) + .widget( + createUpgradeBox( + 23, + 0, + 0, + new int[] { 20, 21, 22 }, + false, + new int[] { 24 }, + false, + false, + 4, + new Pos2d(126, 656), + scrollable)) + .widget( + createUpgradeBox( + 24, + 0, + 1, + new int[] { 23 }, + false, + new int[] { 25 }, + false, + false, + 5, + new Pos2d(126, 718), + scrollable)) + .widget( + createUpgradeBox( + 25, + 0, + 1, + new int[] { 24 }, + false, + new int[] { 26 }, + false, + false, + 6, + new Pos2d(36, 758), + scrollable)) + .widget( + createUpgradeBox( + 26, + 0, + 3, + new int[] { 25 }, + false, + new int[] { 27 }, + false, + true, + 7, + new Pos2d(36, 848), + scrollable)) + .widget( + createUpgradeBox( + 27, + 0, + 2, + new int[] { 26 }, + false, + new int[] { 28 }, + false, + false, + 8, + new Pos2d(126, 888), + scrollable)) + .widget( + createUpgradeBox( + 28, + 0, + 0, + new int[] { 27 }, + false, + new int[] { 29 }, + false, + false, + 9, + new Pos2d(216, 848), + scrollable)) + .widget( + createUpgradeBox( + 29, + 0, + 3, + new int[] { 28 }, + false, + new int[] { 30 }, + false, + true, + 10, + new Pos2d(216, 758), + scrollable)) + .widget( + createUpgradeBox( + 30, + 0, + 3, + new int[] { 29 }, + false, + new int[] {}, + false, + true, + 12, + new Pos2d(126, 798), + scrollable)) + .widget( + new MultiChildWidget().addChild( + new ButtonWidget().setOnClick(((clickData, widget) -> secretUpgrade = !secretUpgrade)) + .setSize(40, 15) + .setBackground(() -> { + if (secretUpgrade) { + return new IDrawable[] { TecTechUITextures.BUTTON_SPACE_PRESSED_32x16 }; + } + return new IDrawable[0]; + }) + .addTooltip(translateToLocal("fog.upgrade.tt.secret")) + .setTooltipShowUpDelay(20)) + .addChild( + new TextWidget(translateToLocal("fog.upgrade.tt.short.secret")).setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setSize(34, 9) + .setPos(3, 4) + .setEnabled((widget -> secretUpgrade))) + .addChild( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_BLUE_OPAQUE) + .setEnabled(widget -> secretUpgrade) + .setPos(40, 4) + .setSize(20, 6)) + .setPos(new Pos2d(66, 56))) + .widget(new TextWidget("").setPos(0, 945)); + + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_STAR) + .setPos(0, 0) + .setSize(300, 300)) + .widget( + scrollable.setSize(292, 292) + .setPos(4, 4)) + .widget( + ButtonWidget.closeWindowButton(true) + .setOnClick((data, widget) -> { + if (!widget.isClient()) { + widget.getWindow() + .closeWindow(); + widget.getContext() + .closeWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); + } + }) + .setPos(282, 4)); + if (ConfigHandler.debug.DEBUG_MODE) { + builder.widget(new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + upgrades = new boolean[31]; + materialPaidUpgrades = new boolean[7]; + }) + .setSize(40, 15) + .setBackground(GTUITextures.BUTTON_STANDARD) + .addTooltip(translateToLocal("fog.debug.resetbutton.tooltip")) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .addChild( + new TextWidget(translateToLocal("fog.debug.resetbutton.text")).setTextAlignment(Alignment.Center) + .setScale(0.57f) + .setMaxWidth(36) + .setPos(3, 3)) + .addChild( + new NumericWidget().setSetter(val -> gravitonShardsAvailable = (int) val) + .setGetter(() -> gravitonShardsAvailable) + .setBounds(0, 112) + .setDefaultValue(0) + .setScrollValues(1, 4, 64) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setSize(25, 18) + .setPos(4, 16) + .addTooltip(translateToLocal("fog.debug.gravitonshardsetter.tooltip")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)) + .addChild( + new ButtonWidget().setOnClick((clickData, widget) -> Arrays.fill(upgrades, true)) + .setSize(40, 15) + .setBackground(GTUITextures.BUTTON_STANDARD) + .addTooltip(translateToLocal("fog.debug.unlockall.text")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(0, 35)) + .addChild( + new TextWidget(translateToLocal("fog.debug.unlockall.text")).setTextAlignment(Alignment.Center) + .setScale(0.57f) + .setMaxWidth(36) + .setPos(3, 38)) + .setPos(4, 4)); + + } + return builder.build(); + } + + protected ModularWindow createIndividualUpgradeWindow(final EntityPlayer player) { + UITexture background; + UITexture overlay; + UITexture milestoneSymbol; + float widthRatio; + switch (currentColorCode) { + case 1 -> { + background = TecTechUITextures.BACKGROUND_GLOW_PURPLE; + overlay = TecTechUITextures.PICTURE_OVERLAY_PURPLE; + } + case 2 -> { + background = TecTechUITextures.BACKGROUND_GLOW_ORANGE; + overlay = TecTechUITextures.PICTURE_OVERLAY_ORANGE; + } + case 3 -> { + background = TecTechUITextures.BACKGROUND_GLOW_GREEN; + overlay = TecTechUITextures.PICTURE_OVERLAY_GREEN; + } + case 4 -> { + background = TecTechUITextures.BACKGROUND_GLOW_RED; + overlay = TecTechUITextures.PICTURE_OVERLAY_RED; + } + default -> { + background = TecTechUITextures.BACKGROUND_GLOW_BLUE; + overlay = TecTechUITextures.PICTURE_OVERLAY_BLUE; + } + } + switch (currentMilestoneBG) { + case 1 -> { + milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CONVERSION; + widthRatio = 0.72f; + } + case 2 -> { + milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CATALYST; + widthRatio = 1f; + } + case 3 -> { + milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_COMPOSITION; + widthRatio = 1f; + } + default -> { + milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CHARGE; + widthRatio = 0.8f; + } + } + int WIDTH = 250; + int HEIGHT = 250; + int LORE_POS = 110; + if (currentUpgradeID == 0 || currentUpgradeID == 30) { + WIDTH = 300; + HEIGHT = 300; + LORE_POS = 85; + } + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT) + .setBackground(background) + .widget( + ButtonWidget.closeWindowButton(true) + .setPos(WIDTH - 15, 3)) + .widget( + new DrawableWidget().setDrawable(milestoneSymbol) + .setPos((int) ((1 - widthRatio / 2) * WIDTH / 2), HEIGHT / 4) + .setSize((int) (WIDTH / 2 * widthRatio), HEIGHT / 2)) + .widget( + new DrawableWidget().setDrawable(overlay) + .setPos(WIDTH / 4, HEIGHT / 4) + .setSize(WIDTH / 2, HEIGHT / 2)) + .widget( + new MultiChildWidget() + .addChild( + new TextWidget(translateToLocal("fog.upgrade.tt." + (currentUpgradeID))) + .setTextAlignment(Alignment.Center) + .setDefaultColor(EnumChatFormatting.GOLD) + .setSize(WIDTH - 15, 30) + .setPos(9, 5)) + .addChild( + new TextWidget(translateToLocal("fog.upgrade.text." + (currentUpgradeID))) + .setTextAlignment(Alignment.Center) + .setDefaultColor(EnumChatFormatting.WHITE) + .setSize(WIDTH - 15, LORE_POS - 30) + .setPos(9, 30)) + .addChild( + new TextWidget( + EnumChatFormatting.ITALIC + translateToLocal("fog.upgrade.lore." + (currentUpgradeID))) + .setTextAlignment(Alignment.Center) + .setDefaultColor(0xbbbdbd) + .setSize(WIDTH - 15, (int) (HEIGHT * 0.9) - LORE_POS) + .setPos(9, LORE_POS)) + .addChild( + new TextWidget( + translateToLocal("gt.blockmachines.multimachine.FOG.shardcost") + " " + + EnumChatFormatting.BLUE + + gravitonShardCost).setTextAlignment(Alignment.Center) + .setScale(0.7f) + .setMaxWidth(70) + .setDefaultColor(0x9c9c9c) + .setPos(11, HEIGHT - 25)) + .addChild( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.availableshards")) + .setTextAlignment(Alignment.Center) + .setScale(0.7f) + .setMaxWidth(90) + .setDefaultColor(0x9c9c9c) + .setPos(WIDTH - 87, HEIGHT - 25)) + .addChild( + TextWidget.dynamicText(this::gravitonShardAmount) + .setTextAlignment(Alignment.Center) + .setScale(0.7f) + .setMaxWidth(90) + .setDefaultColor(0x9c9c9c) + .setPos(WIDTH - 27, HEIGHT - 18))) + .setSize(WIDTH, HEIGHT) + + .widget(new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!upgrades[currentUpgradeID]) { + completeUpgrade(); + } else { + respecUpgrade(); + } + }) + .setSize(40, 15) + .setBackground(() -> { + if (upgrades[currentUpgradeID]) { + return new IDrawable[] { GTUITextures.BUTTON_STANDARD_PRESSED }; + } else { + return new IDrawable[] { GTUITextures.BUTTON_STANDARD }; + } + }) + .dynamicTooltip(this::constructionStatus) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .addChild( + TextWidget.dynamicText(this::constructionStatusText) + .setTextAlignment(Alignment.Center) + .setScale(0.7f) + .setMaxWidth(36) + .setPos(3, 5)) + .setPos(WIDTH / 2 - 21, (int) (HEIGHT * 0.9))); + if (Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .contains(currentUpgradeID)) { + builder.widget(createMaterialInputButton(currentUpgradeID, WIDTH / 2 - 40, (int) (HEIGHT * 0.9), builder)); + } + return builder.build(); + } + + private void completeUpgrade() { + int unlockedPrereqUpgrades = 0; + int unlockedSplitUpgrades = 0; + if (!upgrades[currentUpgradeID]) { + for (int prereqUpgrade : prereqUpgrades[currentUpgradeID]) { + if (upgrades[prereqUpgrade]) { + unlockedPrereqUpgrades++; + } + } + if (!doesCurrentUpgradeRequireExtraMats + || materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(currentUpgradeID)]) { + if (allPrereqRequired[currentUpgradeID]) { + if (unlockedPrereqUpgrades == prereqUpgrades[currentUpgradeID].length + && gravitonShardsAvailable >= gravitonShardCost) { + gravitonShardsAvailable -= gravitonShardCost; + gravitonShardsSpent += gravitonShardCost; + upgrades[currentUpgradeID] = true; + } + } else if (unlockedPrereqUpgrades > 0 || prereqUpgrades[currentUpgradeID].length == 0) { + if (isUpradeSplitStart) { + for (int splitUpgrade : FIRST_SPLIT_UPGRADES) { + if (upgrades[splitUpgrade]) { + unlockedSplitUpgrades++; + } + } + unlockedSplitUpgrades -= (ringAmount - 1); + } + if (unlockedSplitUpgrades <= 0 && gravitonShardsAvailable >= gravitonShardCost) { + gravitonShardsAvailable -= gravitonShardCost; + gravitonShardsSpent += gravitonShardCost; + upgrades[currentUpgradeID] = true; + } + } + } + } + } + + private void respecUpgrade() { + int unlockedFollowupUpgrades = 0; + int unlockedNeighboringUpgrades = 0; + boolean doesFollowupRequireAllPrereqs = false; + boolean canFollowupSpareAConnection = true; + + for (int followupUpgrade : followupUpgrades) { + if (upgrades[followupUpgrade]) { + unlockedFollowupUpgrades++; + if (allPrereqRequired[followupUpgrade]) { + doesFollowupRequireAllPrereqs = true; + } + int[] currentPrereqs = prereqUpgrades[followupUpgrade]; + for (int prereqUpgrade : currentPrereqs) { + if (upgrades[prereqUpgrade]) { + unlockedNeighboringUpgrades++; + } + } + if (unlockedNeighboringUpgrades <= 1) { + canFollowupSpareAConnection = false; + } + } + + unlockedNeighboringUpgrades = 0; + } + + if (!doesFollowupRequireAllPrereqs && followupUpgrades.length > 0 && canFollowupSpareAConnection) { + unlockedFollowupUpgrades = 0; + } + + if (unlockedFollowupUpgrades == 0) { + gravitonShardsAvailable += gravitonShardCost; + gravitonShardsSpent -= gravitonShardCost; + upgrades[currentUpgradeID] = false; + + if (currentUpgradeID == 30) { + gravitonShardEjection = false; + } + } + } + + private Widget createMaterialInputButton(int upgradeID, int xCoord, int yCoord, IWidgetBuilder<?> builder) { + return new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient() && doesCurrentUpgradeRequireExtraMats) { + ModularUIContext ctx = widget.getContext(); + ctx.openSyncedWindow(MANUAL_INSERTION_WINDOW_ID); + ctx.closeWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); + ctx.closeWindow(UPGRADE_TREE_WINDOW_ID); + } + }) + .setPlayClickSound(doesCurrentUpgradeRequireExtraMats) + .setBackground(() -> { + if (doesCurrentUpgradeRequireExtraMats) { + if (materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(upgradeID)]) { + return new IDrawable[] { TecTechUITextures.BUTTON_BOXED_CHECKMARK_18x18 }; + } else { + return new IDrawable[] { TecTechUITextures.BUTTON_BOXED_EXCLAMATION_POINT_18x18 }; + } + } else { + return new IDrawable[] { GTUITextures.TRANSPARENT }; + } + }) + .setPos(xCoord, yCoord) + .setSize(15, 15) + .dynamicTooltip(this::upgradeMaterialRequirements) + .addTooltip(EnumChatFormatting.GRAY + translateToLocal("fog.button.materialrequirements.tooltip.clickhere")) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer( + () -> materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(upgradeID)], + val -> materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(upgradeID)] = val), + builder); + } + + /** + * @param upgradeID ID of the upgrade + * @param colorCode Number deciding which colored background to use, 0 for blue, 1 for purple, 2 for + * orange and 3 for green + * @param milestone Number deciding which milestone symbol to display in the background, 0 for charge, + * 1 for conversion, 2 for catalyst and 3 for composition + * @param prerequisiteUpgradeIDs IDs of the prior upgrades directly connected to the current one + * @param requireAllPrerequisites Decides how many connected prerequisite upgrades have to be unlocked to be able to + * unlock this one. True means ALL, False means AT LEAST ONE + * @param followingUpgradeIDs IDs of the following upgrades directly connected to the current one + * @param isStartOfSplit Whether this upgrade is one of the initial split upgrades + * @param requiresExtraMaterials Whether this upgrade requires materials other than graviton shards to unlock + * @param shardCost How many graviton shards are needed to unlock this upgrade + * @param pos Position of the upgrade inside the scrollableWidget + */ + private Widget createUpgradeBox(int upgradeID, int colorCode, int milestone, int[] prerequisiteUpgradeIDs, + boolean requireAllPrerequisites, int[] followingUpgradeIDs, boolean isStartOfSplit, + boolean requiresExtraMaterials, int shardCost, Pos2d pos, IWidgetBuilder<?> builder) { + prereqUpgrades[upgradeID] = prerequisiteUpgradeIDs; + allPrereqRequired[upgradeID] = requireAllPrerequisites; + return new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + currentUpgradeID = upgradeID; + currentColorCode = colorCode; + currentMilestoneBG = milestone; + gravitonShardCost = shardCost; + followupUpgrades = followingUpgradeIDs; + isUpradeSplitStart = isStartOfSplit; + doesCurrentUpgradeRequireExtraMats = requiresExtraMaterials; + if (clickData.mouseButton == 0) { + if (clickData.shift) { + if (!doesCurrentUpgradeRequireExtraMats + || materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(currentUpgradeID)]) { + completeUpgrade(); + } else if (!widget.isClient()) { + ModularUIContext ctx = widget.getContext(); + ctx.openSyncedWindow(MANUAL_INSERTION_WINDOW_ID); + ctx.closeWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); + ctx.closeWindow(UPGRADE_TREE_WINDOW_ID); + } + } else { + ForgeOfGodsUI.reopenWindow(widget, INDIVIDUAL_UPGRADE_WINDOW_ID); + } + } else if (clickData.mouseButton == 1) { + respecUpgrade(); + } + }) + .setSize(40, 15) + .setBackground(() -> { + if (upgrades[upgradeID]) { + return new IDrawable[] { TecTechUITextures.BUTTON_SPACE_PRESSED_32x16 }; + } else { + return new IDrawable[] { TecTechUITextures.BUTTON_SPACE_32x16 }; + } + }) + .addTooltip(translateToLocal("fog.upgrade.tt." + upgradeID)) + .setTooltipShowUpDelay(TOOLTIP_DELAY)) + .addChild( + new TextWidget(translateToLocal("fog.upgrade.tt.short." + upgradeID)).setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setSize(34, 9) + .setPos(3, 4)) + .setPos(pos) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(() -> upgrades[upgradeID], val -> upgrades[upgradeID] = val), + builder); + } + + private Widget createUpgradeConnectorLine(Pos2d pos, int length, float rotationAngle, int colorCode, + int startUpgradeID, int endUpgradeID) { + return new DrawableWidget() + .setDrawable( + () -> (upgrades[startUpgradeID] && upgrades[endUpgradeID]) + ? coloredLine(colorCode, true).withRotationDegree(rotationAngle) + : coloredLine(colorCode, false).withRotationDegree(rotationAngle)) + .setPos(pos) + .setSize(6, length); + } + + private IDrawable coloredLine(int colorCode, boolean opaque) { + IDrawable line; + switch (colorCode) { + case 1 -> { + line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_PURPLE_OPAQUE + : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_PURPLE; + } + case 2 -> { + line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_ORANGE_OPAQUE + : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_ORANGE; + } + case 3 -> { + line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_GREEN_OPAQUE + : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_GREEN; + } + case 4 -> { + line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_RED_OPAQUE + : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_RED; + } + default -> { + line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_BLUE_OPAQUE + : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_BLUE; + } + } + return line; + } + + protected ModularWindow createManualInsertionWindow(final EntityPlayer player) { + ItemStack[] inputs = godforgeUpgradeMats.get(currentUpgradeID); + final int WIDTH = 189; + final int HEIGHT = 106; + final int PARENT_WIDTH = getGUIWidth(); + final int PARENT_HEIGHT = getGUIHeight(); + final MultiChildWidget columns = new MultiChildWidget(); + final DynamicPositionedColumn column1 = new DynamicPositionedColumn(); + final DynamicPositionedColumn column2 = new DynamicPositionedColumn(); + final DynamicPositionedColumn column3 = new DynamicPositionedColumn(); + final DynamicPositionedColumn column4 = new DynamicPositionedColumn(); + final DynamicPositionedColumn column5 = new DynamicPositionedColumn(); + final DynamicPositionedColumn column6 = new DynamicPositionedColumn(); + + for (int i = 0; i < 16; i++) { + inputSlotHandler.insertItem(i, storedUpgradeWindowItems[i], false); + storedUpgradeWindowItems[i] = null; + } + + List<DynamicPositionedColumn> columnList = Arrays.asList(column1, column2, column3, column4, column5, column6); + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.setPos( + (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) + .add(Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT))) + .subtract(5, 0) + .add(0, 4)); + builder.widget( + SlotGroup.ofItemHandler(inputSlotHandler, 4) + .startFromSlot(0) + .endAtSlot(15) + .phantom(false) + .background(getGUITextureSet().getItemSlot()) + .build() + .setPos(112, 6)); + builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient()) { + widget.getWindow() + .closeWindow(); + widget.getContext() + .openSyncedWindow(UPGRADE_TREE_WINDOW_ID); + widget.getContext() + .openSyncedWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); + } + }) + .setBackground(ModularUITextures.VANILLA_BACKGROUND, new Text("x")) + .setPos(179, 0) + .setSize(10, 10)); + builder.widget(new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!widget.isClient()) { + ArrayList<ItemStack> list = new ArrayList<>(inputSlotHandler.getStacks()); + list.removeIf(Objects::isNull); + int foundInputs = 0; + int[] foundInputIndices = new int[inputs.length]; + for (ItemStack inputStack : list) { + for (ItemStack requiredStack : inputs) { + if (ItemStack.areItemStacksEqual(requiredStack, inputStack)) { + foundInputIndices[foundInputs] = inputSlotHandler.getStacks() + .indexOf(inputStack); + foundInputs++; + } + } + } + if (foundInputs == inputs.length) { + for (int index : foundInputIndices) { + inputSlotHandler.extractItem(index, inputSlotHandler.getStackInSlot(index).stackSize, false); + } + materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(currentUpgradeID)] = true; + } + } + }) + .setPlayClickSound(true) + .setBackground(GTUITextures.BUTTON_STANDARD) + .setSize(179, 18)) + .addChild( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.consumeUpgradeMats")) + .setTextAlignment(Alignment.Center) + .setScale(0.75f) + .setPos(0, 1) + .setSize(179, 18)) + .setPos(5, 82) + .setSize(179, 16)); + + IItemHandlerModifiable upgradeMatsHandler = new ItemStackHandler(12); + int uniqueItems = inputs.length; + for (int i = 0; i < 12; i++) { + int cleanDiv4 = i / 4; + if (i < uniqueItems) { + ItemStack stack = inputs[i]; + if (stack != null) { + upgradeMatsHandler.setStackInSlot(i, stack.copy()); + } + builder.widget( + new DrawableWidget().setDrawable(GTUITextures.BUTTON_STANDARD_PRESSED) + .setPos(5 + cleanDiv4 * 36, 6 + i % 4 * 18) + .setSize(18, 18)); + columnList.get(cleanDiv4) + .addChild( + new SlotWidget(upgradeMatsHandler, i).setAccess(false, false) + .setRenderStackSize(false) + .disableInteraction()); + columnList.get(cleanDiv4 + 3) + .addChild( + new TextWidget("x" + inputs[i].stackSize).setTextAlignment(Alignment.CenterLeft) + .setScale(0.8f) + .setSize(18, 8)); + } else { + builder.widget( + new DrawableWidget().setDrawable(GTUITextures.BUTTON_STANDARD_DISABLED) + .setPos(5 + cleanDiv4 * 36, 6 + i % 4 * 18) + .setSize(18, 18)); + } + } + + int counter = 0; + for (DynamicPositionedColumn column : columnList) { + int spacing = 0; + int xCord = counter * 36; + int yCord = 0; + if (counter > 2) { + spacing = 10; + xCord = 19 + (counter - 3) * 36; + yCord = 5; + } + columns.addChild( + column.setSpace(spacing) + .setAlignment(MainAxisAlignment.SPACE_BETWEEN) + .setSize(16, 72) + .setPos(xCord, yCord)); + counter++; + } + + builder.widget( + columns.setSize(108, 72) + .setPos(5, 6)); + + return builder.build(); + } + + protected ModularWindow createGeneralInfoWindow(final EntityPlayer player) { + return ForgeOfGodsUI.createGeneralInfoWindow(() -> inversion, val -> inversion = val); + } + + protected ModularWindow createSpecialThanksWindow(final EntityPlayer player) { + final int WIDTH = 200; + final int HEIGHT = 200; + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + + builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_RAINBOW); + builder.setDraggable(true); + builder.widget( + ButtonWidget.closeWindowButton(true) + .setPos(184, 4)) + .widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_THANKS) + .setPos(50, 50) + .setSize(100, 100)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.contributors")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setScale(1f) + .setPos(0, 5) + .setSize(200, 15)) + .widget( + new TextWidget( + EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.lead")) + .setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 30) + .setSize(60, 10)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.cloud")).setScale(0.8f) + .setDefaultColor(EnumChatFormatting.AQUA) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 40) + .setSize(60, 10)) + .widget( + new TextWidget( + EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.programming")) + .setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 55) + .setSize(60, 10)) + .widget( + new TextWidget( + translateToLocal("gt.blockmachines.multimachine.FOG.serenibyss") + " " + + EnumChatFormatting.DARK_AQUA + + translateToLocal("gt.blockmachines.multimachine.FOG.teg")).setScale(0.8f) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 67) + .setSize(60, 10)) + .widget( + new TextWidget( + EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.textures")) + .setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 85) + .setSize(100, 10)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.ant")).setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GREEN) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 95) + .setSize(60, 10)) + .widget( + new TextWidget( + EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.rendering")) + .setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 110) + .setSize(100, 10)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.bucket")).setScale(0.8f) + .setDefaultColor(EnumChatFormatting.WHITE) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 120) + .setSize(60, 10)) + .widget( + new TextWidget( + EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.lore")) + .setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 135) + .setSize(100, 10)) + .widget( + delenoName().setSpace(-1) + .setAlignment(MainAxisAlignment.SPACE_BETWEEN) + .setPos(7, 145) + .setSize(60, 10)) + .widget( + new TextWidget( + EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.playtesting")) + .setScale(0.8f) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 160) + .setSize(100, 10)) + .widget( + new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.misi")).setScale(0.8f) + .setDefaultColor(0xffc26f) + .setTextAlignment(Alignment.CenterLeft) + .setPos(7, 170) + .setSize(60, 10)) + .widget( + new TextWidget(EnumChatFormatting.ITALIC + translateToLocal("gt.blockmachines.multimachine.FOG.thanks")) + .setScale(0.8f) + .setDefaultColor(0xbbbdbd) + .setTextAlignment(Alignment.Center) + .setPos(90, 140) + .setSize(100, 60)); + return builder.build(); + } + + protected ModularWindow createStarCosmeticsWindow(final EntityPlayer player) { + final int WIDTH = 200; + final int HEIGHT = 200; + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_WHITE); + builder.setDraggable(true); + + // Syncers + builder.widget(new FakeSyncWidget.StringSyncer(() -> selectedStarColor, val -> selectedStarColor = val)); + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> rotationSpeed, val -> rotationSpeed = val)); + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> starSize, val -> starSize = val)); + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> editingStarIndex, val -> editingStarIndex = val)); + builder.widget(starColors.getSyncer()); + + // Exit button and header + builder.widget( + ButtonWidget.closeWindowButton(true) + .setPos(184, 4)) + .widget( + new TextWidget(translateToLocal("fog.cosmetics.header")).setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setScale(1f) + .setPos(0, 5) + .setSize(200, 15)); + + // Color options + // Header + builder.widget( + new TextWidget(EnumChatFormatting.UNDERLINE + translateToLocal("fog.cosmetics.color")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(9, 25) + .setSize(60, 10)); + + // Current presets + for (int i = 0; i < 7; i++) { + MultiChildWidget widget = createColorGroup(i); + widget.setPos(8, 45 + i * 20); + builder.widget(widget); + } + + // Option to add a new preset, only shown if there is room available + MultiChildWidget newPreset = new MultiChildWidget(); + Function<Widget, Boolean> newPresetEnabled = $ -> !starColors.isFull(); + newPreset.setSize(18, 80); + newPreset.setPosProvider(($, $$, $$$) -> new Pos2d(8, 45 + starColors.size() * 20)); + newPreset.setEnabled(newPresetEnabled); + + // New preset button + newPreset.addChild(new ButtonWidget().setOnClick((data, widget) -> { + if (!widget.isClient()) { + editingStarIndex = -1; + openCustomStarColorWindowFresh(widget, null); + } + }) + .setPlayClickSound(true) + .setBackground(GTUITextures.BUTTON_STANDARD) + .addTooltip(translateToLocal("fog.cosmetics.starcolor")) + .setSize(16, 16) + .setPos(0, 0) + .setEnabled(newPresetEnabled)); + + // Text overlaid on the above button + newPreset.addChild( + new TextWidget("+").setDefaultColor(EnumChatFormatting.DARK_GRAY) + .setTextAlignment(Alignment.Center) + .setSize(16, 16) + .setPos(0, 0) + .setEnabled(newPresetEnabled)); + + // Text for what this button does + newPreset.addChild( + new TextWidget(translateToLocal("fog.cosmetics.customstarcolor")).setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setSize(60, 18) + .setPos(20, 0) + .setEnabled(newPresetEnabled)); + + builder.widget(newPreset); + + // Miscellaneous options not related to color settings + builder + .widget( + new TextWidget(EnumChatFormatting.UNDERLINE + translateToLocal("fog.cosmetics.misc")) + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(120, 25) + .setSize(80, 10)) + .widget( + TextWidget.localised("fog.cosmetics.spin") + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(120, 45) + .setSize(60, 18)) + .widget( + new NumericWidget().setSetter(val -> rotationSpeed = (int) val) + .setGetter(() -> rotationSpeed) + .setBounds(0, 100) + .setDefaultValue(5) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setSize(35, 18) + .setPos(155, 45) + .addTooltip(translateToLocal("fog.cosmetics.onlyintegers")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)) + .widget( + TextWidget.localised("fog.cosmetics.size") + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.CenterLeft) + .setPos(120, 65) + .setSize(60, 18)) + .widget( + new NumericWidget().setSetter(val -> starSize = (int) val) + .setGetter(() -> starSize) + .setBounds(1, 40) + .setDefaultValue(20) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setSize(35, 18) + .setPos(155, 65) + .addTooltip(translateToLocal("fog.cosmetics.onlyintegers")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)); + + return builder.build(); + } + + private MultiChildWidget createColorGroup(final int index) { + final int textWidth = 60; // for convenient changing, if we need to make this wider + + MultiChildWidget parent = new MultiChildWidget(); + parent.setSize(18, 20 + textWidth); + Function<Widget, Boolean> enabledCheck = $ -> index < starColors.size(); + + // Button to enable this star color + parent.addChild(new ButtonWidget().setOnClick((data, widget) -> { + if (!widget.isClient()) { + if (index < starColors.size()) { + ForgeOfGodsStarColor color = starColors.getByIndex(index); + if (data.shift && !color.isPresetColor()) { + // if shift is held, open color editor for this preset, if not a default preset + editingStarIndex = index; + openCustomStarColorWindowFresh(widget, color); + } else { + // otherwise select this color + selectedStarColor = color.getName(); + updateRenderer(); + } + } + } + }) + .setPlayClickSound(true) + .setBackground(() -> { + IDrawable bg = GTUITextures.BUTTON_STANDARD; + if (index < starColors.size()) { + ForgeOfGodsStarColor color = starColors.getByIndex(index); + if (color.getName() + .equals(selectedStarColor)) { + bg = GTUITextures.BUTTON_STANDARD_PRESSED; + } + } + return new IDrawable[] { bg }; + }) + .addTooltips( + ImmutableList.of( + translateToLocal("fog.cosmetics.selectcolor.tooltip.1"), + translateToLocal("fog.cosmetics.selectcolor.tooltip.2"))) + .setSize(16, 16) + .setPos(0, 0) + .setEnabled(enabledCheck)); + + // Drawable representation of this star color, overlaid on the above button + parent.addChild(new DrawableWidget().setDrawable(() -> { + if (index < starColors.size()) { + return starColors.getByIndex(index) + .getDrawable(); + } + return IDrawable.EMPTY; + }) + .setPos(1, 1) + .setSize(14, 14) + .setEnabled(enabledCheck)); + + // Name of this star color + parent.addChild(new DynamicTextWidget(() -> { + if (index < starColors.size()) { + ForgeOfGodsStarColor color = starColors.getByIndex(index); + return new Text(color.getName()); + } + return Text.EMPTY; + }).setDefaultColor(ForgeOfGodsUI.GOLD_ARGB) + .setTextAlignment(Alignment.CenterLeft) + .setSize(textWidth, 18) + .setPos(20, 0) + .setEnabled(enabledCheck)); + + return parent; + } + + protected ModularWindow createStarCustomColorWindow(final EntityPlayer player) { + ModularWindow.Builder builder = ModularWindow.builder(200, 200); + builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_WHITE); + builder.setDraggable(true); + + // Syncers + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> starColorR, val -> starColorR = val)); + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> starColorG, val -> starColorG = val)); + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> starColorB, val -> starColorB = val)); + builder.widget(new FakeSyncWidget.FloatSyncer(() -> starGamma, val -> starGamma = val)); + builder.widget(new FakeSyncWidget.IntegerSyncer(() -> editingColorIndex, val -> editingColorIndex = val)); + + builder.widget( + new FakeSyncWidget<>( + () -> newStarColor, + val -> newStarColor = val, + ForgeOfGodsStarColor::writeToBuffer, + ForgeOfGodsStarColor::readFromBuffer)); + + // Exit button and header + builder.widget( + ButtonWidget.closeWindowButton(true) + .setPos(184, 4)) + .widget( + TextWidget.localised("fog.cosmetics.starcolor") + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setScale(1f) + .setPos(0, 5) + .setSize(200, 15)); + + // *********** + // Color Entry + // *********** + + // RGB + Gamma text fields + Widget redField = ForgeOfGodsUI + .createStarColorRGBMGroup(StarColorRGBM.RED, val -> starColorR = (int) val, () -> starColorR); + builder.widget(redField.setPos(8, 21)); + + Widget greenField = ForgeOfGodsUI + .createStarColorRGBMGroup(StarColorRGBM.GREEN, val -> starColorG = (int) val, () -> starColorG); + builder.widget(greenField.setPos(8, 40)); + + Widget blueField = ForgeOfGodsUI + .createStarColorRGBMGroup(StarColorRGBM.BLUE, val -> starColorB = (int) val, () -> starColorB); + builder.widget(blueField.setPos(8, 59)); + + Widget gammaField = ForgeOfGodsUI + .createStarColorRGBMGroup(StarColorRGBM.GAMMA, val -> starGamma = (float) val, () -> starGamma); + builder.widget(gammaField.setPos(8, 78)); + + // Color preview box + Widget colorPreviewBox = new DrawableWidget() + .setDrawable(() -> new Rectangle().setColor(Color.rgb(starColorR, starColorG, starColorB))) + .setSize(168, 15) + .setPos(16, 99); + builder.widget(colorPreviewBox); + + // Apply color button + Widget colorApplyButton = ForgeOfGodsUI.createStarColorButton(() -> { + if (editingColorIndex >= 0) { + return "fog.cosmetics.applycolor"; + } + return "fog.cosmetics.addcolor"; + }, () -> { + if (editingColorIndex >= 0) { + return "fog.cosmetics.applycolor.tooltip"; + } + return "fog.cosmetics.addcolor.tooltip"; + }, (clickData, widget) -> { + if (!widget.isClient()) { + StarColorSetting color = new StarColorSetting(starColorR, starColorG, starColorB, starGamma); + if (editingColorIndex >= 0 && editingColorIndex < newStarColor.numColors()) { + // insert into the list, as we are editing an existing color + newStarColor.setColor(editingColorIndex, color); + } else { + // add a new color at the end of the list + newStarColor.addColor(color); + } + ForgeOfGodsUI.reopenWindow(widget, STAR_CUSTOM_COLOR_WINDOW_ID); + } + }); + builder.widget(colorApplyButton.setPos(63, 118)); + + // Reset color button + Widget colorResetButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.resetcolor", + "fog.cosmetics.resetcolor.tooltip", + (clickData, widget) -> { + if (!widget.isClient()) { + starColorR = ForgeOfGodsStarColor.DEFAULT_RED; + starColorG = ForgeOfGodsStarColor.DEFAULT_GREEN; + starColorB = ForgeOfGodsStarColor.DEFAULT_BLUE; + starGamma = ForgeOfGodsStarColor.DEFAULT_GAMMA; + } + }); + builder.widget(colorResetButton.setPos(102, 118)); + + // ********** + // Color List + // ********** + + // Color list + for (int i = 0; i < 9; i++) { + final int ii = i; + + MultiChildWidget colorListEntry = new MultiChildWidget(); + colorListEntry.setSize(18, 18); + colorListEntry.setPos(8 + i * 18, 136); + + // List entry button + selector outline + colorListEntry.addChild(new ButtonWidget().setOnClick((clickData, widget) -> { + if (widget.isClient()) return; + + if (clickData.mouseButton == 0) { // left click + // deselect this if its already selected + if (editingColorIndex == ii) { + editingColorIndex = -1; + return; + } + + // otherwise select this if it's valid to select + if (ii < newStarColor.numColors()) { + editingColorIndex = ii; + StarColorSetting color = newStarColor.getColor(ii); + starColorR = color.getColorR(); + starColorG = color.getColorG(); + starColorB = color.getColorB(); + starGamma = color.getGamma(); + } + } else if (clickData.mouseButton == 1) { // right click + // if this is valid, remove it and shift other values down + if (ii < newStarColor.numColors()) { + newStarColor.removeColor(ii); + + if (editingColorIndex == ii) { + // deselect if this index was selected + editingColorIndex = -1; + } else if (editingColorIndex > ii) { + // shift down the editing index if it was after this entry + editingColorIndex -= 1; + } + ForgeOfGodsUI.reopenWindow(widget, STAR_CUSTOM_COLOR_WINDOW_ID); + } + } + }) + .setPlayClickSound(false) + .setBackground(() -> { + if (editingColorIndex == ii) { + return new IDrawable[] { TecTechUITextures.UNSELECTED_OPTION, + TecTechUITextures.SLOT_OUTLINE_GREEN }; + } + return new IDrawable[] { TecTechUITextures.UNSELECTED_OPTION }; + }) + .dynamicTooltip(() -> { + List<String> ret = new ArrayList<>(); + ret.add(translateToLocal("fog.cosmetics.colorlist.tooltip.1")); + ret.add(translateToLocal("fog.cosmetics.colorlist.tooltip.2")); + + if (ii < newStarColor.numColors()) { + ret.add(""); + StarColorSetting color = newStarColor.getColor(ii); + ret.add(StarColorRGBM.RED.tooltip(color.getColorR())); + ret.add(StarColorRGBM.GREEN.tooltip(color.getColorG())); + ret.add(StarColorRGBM.BLUE.tooltip(color.getColorB())); + ret.add(StarColorRGBM.GAMMA.tooltip(color.getGamma())); + } + return ret; + }) + .setUpdateTooltipEveryTick(true) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(18, 18) + .setPos(0, 0)); + + // List entry color + colorListEntry.addChild(new DrawableWidget().setDrawable(() -> { + if (ii < newStarColor.numColors()) { + StarColorSetting color = newStarColor.getColor(ii); + return new Rectangle().setColor(Color.rgb(color.getColorR(), color.getColorG(), color.getColorB())); + } + return IDrawable.EMPTY; + }) + .setSize(16, 16) + .setPos(1, 1)); + + builder.widget(colorListEntry); + } + + // Cycle rate text field + Widget cycleRateField = new NumericWidget().setSetter(val -> newStarColor.setCycleSpeed((int) val)) + .setGetter(() -> newStarColor.getCycleSpeed()) + .setBounds(1, 100) + .setDefaultValue(1) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .addTooltip(translateToLocal("fog.cosmetics.cyclespeed")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD) + .setSize(21, 16) + .setPos(171, 137); + builder.widget(cycleRateField); + + // Name text field + Widget nameEntryField = new TextFieldWidget().setSetter(val -> newStarColor.setName(val)) + .setGetter(() -> newStarColor.getName()) + .setMaxLength(15) + .setTextAlignment(Alignment.CenterLeft) + .setTextColor(ForgeOfGodsUI.GOLD_ARGB) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD) + .addTooltips( + ImmutableList.of( + translateToLocal("fog.cosmetics.starcolorname.tooltip.1"), + translateToLocal("fog.cosmetics.starcolorname.tooltip.2"))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(101, 158) + .setSize(91, 16); + builder.widget(nameEntryField); + + // Name label + Widget nameLabel = TextWidget.localised("fog.cosmetics.starcolorname") + .setTextAlignment(Alignment.CenterLeft) + .setDefaultColor(EnumChatFormatting.GOLD) + .setPos(8, 158) + .setSize(100, 16); + builder.widget(nameLabel); + + // ************** + // Preset Buttons + // ************** + + // Save preset button + Widget savePresetButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.savecolors", + "fog.cosmetics.savecolors.tooltip", + (clickData, widget) -> { + if (!widget.isClient()) { + if (newStarColor.numColors() == 0) return; + if (editingStarIndex >= 0) { + starColors.insert(newStarColor, editingStarIndex); + selectedStarColor = newStarColor.getName(); + updateRenderer(); + } else { + starColors.store(newStarColor); + } + widget.getWindow() + .closeWindow(); + ForgeOfGodsUI.reopenWindow(widget, STAR_COSMETICS_WINDOW_ID); + } + }); + builder.widget(savePresetButton.setPos(138, 177)); + + // Delete preset button + Widget deletePresetButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.deletecolors", + "fog.cosmetics.deletecolors.tooltip", + (clickData, widget) -> { + if (!widget.isClient()) { + starColors.drop(newStarColor); + if (selectedStarColor.equals(newStarColor.getName())) { + // set to default if the deleted color was selected + selectedStarColor = ForgeOfGodsStarColor.DEFAULT.getName(); + updateRenderer(); + } + widget.getWindow() + .closeWindow(); + ForgeOfGodsUI.reopenWindow(widget, STAR_COSMETICS_WINDOW_ID); + } + }); + builder.widget(deletePresetButton.setPos(101, 177)); + + // Import preset button + Widget importPresetButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.importcolors", + "fog.cosmetics.importcolors.tooltip", + (clickData, widget) -> { + if (!widget.isClient()) { + // reset state from before if it exists + importedStarColor = null; + widget.getContext() + .openSyncedWindow(STAR_CUSTOM_COLOR_IMPORT_WINDOW_ID); + } + }); + builder.widget(importPresetButton.setPos(64, 177)); + + // Export preset button + Widget exportPresetButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.exportcolors", + "fog.cosmetics.exportcolors.tooltip", + (clickData, widget) -> { + if (widget.isClient()) { + if (newStarColor.numColors() == 0) return; + if (Desktop.isDesktopSupported()) { + String output = newStarColor.serializeToString(); + Clipboard clipboard = Toolkit.getDefaultToolkit() + .getSystemClipboard(); + clipboard.setContents(new StringSelection(output), null); + } + } + }); + builder.widget(exportPresetButton.setPos(27, 177)); + + return builder.build(); + } + + protected ModularWindow createStarColorImportWindow(final EntityPlayer player) { + ModularWindow.Builder builder = ModularWindow.builder(200, 100); + builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_WHITE_HALF); + builder.setDraggable(true); + + // Syncers + builder.widget( + new FakeSyncWidget<>( + () -> importedStarColor, + val -> importedStarColor = val, + ForgeOfGodsStarColor::writeToBuffer, + ForgeOfGodsStarColor::readFromBuffer)); + + // Exit button and header + builder.widget( + ButtonWidget.closeWindowButton(true) + .setPos(184, 4)) + .widget( + TextWidget.localised("fog.cosmetics.importer.import") + .setDefaultColor(EnumChatFormatting.GOLD) + .setTextAlignment(Alignment.Center) + .setScale(1f) + .setPos(0, 5) + .setSize(200, 15)); + + // Serialized star color input + TextFieldWidget textField = new TextFieldWidget(); + textField.setSynced(false, true) + .setSetter(val -> { + if (!textField.isClient()) { + if (val == null || val.isEmpty()) { + importedStarColor = null; + return; + } + importedStarColor = ForgeOfGodsStarColor.deserialize(val); + } + }) + .setMaxLength(32767) + .setScrollBar() + .setTextAlignment(Alignment.CenterLeft) + .setTextColor(Color.WHITE.normal) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD) + .setSize(184, 18) + .setPos(8, 20); + builder.widget(textField); + + // Color preview for a valid star color string + for (int i = 0; i < 9; i++) { + int ii = i; + Widget colorEntry = new DrawableWidget().setDrawable(() -> { + if (importedStarColor != null && ii < importedStarColor.numColors()) { + StarColorSetting color = importedStarColor.getColor(ii); + return new Rectangle().setColor(Color.rgb(color.getColorR(), color.getColorG(), color.getColorB())) + .withOffset(1, 1, -2, -2); + } + return IDrawable.EMPTY; + }) + .setBackground(TecTechUITextures.UNSELECTED_OPTION) + .dynamicTooltip(() -> { + if (importedStarColor != null && ii < importedStarColor.numColors()) { + StarColorSetting color = importedStarColor.getColor(ii); + List<String> ret = new ArrayList<>(); + ret.add(StarColorRGBM.RED.tooltip(color.getColorR())); + ret.add(StarColorRGBM.GREEN.tooltip(color.getColorG())); + ret.add(StarColorRGBM.BLUE.tooltip(color.getColorB())); + ret.add(StarColorRGBM.GAMMA.tooltip(color.getGamma())); + return ret; + } + return Collections.emptyList(); + }) + .setSize(18, 18) + .setPos(8 + i * 18, 42); + builder.widget(colorEntry); + } + + // Cycle rate + Widget cycleRateText = new DynamicTextWidget(() -> { + if (importedStarColor != null) { + return new Text(Integer.toString(importedStarColor.getCycleSpeed())); + } + return Text.EMPTY; + }).setTextAlignment(Alignment.Center) + .setDefaultColor(Color.WHITE.normal) + .addTooltip(translateToLocal("fog.cosmetics.cyclespeed")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD) + .setSize(21, 16) + .setPos(171, 43); + builder.widget(cycleRateText); + + // Validator string + Widget validatorText = new DynamicTextWidget(() -> { + if (importedStarColor == null) { + return new Text(EnumChatFormatting.RED + translateToLocal("fog.cosmetics.importer.error")); + } + return new Text(EnumChatFormatting.GREEN + translateToLocal("fog.cosmetics.importer.valid")); + }).setTextAlignment(Alignment.Center) + .setPos(0, 62) + .setSize(200, 16); + builder.widget(validatorText); + + // Confirm button + Widget confirmImportButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.importer.apply", + "fog.cosmetics.importer.apply.tooltip", + (clickData, widget) -> { + if (!widget.isClient()) { + // no action if a valid star color isn't provided + if (importedStarColor != null) { + widget.getWindow() + .closeWindow(); + openCustomStarColorWindowFresh(widget, importedStarColor); + } + } + }); + builder.widget(confirmImportButton.setPos(101, 77)); + + // Reset button + Widget resetImportButton = ForgeOfGodsUI.createStarColorButton( + "fog.cosmetics.importer.reset", + "fog.cosmetics.importer.reset.tooltip", + (clickData, widget) -> { + if (!widget.isClient()) { + importedStarColor = null; + } + }); + builder.widget(resetImportButton.setPos(64, 77)); + + return builder.build(); + } + + // Opens the custom color window while also resetting the editing values. + // Can optionally pass a star color to set as the editing color + private void openCustomStarColorWindowFresh(Widget widget, @Nullable ForgeOfGodsStarColor importedColor) { + if (!widget.isClient()) { + // Reset star color state + if (importedColor == null) { + importedColor = starColors.newTemplateColor(); + } + newStarColor = importedColor; + editingColorIndex = -1; + starColorR = ForgeOfGodsStarColor.DEFAULT_RED; + starColorG = ForgeOfGodsStarColor.DEFAULT_GREEN; + starColorB = ForgeOfGodsStarColor.DEFAULT_BLUE; + starGamma = ForgeOfGodsStarColor.DEFAULT_GAMMA; + + ForgeOfGodsUI.reopenWindow(widget, STAR_CUSTOM_COLOR_WINDOW_ID); + } + } + + private DynamicPositionedRow delenoName() { + DynamicPositionedRow nameRow = new DynamicPositionedRow(); + String deleno = translateToLocal("gt.blockmachines.multimachine.FOG.deleno"); + int[] colors = new int[] { 0xffffff, 0xf6fff5, 0xecffec, 0xe3ffe2, 0xd9ffd9, 0xd0ffcf }; + + for (int i = 0; i < 6; i++) { + nameRow.addChild( + new TextWidget(Character.toString(deleno.charAt(i))).setDefaultColor(colors[i]) + .setScale(0.8f) + .setTextAlignment(Alignment.CenterLeft)); + } + return nameRow; + } + + @Override + public MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Stellar Forge") + .addInfo(EnumChatFormatting.ITALIC + "Also known as Godforge or Gorge for short.") + .addSeparator(EnumChatFormatting.AQUA, 73) + .addInfo("A massive structure harnessing the thermal, gravitational and") + .addInfo("kinetic energy of a stabilised neutron star for material processing.") + .addInfo( + "This multiblock can house " + EnumChatFormatting.RED + + "up to 16 modules " + + EnumChatFormatting.GRAY + + "which utilize the star to energize materials") + .addInfo("to varying degrees, ranging from regular smelting to matter degeneration.") + .addInfo("EU requirements for all modules are handled via wireless energy directly.") + .addSeparator(EnumChatFormatting.AQUA, 73) + .addInfo( + "This multiblock has an " + EnumChatFormatting.GOLD + + "extensive upgrade tree " + + EnumChatFormatting.GRAY + + "which influences all of its functions,") + .addInfo( + "such as " + EnumChatFormatting.GOLD + + "unlocking new module types, increasing heat levels " + + EnumChatFormatting.GRAY + + "and " + + EnumChatFormatting.GOLD + + "granting") + .addInfo( + EnumChatFormatting.GOLD + "various processing speed bonuses. " + + EnumChatFormatting.GRAY + + "These upgrades can be unlocked by reaching") + .addInfo("certain milestones and/or spending materials.") + .addSeparator(EnumChatFormatting.AQUA, 73) + .addInfo( + EnumChatFormatting.GREEN + + "Clicking on the logo in the controller gui opens an extensive information window,") + .addInfo("explaining everything there is to know about this multiblock.") + .beginStructureBlock(127, 29, 186, false) + .addStructureInfo( + "Total blocks needed for the structure with " + EnumChatFormatting.DARK_PURPLE + + "1" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "2" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "3" + + EnumChatFormatting.GRAY + + " rings:") + .addStructureInfo( + EnumChatFormatting.DARK_PURPLE + "3943" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "7279" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "11005" + + EnumChatFormatting.GRAY + + " Transcendentally Amplified Magnetic Confinement Casing") + .addStructureInfo( + EnumChatFormatting.DARK_PURPLE + "2819" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "4831" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "6567" + + EnumChatFormatting.GRAY + + " Singularity Reinforced Stellar Shielding Casing") + .addStructureInfo( + EnumChatFormatting.DARK_PURPLE + "272" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "512" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "824" + + EnumChatFormatting.GRAY + + " Celestial Matter Guidance Casing") + .addStructureInfo( + EnumChatFormatting.DARK_PURPLE + "130" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "144" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "158" + + EnumChatFormatting.GRAY + + " Boundless Gravitationally Severed Structure Casing") + .addStructureInfo( + EnumChatFormatting.DARK_PURPLE + "9" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "54" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "155" + + EnumChatFormatting.GRAY + + " Spatially Transcendent Gravitational Lens Block") + .addStructureInfo( + EnumChatFormatting.DARK_PURPLE + "345" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "357" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "397" + + EnumChatFormatting.DARK_PURPLE + + " Remote" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.DARK_GREEN + + "Medial" + + EnumChatFormatting.GRAY + + "/" + + EnumChatFormatting.AQUA + + "Central" + + EnumChatFormatting.GRAY + + " Graviton Flow Modulator") + .addStructureInfo( + EnumChatFormatting.GOLD + "36" + EnumChatFormatting.GRAY + " Stellar Energy Siphon Casing") + .addStructureInfoSeparator() + .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Input Hatch") + .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Output Bus (ME)") + .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Input Bus") + .toolTipFinisher(EnumChatFormatting.AQUA, 73); + return tt; + } + + @Override + public boolean energyFlowOnRunningTick(ItemStack aStack, boolean allowProduction) { + return true; + } + + @Override + public String[] getStructureDescription(ItemStack stackSize) { + return new String[] { EnumChatFormatting.AQUA + translateToLocal("tt.keyphrase.Hint_Details") + ":", + translateToLocal("gt.blockmachines.multimachine.FOG.hint.0"), + translateToLocal("gt.blockmachines.multimachine.FOG.hint.1") }; + } + + public int getFuelType() { + return selectedFuelType; + } + + private void setFuelType(int fuelType) { + selectedFuelType = fuelType; + } + + public int getFuelFactor() { + return fuelConsumptionFactor; + } + + public boolean isUpgradeActive(int upgradeID) { + return upgrades[upgradeID]; + } + + public int getRingAmount() { + return ringAmount; + } + + public int getTotalActiveUpgrades() { + int totalUpgrades = 0; + for (boolean upgrade : upgrades) { + if (upgrade) { + totalUpgrades++; + } + } + return totalUpgrades; + } + + private Text fuelUsage() { + return new Text(fuelConsumption + " L/5s"); + } + + private Text gravitonShardAmount() { + EnumChatFormatting enoughGravitonShards = EnumChatFormatting.RED; + if (gravitonShardsAvailable >= gravitonShardCost) { + enoughGravitonShards = EnumChatFormatting.GREEN; + } + return new Text(enoughGravitonShards + Integer.toString(gravitonShardsAvailable)); + + } + + private Text storedFuel() { + if (internalBattery == 0) { + return new Text( + translateToLocal("gt.blockmachines.multimachine.FOG.storedstartupfuel") + " " + + stellarFuelAmount + + "/" + + neededStartupFuel); + } + return new Text( + translateToLocal("gt.blockmachines.multimachine.FOG.storedfuel") + " " + + internalBattery + + "/" + + maxBatteryCharge); + } + + private void checkInversionStatus() { + int inversionChecker = 0; + for (int progress : milestoneProgress) { + if (progress < 7) { + break; + } + inversionChecker++; + } + inversion = inversionChecker == 4; + } + + public boolean isInversionAvailable() { + return inversion; + } + + private Text inversionStatusText() { + String inversionStatus = ""; + if (inversion) { + inversionStatus = EnumChatFormatting.BOLD + + translateToLocal("gt.blockmachines.multimachine.FOG.inversionactive"); + } + return new Text(inversionStatus); + } + + private void determineCompositionMilestoneLevel() { + int[] uniqueModuleCount = new int[5]; + int smelting = 0; + int molten = 0; + int plasma = 0; + int exotic = 0; + int exoticMagmatter = 0; + for (MTEBaseModule module : moduleHatches) { + if (module instanceof MTESmeltingModule) { + uniqueModuleCount[0] = 1; + smelting++; + continue; + } + if (module instanceof MTEMoltenModule) { + uniqueModuleCount[1] = 1; + molten++; + continue; + } + if (module instanceof MTEPlasmaModule) { + uniqueModuleCount[2] = 1; + plasma++; + continue; + } + if (module instanceof MTEExoticModule) { + if (!((MTEExoticModule) module).isMagmatterModeOn()) { + uniqueModuleCount[3] = 1; + exotic++; + } else { + uniqueModuleCount[4] = 1; + exoticMagmatter++; + } + } + + } + totalExtensionsBuilt = Arrays.stream(uniqueModuleCount) + .sum() + ringAmount + - 1; + if (inversion) { + totalExtensionsBuilt += (smelting - 1 + + (molten - 1) * 2 + + (plasma - 1) * 3 + + (exotic - 1) * 4 + + (exoticMagmatter - 1) * 5) / 5f; + } + milestoneProgress[3] = (int) Math.floor(totalExtensionsBuilt); + } + + private void determineMilestoneProgress() { + int closestRelevantSeven; + float rawProgress; + float actualProgress; + if (milestoneProgress[0] < 7) { + powerMilestonePercentage = (float) max( + (log((totalPowerConsumed.divide(BigInteger.valueOf(POWER_MILESTONE_CONSTANT))).longValue()) + / POWER_LOG_CONSTANT + 1), + 0) / 7; + milestoneProgress[0] = (int) floor(powerMilestonePercentage * 7); + } + if (inversion) { + rawProgress = (totalPowerConsumed.divide(POWER_MILESTONE_T7_CONSTANT) + .floatValue() - 1) / 7; + closestRelevantSeven = (int) floor(rawProgress); + actualProgress = rawProgress - closestRelevantSeven; + milestoneProgress[0] = 7 + (int) floor(rawProgress * 7); + if (closestRelevantSeven % 2 == 0) { + invertedPowerMilestonePercentage = actualProgress; + powerMilestonePercentage = 1 - invertedPowerMilestonePercentage; + } else { + powerMilestonePercentage = actualProgress; + invertedPowerMilestonePercentage = 1 - powerMilestonePercentage; + } + } + + if (milestoneProgress[1] < 7) { + recipeMilestonePercentage = (float) max( + (log(totalRecipesProcessed * 1f / RECIPE_MILESTONE_CONSTANT) / RECIPE_LOG_CONSTANT + 1), + 0) / 7; + milestoneProgress[1] = (int) floor(recipeMilestonePercentage * 7); + } + if (inversion) { + rawProgress = (((float) totalRecipesProcessed / RECIPE_MILESTONE_T7_CONSTANT) - 1) / 7; + closestRelevantSeven = (int) floor(rawProgress); + actualProgress = rawProgress - closestRelevantSeven; + milestoneProgress[1] = 7 + (int) floor(rawProgress * 7); + if (closestRelevantSeven % 2 == 0) { + invertedRecipeMilestonePercentage = actualProgress; + recipeMilestonePercentage = 1 - invertedRecipeMilestonePercentage; + } else { + recipeMilestonePercentage = actualProgress; + invertedRecipeMilestonePercentage = 1 - recipeMilestonePercentage; + } + } + if (milestoneProgress[2] < 7) { + fuelMilestonePercentage = (float) max( + (log(totalFuelConsumed * 1f / FUEL_MILESTONE_CONSTANT) / FUEL_LOG_CONSTANT + 1), + 0) / 7; + milestoneProgress[2] = (int) floor(fuelMilestonePercentage * 7); + } + if (inversion) { + rawProgress = (((float) totalFuelConsumed / FUEL_MILESTONE_T7_CONSTANT) - 1) / 7; + closestRelevantSeven = (int) floor(rawProgress); + actualProgress = rawProgress - closestRelevantSeven; + milestoneProgress[2] = 7 + (int) floor(rawProgress * 7); + if ((closestRelevantSeven % 2) == 0) { + invertedFuelMilestonePercentage = actualProgress; + fuelMilestonePercentage = 1 - invertedFuelMilestonePercentage; + } else { + fuelMilestonePercentage = actualProgress; + invertedFuelMilestonePercentage = 1 - fuelMilestonePercentage; + } + } + + if (milestoneProgress[3] <= 7) { + structureMilestonePercentage = totalExtensionsBuilt / 7f; + } + if (inversion) { + rawProgress = (totalExtensionsBuilt - 7) / 7f; + closestRelevantSeven = (int) floor(rawProgress); + actualProgress = rawProgress - closestRelevantSeven; + if ((closestRelevantSeven % 2) == 0) { + invertedStructureMilestonePercentage = actualProgress; + structureMilestonePercentage = 1 - invertedStructureMilestonePercentage; + } else { + structureMilestonePercentage = actualProgress; + invertedStructureMilestonePercentage = 1 - structureMilestonePercentage; + } + } + } + + private void determineGravitonShardAmount() { + int sum = 0; + for (int progress : milestoneProgress) { + if (!inversion) { + progress = Math.min(progress, 7); + } + sum += progress * (progress + 1) / 2; + } + gravitonShardsAvailable = sum - gravitonShardsSpent; + } + + private void ejectGravitonShards() { + if (mOutputBusses.size() == 1) { + while (gravitonShardsAvailable >= 64) { + addOutput(GTOreDictUnificator.get(OrePrefixes.gem, MaterialsUEVplus.GravitonShard, 64)); + gravitonShardsAvailable -= 64; + } + addOutput( + GTOreDictUnificator.get(OrePrefixes.gem, MaterialsUEVplus.GravitonShard, gravitonShardsAvailable)); + gravitonShardsAvailable = 0; + } + } + + private Text gravitonShardAmountText(int milestoneID) { + int sum; + int progress = milestoneProgress[milestoneID]; + if (!inversion) { + progress = Math.min(progress, 7); + } + sum = progress * (progress + 1) / 2; + return new Text( + translateToLocal("gt.blockmachines.multimachine.FOG.shardgain") + ": " + EnumChatFormatting.GRAY + sum); + } + + private enum FormattingMode { + + NONE, + COMMA, + EXPONENT; + + static final FormattingMode[] VALUES = values(); + + FormattingMode cycle() { + return switch (this) { + case NONE -> COMMA; + case COMMA -> EXPONENT; + case EXPONENT -> NONE; + }; + } + + String format(Number number) { + return switch (this) { + case NONE -> number.toString(); + case COMMA -> { + if (number instanceof BigInteger bi) yield formatNumbers(bi); + else yield formatNumbers(number.longValue()); + } + case EXPONENT -> { + if (number instanceof BigInteger bi) { + if (bi.compareTo(BigInteger.valueOf(1_000L)) > 0) { + yield toExponentForm(bi); + } + yield bi.toString(); + } else { + long value = number.longValue(); + if (value > 1_000L) { + yield toExponentForm(value); + } + yield Long.toString(value); + } + } + }; + } + } + + private Text totalMilestoneProgress(int milestoneID) { + Number progress; + String suffix; + switch (milestoneID) { + case 0 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.power"); + progress = totalPowerConsumed; + } + case 1 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.recipes"); + progress = totalRecipesProcessed; + } + case 2 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.fuelconsumed"); + progress = totalFuelConsumed; + } + case 3 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.extensions"); + progress = milestoneProgress[3]; + } + default -> throw new IllegalArgumentException("Invalid Milestone ID"); + } + return new Text( + translateToLocal("gt.blockmachines.multimachine.FOG.totalprogress") + ": " + + EnumChatFormatting.GRAY + + formattingMode.format(progress) + + " " + + suffix); + } + + private Text currentMilestoneLevel(int milestoneID) { + int milestoneLevel = inversion ? milestoneProgress[milestoneID] : Math.min(milestoneProgress[milestoneID], 7); + return new Text( + translateToLocal("gt.blockmachines.multimachine.FOG.milestoneprogress") + ": " + + EnumChatFormatting.GRAY + + milestoneLevel); + } + + private Text milestoneProgressText(int milestoneID) { + Number max; + String suffix; + String progressText = translateToLocal("gt.blockmachines.multimachine.FOG.progress"); + Text done = new Text( + translateToLocal("gt.blockmachines.multimachine.FOG.milestonecomplete") + + (formattingMode != FormattingMode.NONE ? EnumChatFormatting.DARK_RED + "?" : "")); + + if (milestoneProgress[milestoneID] >= 7 && !inversion) { + return done; + } + + switch (milestoneID) { + case 0 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.power"); + if (inversion) { + max = POWER_MILESTONE_T7_CONSTANT.multiply(BigInteger.valueOf(milestoneProgress[0] - 5)); + } else { + max = BigInteger.valueOf(LongMath.pow(9, milestoneProgress[0])) + .multiply(BigInteger.valueOf(LongMath.pow(10, 15))); + } + } + case 1 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.recipes"); + if (inversion) { + max = RECIPE_MILESTONE_T7_CONSTANT * (milestoneProgress[1] - 5); + } else { + max = LongMath.pow(6, milestoneProgress[1]) * LongMath.pow(10, 7); + } + } + case 2 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.fuelconsumed"); + if (inversion) { + max = FUEL_MILESTONE_T7_CONSTANT * (milestoneProgress[2] - 5); + } else { + max = LongMath.pow(3, milestoneProgress[2]) * LongMath.pow(10, 4); + } + } + case 3 -> { + suffix = translateToLocal("gt.blockmachines.multimachine.FOG.extensions"); + max = milestoneProgress[3] + 1; + } + default -> throw new IllegalArgumentException("Invalid Milestone ID"); + } + return new Text(progressText + ": " + EnumChatFormatting.GRAY + formattingMode.format(max) + " " + suffix); + } + + private Text constructionStatusText() { + return upgrades[currentUpgradeID] ? new Text(translateToLocal("fog.upgrade.respec")) + : new Text(translateToLocal("fog.upgrade.confirm")); + } + + private List<String> constructionStatus() { + if (upgrades[currentUpgradeID]) { + return ImmutableList.of(translateToLocal("fog.upgrade.respec")); + } + return ImmutableList.of(translateToLocal("fog.upgrade.confirm")); + } + + private List<String> upgradeMaterialRequirements() { + if (materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) + .indexOf(currentUpgradeID)]) { + return ImmutableList.of(translateToLocal("fog.button.materialrequirementsmet.tooltip")); + } + return ImmutableList.of(translateToLocal("fog.button.materialrequirements.tooltip")); + } + + private void increaseBattery(int amount) { + if ((internalBattery + amount) <= maxBatteryCharge) { + internalBattery += amount; + } else { + internalBattery = maxBatteryCharge; + batteryCharging = false; + } + } + + public void reduceBattery(int amount) { + if (internalBattery - amount <= 0) { + internalBattery = 0; + if (!moduleHatches.isEmpty()) { + for (MTEBaseModule module : moduleHatches) { + module.disconnect(); + } + } + destroyRenderer(); + } else { + internalBattery -= amount; + totalFuelConsumed += amount; + } + + } + + public int getBatteryCharge() { + return internalBattery; + } + + public int getMaxBatteryCharge() { + return maxBatteryCharge; + } + + public void addTotalPowerConsumed(BigInteger amount) { + totalPowerConsumed = totalPowerConsumed.add(amount); + } + + public void addTotalRecipesProcessed(long amount) { + totalRecipesProcessed += amount; + } + + @Override + protected void setHatchRecipeMap(MTEHatchInput hatch) {} + + @Override + public void setItemNBT(NBTTagCompound NBT) { + NBT.setInteger("selectedFuelType", selectedFuelType); + NBT.setInteger("fuelConsumptionFactor", fuelConsumptionFactor); + NBT.setInteger("internalBattery", internalBattery); + NBT.setBoolean("batteryCharging", batteryCharging); + NBT.setInteger("batterySize", maxBatteryCharge); + NBT.setInteger("gravitonShardsAvailable", gravitonShardsAvailable); + NBT.setInteger("gravitonShardsSpent", gravitonShardsSpent); + NBT.setByteArray("totalPowerConsumed", totalPowerConsumed.toByteArray()); + NBT.setLong("totalRecipesProcessed", totalRecipesProcessed); + NBT.setLong("totalFuelConsumed", totalFuelConsumed); + NBT.setInteger("starFuelStored", stellarFuelAmount); + NBT.setBoolean("gravitonShardEjection", gravitonShardEjection); + NBT.setBoolean("secretUpgrde", secretUpgrade); + + // Store booleanArrays of all upgrades + NBTTagCompound upgradeBooleanArrayNBTTag = new NBTTagCompound(); + + int upgradeIndex = 0; + for (Boolean upgrade : upgrades) { + upgradeBooleanArrayNBTTag.setBoolean("upgrade" + upgradeIndex, upgrade); + upgradeIndex++; + } + + NBT.setTag("upgrades", upgradeBooleanArrayNBTTag); + + NBTTagCompound upgradeMaterialBooleanArrayNBTTag = new NBTTagCompound(); + + int upgradeMaterialIndex = 0; + for (Boolean upgrade : materialPaidUpgrades) { + upgradeBooleanArrayNBTTag.setBoolean("upgradeMaterial" + upgradeMaterialIndex, upgrade); + upgradeMaterialIndex++; + } + + NBT.setTag("upgradeMaterials", upgradeMaterialBooleanArrayNBTTag); + + starColors.serializeToNBT(NBT); + + super.saveNBTData(NBT); + } + + @Override + public void saveNBTData(NBTTagCompound NBT) { + NBT.setInteger("selectedFuelType", selectedFuelType); + NBT.setInteger("fuelConsumptionFactor", fuelConsumptionFactor); + NBT.setInteger("internalBattery", internalBattery); + NBT.setBoolean("batteryCharging", batteryCharging); + NBT.setInteger("batterySize", maxBatteryCharge); + NBT.setInteger("gravitonShardsAvailable", gravitonShardsAvailable); + NBT.setInteger("gravitonShardsSpent", gravitonShardsSpent); + NBT.setByteArray("totalPowerConsumed", totalPowerConsumed.toByteArray()); + NBT.setLong("totalRecipesProcessed", totalRecipesProcessed); + NBT.setLong("totalFuelConsumed", totalFuelConsumed); + NBT.setInteger("starFuelStored", stellarFuelAmount); + NBT.setBoolean("gravitonShardEjection", gravitonShardEjection); + NBT.setInteger("ringAmount", ringAmount); + NBT.setBoolean("secretUpgrade", secretUpgrade); + + // Store booleanArray of all upgrades + NBTTagCompound upgradeBooleanArrayNBTTag = new NBTTagCompound(); + + int upgradeIndex = 0; + for (boolean upgrade : upgrades) { + upgradeBooleanArrayNBTTag.setBoolean("upgrade" + upgradeIndex, upgrade); + upgradeIndex++; + } + + NBT.setTag("upgrades", upgradeBooleanArrayNBTTag); + + NBTTagCompound upgradeMaterialBooleanArrayNBTTag = new NBTTagCompound(); + + int upgradeMaterialIndex = 0; + for (boolean upgrade : materialPaidUpgrades) { + upgradeMaterialBooleanArrayNBTTag.setBoolean("upgradeMaterial" + upgradeMaterialIndex, upgrade); + upgradeMaterialIndex++; + } + + NBT.setTag("upgradeMaterials", upgradeMaterialBooleanArrayNBTTag); + + NBTTagCompound upgradeWindowStorageNBTTag = new NBTTagCompound(); + + int storageIndex = 0; + for (ItemStack itemStack : inputSlotHandler.getStacks()) { + if (itemStack != null) { + upgradeWindowStorageNBTTag + .setInteger(storageIndex + "stacksizeOfStoredUpgradeItems", itemStack.stackSize); + NBT.setTag(storageIndex + "storedUpgradeItem", itemStack.writeToNBT(new NBTTagCompound())); + } + storageIndex++; + } + + NBT.setTag("upgradeWindowStorage", upgradeWindowStorageNBTTag); + + // Renderer information + NBT.setInteger("rotationSpeed", rotationSpeed); + NBT.setInteger("starSize", starSize); + NBT.setString("selectedStarColor", selectedStarColor); + NBT.setBoolean("isRenderActive", isRenderActive); + + starColors.serializeToNBT(NBT); + + super.saveNBTData(NBT); + } + + @Override + public void loadNBTData(NBTTagCompound NBT) { + selectedFuelType = NBT.getInteger("selectedFuelType"); + fuelConsumptionFactor = NBT.getInteger("fuelConsumptionFactor"); + internalBattery = NBT.getInteger("internalBattery"); + batteryCharging = NBT.getBoolean("batteryCharging"); + maxBatteryCharge = NBT.getInteger("batterySize"); + gravitonShardsAvailable = NBT.getInteger("gravitonShardsAvailable"); + gravitonShardsSpent = NBT.getInteger("gravitonShardsSpent"); + totalPowerConsumed = new BigInteger(NBT.getByteArray("totalPowerConsumed")); + totalRecipesProcessed = NBT.getLong("totalRecipesProcessed"); + totalFuelConsumed = NBT.getLong("totalFuelConsumed"); + stellarFuelAmount = NBT.getInteger("starFuelStored"); + gravitonShardEjection = NBT.getBoolean("gravitonShardEjection"); + ringAmount = NBT.getInteger("ringAmount"); + secretUpgrade = NBT.getBoolean("secretUpgrade"); + + NBTTagCompound tempBooleanTag = NBT.getCompoundTag("upgrades"); + + for (int upgradeIndex = 0; upgradeIndex < 31; upgradeIndex++) { + boolean upgrade = tempBooleanTag.getBoolean("upgrade" + upgradeIndex); + upgrades[upgradeIndex] = upgrade; + } + + tempBooleanTag = NBT.getCompoundTag("upgradeMaterials"); + + for (int upgradeIndex = 0; upgradeIndex < 7; upgradeIndex++) { + boolean upgrade = tempBooleanTag.getBoolean("upgradeMaterial" + upgradeIndex); + materialPaidUpgrades[upgradeIndex] = upgrade; + } + + NBTTagCompound tempItemTag = NBT.getCompoundTag("upgradeWindowStorage"); + + for (int index = 0; index < 16; index++) { + + int stackSize = tempItemTag.getInteger(index + "stacksizeOfStoredUpgradeItems"); + ItemStack itemStack = ItemStack.loadItemStackFromNBT(NBT.getCompoundTag(index + "storedUpgradeItem")); + + if (itemStack != null) { + storedUpgradeWindowItems[index] = itemStack.splitStack(stackSize); + } + } + + // Renderer information + rotationSpeed = NBT.getInteger("rotationSpeed"); + starSize = NBT.getInteger("starSize"); + selectedStarColor = NBT.getString("selectedStarColor"); + isRenderActive = NBT.getBoolean("isRenderActive"); + + starColors.rebuildFromNBT(NBT); + + super.loadNBTData(NBT); + } + + @Override + public boolean getDefaultHasMaintenanceChecks() { + return false; + } + + @SideOnly(Side.CLIENT) + @Override + protected SoundResource getActivitySoundLoop() { + return SoundResource.GT_MACHINES_GOD_FORGE_LOOP; + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEMoltenModule.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEMoltenModule.java new file mode 100644 index 0000000000..51bfe51ac0 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEMoltenModule.java @@ -0,0 +1,179 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static gregtech.api.util.GTUtility.formatNumbers; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static net.minecraft.util.EnumChatFormatting.GREEN; +import static net.minecraft.util.EnumChatFormatting.RED; +import static net.minecraft.util.EnumChatFormatting.RESET; +import static net.minecraft.util.EnumChatFormatting.YELLOW; + +import java.math.BigInteger; +import java.util.ArrayList; + +import javax.annotation.Nonnull; + +import net.minecraft.util.EnumChatFormatting; + +import org.jetbrains.annotations.NotNull; + +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.OverclockCalculator; +import tectech.recipe.TecTechRecipeMaps; + +public class MTEMoltenModule extends MTEBaseModule { + + private long EUt = 0; + private int currentParallel = 0; + + public MTEMoltenModule(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTEMoltenModule(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTEMoltenModule(mName); + } + + long wirelessEUt = 0; + + @Override + protected ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @NotNull + @Override + protected CheckRecipeResult validateRecipe(@Nonnull GTRecipe recipe) { + if (recipe.mSpecialValue > getHeat()) { + return CheckRecipeResultRegistry.insufficientHeat(recipe.mSpecialValue); + } + + if (recipe.mEUt > getProcessingVoltage()) { + return CheckRecipeResultRegistry.insufficientPower(recipe.mEUt); + } + + wirelessEUt = (long) recipe.mEUt * getMaxParallel(); + if (getUserEU(userUUID).compareTo(BigInteger.valueOf(wirelessEUt * recipe.mDuration)) < 0) { + return CheckRecipeResultRegistry.insufficientPower(wirelessEUt * recipe.mDuration); + } + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @Nonnull + @Override + protected OverclockCalculator createOverclockCalculator(@Nonnull GTRecipe recipe) { + return super.createOverclockCalculator(recipe).setEUt(getProcessingVoltage()) + .setRecipeHeat(recipe.mSpecialValue) + .setHeatOC(true) + .setHeatDiscount(true) + .setMachineHeat(Math.max(recipe.mSpecialValue, getHeatForOC())) + .setHeatDiscountMultiplier(getHeatEnergyDiscount()) + .setDurationDecreasePerOC(getOverclockTimeFactor()); + + } + + @NotNull + @Override + protected CheckRecipeResult onRecipeStart(@Nonnull GTRecipe recipe) { + if (!addEUToGlobalEnergyMap(userUUID, -calculatedEut * duration)) { + return CheckRecipeResultRegistry.insufficientPower(calculatedEut * duration); + } + addToPowerTally( + BigInteger.valueOf(calculatedEut) + .multiply(BigInteger.valueOf(duration))); + addToRecipeTally(calculatedParallels); + currentParallel = calculatedParallels; + EUt = calculatedEut; + setCalculatedEut(0); + return CheckRecipeResultRegistry.SUCCESSFUL; + } + }; + } + + @Override + protected void setProcessingLogicPower(ProcessingLogic logic) { + logic.setAvailableVoltage(Long.MAX_VALUE); + logic.setAvailableAmperage(Integer.MAX_VALUE); + logic.setAmperageOC(false); + logic.setMaxParallel(getMaxParallel()); + logic.setSpeedBonus(getSpeedBonus()); + logic.setEuModifier(getEnergyDiscount()); + } + + @Override + public RecipeMap<?> getRecipeMap() { + return TecTechRecipeMaps.godforgeMoltenRecipes; + } + + @Override + public String[] getInfoData() { + ArrayList<String> str = new ArrayList<>(); + str.add( + "Progress: " + GREEN + + formatNumbers(mProgresstime / 20) + + RESET + + " s / " + + YELLOW + + formatNumbers(mMaxProgresstime / 20) + + RESET + + " s"); + str.add( + "Currently using: " + RED + + (getBaseMetaTileEntity().isActive() ? formatNumbers(EUt) : "0") + + RESET + + " EU/t"); + str.add(YELLOW + "Max Parallel: " + RESET + formatNumbers(getMaxParallel())); + str.add( + YELLOW + "Current Parallel: " + + RESET + + (getBaseMetaTileEntity().isActive() ? formatNumbers(currentParallel) : "0")); + str.add(YELLOW + "Heat Capacity: " + RESET + formatNumbers(getHeat())); + str.add(YELLOW + "Effective Heat Capacity: " + RESET + formatNumbers(getHeatForOC())); + str.add(YELLOW + "Recipe time multiplier: " + RESET + formatNumbers(getSpeedBonus())); + str.add(YELLOW + "Energy multiplier: " + RESET + formatNumbers(getEnergyDiscount())); + str.add(YELLOW + "Recipe time divisor per non-perfect OC: " + RESET + formatNumbers(getOverclockTimeFactor())); + return str.toArray(new String[0]); + } + + @Override + public MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Blast Smelter") + .addInfo("This is a module of the Godforge.") + .addInfo("Must be part of a Godforge to function.") + .addInfo("Used for high temperature material liquefaction.") + .addSeparator(EnumChatFormatting.AQUA, 74) + .addInfo("The second module of the Godforge, this module melts materials directly into") + .addInfo("their liquid form. If an output material does not have a liquid form, it will be output") + .addInfo("as a regular solid instead.") + .addInfo("This module is specialized towards parallel processing.") + .beginStructureBlock(7, 7, 13, false) + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Singularity Reinforced Stellar Shielding Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Boundless Gravitationally Severed Structure Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Harmonic Phonon Transmission Conduit") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Celestial Matter Guidance Casing") + .addStructureInfo(EnumChatFormatting.GOLD + "1" + EnumChatFormatting.GRAY + " Stellar Energy Siphon Casing") + .toolTipFinisher(EnumChatFormatting.AQUA, 74); + return tt; + } + +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEPlasmaModule.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEPlasmaModule.java new file mode 100644 index 0000000000..29675ae5ce --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTEPlasmaModule.java @@ -0,0 +1,285 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.api.util.GTRecipeConstants.FOG_PLASMA_MULTISTEP; +import static gregtech.api.util.GTRecipeConstants.FOG_PLASMA_TIER; +import static gregtech.api.util.GTUtility.formatNumbers; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static net.minecraft.util.EnumChatFormatting.GREEN; +import static net.minecraft.util.EnumChatFormatting.RED; +import static net.minecraft.util.EnumChatFormatting.RESET; +import static net.minecraft.util.EnumChatFormatting.YELLOW; + +import java.math.BigInteger; +import java.util.ArrayList; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumChatFormatting; + +import org.jetbrains.annotations.NotNull; + +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.math.Size; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; + +import gregtech.api.enums.SoundResource; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.recipe.check.SimpleCheckRecipeResult; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.OverclockCalculator; +import tectech.loader.ConfigHandler; +import tectech.recipe.TecTechRecipeMaps; +import tectech.thing.gui.TecTechUITextures; + +public class MTEPlasmaModule extends MTEBaseModule { + + private long EUt = 0; + private int currentParallel = 0; + private int inputMaxParallel = 0; + + private static final int DEBUG_WINDOW_ID = 11; + + public MTEPlasmaModule(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTEPlasmaModule(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTEPlasmaModule(mName); + } + + long wirelessEUt = 0; + + @Override + protected ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @NotNull + @Override + protected CheckRecipeResult validateRecipe(@Nonnull GTRecipe recipe) { + wirelessEUt = (long) recipe.mEUt * getMaxParallel(); + if (getUserEU(userUUID).compareTo(BigInteger.valueOf(wirelessEUt * recipe.mDuration)) < 0) { + return CheckRecipeResultRegistry.insufficientPower(wirelessEUt * recipe.mDuration); + } + if (recipe.getMetadataOrDefault(FOG_PLASMA_TIER, 0) > getPlasmaTier() + || (recipe.getMetadataOrDefault(FOG_PLASMA_MULTISTEP, false) && !isMultiStepPlasmaCapable)) { + return SimpleCheckRecipeResult.ofFailure("missing_upgrades"); + } + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @NotNull + @Override + protected CheckRecipeResult onRecipeStart(@Nonnull GTRecipe recipe) { + wirelessEUt = (long) recipe.mEUt * maxParallel; + if (!addEUToGlobalEnergyMap(userUUID, -calculatedEut * duration)) { + return CheckRecipeResultRegistry.insufficientPower(wirelessEUt * recipe.mDuration); + } + addToPowerTally( + BigInteger.valueOf(calculatedEut) + .multiply(BigInteger.valueOf(duration))); + addToRecipeTally(calculatedParallels); + currentParallel = calculatedParallels; + EUt = calculatedEut; + setCalculatedEut(0); + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @Nonnull + @Override + protected OverclockCalculator createOverclockCalculator(@Nonnull GTRecipe recipe) { + return super.createOverclockCalculator(recipe).setEUt(getProcessingVoltage()) + .setDurationDecreasePerOC(getOverclockTimeFactor()); + } + }; + } + + @Override + protected void setProcessingLogicPower(ProcessingLogic logic) { + logic.setAvailableVoltage(Long.MAX_VALUE); + logic.setAvailableAmperage(Integer.MAX_VALUE); + logic.setAmperageOC(false); + logic.setMaxParallel(getMaxParallel()); + logic.setSpeedBonus(getSpeedBonus()); + logic.setEuModifier(getEnergyDiscount()); + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + super.addUIWidgets(builder, buildContext); + buildContext.addSyncedWindow(DEBUG_WINDOW_ID, this::createDebugWindow); + if (ConfigHandler.debug.DEBUG_MODE) { + builder.widget(createDebugWindowButton()); + } + } + + protected ButtonWidget createDebugWindowButton() { + Widget button = new ButtonWidget().setOnClick( + (data, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(DEBUG_WINDOW_ID); + }) + .setPlayClickSound(false) + .setBackground(TecTechUITextures.BUTTON_CELESTIAL_32x32, TecTechUITextures.OVERLAY_BUTTON_LOAF_MODE) + .addTooltip("Debug Window") + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(174, 91) + .setSize(16, 16); + return (ButtonWidget) button; + } + + protected ModularWindow createDebugWindow(final EntityPlayer player) { + final int WIDTH = 78; + final int HEIGHT = 60; + final int PARENT_WIDTH = getGUIWidth(); + final int PARENT_HEIGHT = getGUIHeight(); + ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); + builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.setGuiTint(getGUIColorization()); + builder.setDraggable(true); + builder.setPos( + (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) + .add( + Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT)) + .add(WIDTH - 3, 0))); + + // Debug enable/disable multi-step + builder.widget( + new ButtonWidget().setOnClick((clickData, widget) -> isMultiStepPlasmaCapable = !isMultiStepPlasmaCapable) + .setPlayClickSoundResource( + () -> isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation + : SoundResource.GUI_BUTTON_DOWN.resourceLocation) + .setBackground(() -> { + if (isMultiStepPlasmaCapable) { + return new IDrawable[] { GTUITextures.BUTTON_STANDARD_PRESSED, + GTUITextures.OVERLAY_BUTTON_POWER_SWITCH_ON }; + } else { + return new IDrawable[] { GTUITextures.BUTTON_STANDARD, + GTUITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF }; + } + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(this::isAllowedToWork, val -> { + if (val) enableWorking(); + else disableWorking(); + }), builder) + .addTooltip("multi-step") + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(4, 40) + .setSize(16, 16)); + + // Debug set plasma tier + builder.widget( + new TextFieldWidget().setSetterInt(this::setPlasmaTier) + .setGetterInt(this::getPlasmaTier) + .setNumbers(0, 2) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setPos(3, 18) + .addTooltip("fusion tier") + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(16, 16) + .setPos(4, 20) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)); + + // Debug set max parallel + builder.widget( + new TextFieldWidget().setSetterInt(val -> inputMaxParallel = val) + .setGetterInt(() -> inputMaxParallel) + .setNumbers(0, Integer.MAX_VALUE) + .setTextAlignment(Alignment.Center) + .setTextColor(Color.WHITE.normal) + .setPos(3, 18) + .addTooltip("parallel") + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setSize(70, 16) + .setPos(4, 4) + .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)); + + return builder.build(); + } + + @Override + public RecipeMap<?> getRecipeMap() { + return TecTechRecipeMaps.godforgePlasmaRecipes; + } + + @Override + public String[] getInfoData() { + ArrayList<String> str = new ArrayList<>(); + str.add( + "Progress: " + GREEN + + formatNumbers(mProgresstime / 20) + + RESET + + " s / " + + YELLOW + + formatNumbers(mMaxProgresstime / 20) + + RESET + + " s"); + str.add( + "Currently using: " + RED + + (getBaseMetaTileEntity().isActive() ? formatNumbers(EUt) : "0") + + RESET + + " EU/t"); + str.add(YELLOW + "Max Parallel: " + RESET + formatNumbers(getMaxParallel())); + str.add( + YELLOW + "Current Parallel: " + + RESET + + (getBaseMetaTileEntity().isActive() ? formatNumbers(currentParallel) : "0")); + str.add(YELLOW + "Recipe time multiplier: " + RESET + formatNumbers(getSpeedBonus())); + str.add(YELLOW + "Energy multiplier: " + RESET + formatNumbers(getEnergyDiscount())); + str.add(YELLOW + "Recipe time divisor per non-perfect OC: " + RESET + formatNumbers(getOverclockTimeFactor())); + return str.toArray(new String[0]); + } + + @Override + public MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Plasma Fabricator") + .addInfo("This is a module of the Godforge.") + .addInfo("Must be part of a Godforge to function.") + .addInfo("Used for extreme temperature matter ionization.") + .addSeparator(EnumChatFormatting.AQUA, 74) + .addInfo("The third module of the Godforge, this module infuses materials with extreme amounts") + .addInfo("of heat, ionizing and turning them into plasma directly. Not all plasmas can be produced") + .addInfo("right away, some of them require certain upgrades to be unlocked.") + .addInfo("This module is specialized towards energy and overclock efficiency.") + .beginStructureBlock(7, 7, 13, false) + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Singularity Reinforced Stellar Shielding Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Boundless Gravitationally Severed Structure Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Harmonic Phonon Transmission Conduit") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Celestial Matter Guidance Casing") + .addStructureInfo(EnumChatFormatting.GOLD + "1" + EnumChatFormatting.GRAY + " Stellar Energy Siphon Casing") + .toolTipFinisher(EnumChatFormatting.AQUA, 74); + return tt; + } + +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTESmeltingModule.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTESmeltingModule.java new file mode 100644 index 0000000000..ba8e5f2666 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/MTESmeltingModule.java @@ -0,0 +1,264 @@ +package tectech.thing.metaTileEntity.multi.godforge; + +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.api.util.GTUtility.formatNumbers; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static net.minecraft.util.EnumChatFormatting.GREEN; +import static net.minecraft.util.EnumChatFormatting.RED; +import static net.minecraft.util.EnumChatFormatting.RESET; +import static net.minecraft.util.EnumChatFormatting.YELLOW; +import static net.minecraft.util.StatCollector.translateToLocal; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nonnull; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; + +import org.jetbrains.annotations.NotNull; + +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; + +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.RecipeMaps; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.OverclockCalculator; +import tectech.TecTech; +import tectech.thing.gui.TecTechUITextures; + +public class MTESmeltingModule extends MTEBaseModule { + + private long EUt = 0; + private long currentParallel = 0; + private boolean furnaceMode = false; + + public MTESmeltingModule(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTESmeltingModule(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTESmeltingModule(mName); + } + + @Override + public RecipeMap<?> getRecipeMap() { + return furnaceMode ? RecipeMaps.furnaceRecipes : RecipeMaps.blastFurnaceRecipes; + } + + @Nonnull + @Override + public Collection<RecipeMap<?>> getAvailableRecipeMaps() { + return Arrays.asList(RecipeMaps.blastFurnaceRecipes, RecipeMaps.furnaceRecipes); + } + + @Override + public int getRecipeCatalystPriority() { + return -10; + } + + long wirelessEUt = 0; + + @Override + protected ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @NotNull + @Override + protected CheckRecipeResult validateRecipe(@Nonnull GTRecipe recipe) { + + if (recipe.mSpecialValue > getHeat()) { + return CheckRecipeResultRegistry.insufficientHeat(recipe.mSpecialValue); + } + + if (recipe.mEUt > getProcessingVoltage()) { + return CheckRecipeResultRegistry.insufficientPower(recipe.mEUt); + } + + wirelessEUt = (long) recipe.mEUt * getMaxParallel(); + if (getUserEU(userUUID).compareTo(BigInteger.valueOf(wirelessEUt * recipe.mDuration)) < 0) { + return CheckRecipeResultRegistry.insufficientPower(wirelessEUt * recipe.mDuration); + } + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @NotNull + @Override + protected CheckRecipeResult onRecipeStart(@Nonnull GTRecipe recipe) { + if (!addEUToGlobalEnergyMap(userUUID, -calculatedEut * duration)) { + return CheckRecipeResultRegistry.insufficientPower(calculatedEut * duration); + } + addToPowerTally( + BigInteger.valueOf(calculatedEut) + .multiply(BigInteger.valueOf(duration))); + if (!furnaceMode) { + addToRecipeTally(calculatedParallels); + } + currentParallel = calculatedParallels; + EUt = calculatedEut; + setCalculatedEut(0); + return CheckRecipeResultRegistry.SUCCESSFUL; + } + + @Nonnull + @Override + protected OverclockCalculator createOverclockCalculator(@Nonnull GTRecipe recipe) { + return super.createOverclockCalculator(recipe).setEUt(getProcessingVoltage()) + .setRecipeHeat(recipe.mSpecialValue) + .setHeatOC(true) + .setHeatDiscount(true) + .setMachineHeat(Math.max(recipe.mSpecialValue, getHeatForOC())) + .setHeatDiscountMultiplier(getHeatEnergyDiscount()) + .setDurationDecreasePerOC(getOverclockTimeFactor()); + } + }; + } + + @Override + protected void setProcessingLogicPower(ProcessingLogic logic) { + logic.setAvailableVoltage(Long.MAX_VALUE); + logic.setAvailableAmperage(Integer.MAX_VALUE); + logic.setAmperageOC(false); + logic.setMaxParallel(getMaxParallel()); + logic.setSpeedBonus(getSpeedBonus()); + logic.setEuModifier(getEnergyDiscount()); + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + super.addUIWidgets(builder, buildContext); + builder.widget(createFurnaceModeButton(builder)); + } + + protected ButtonWidget createFurnaceModeButton(IWidgetBuilder<?> builder) { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); + furnaceMode = !furnaceMode; + widget.notifyTooltipChange(); + }) + .setPlayClickSound(false) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); + if (isFurnaceModeOn()) { + ret.add(TecTechUITextures.OVERLAY_BUTTON_FURNACE_MODE); + } else { + ret.add(TecTechUITextures.OVERLAY_BUTTON_FURNACE_MODE_OFF); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(this::isFurnaceModeOn, this::setFurnaceMode), builder) + .dynamicTooltip( + () -> Collections.singletonList( + translateToLocal( + furnaceMode ? "fog.button.furnacemode.tooltip.02" : "fog.button.furnacemode.tooltip.01"))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(174, 91) + .setSize(16, 16); + return (ButtonWidget) button; + } + + private boolean isFurnaceModeOn() { + return furnaceMode; + } + + private void setFurnaceMode(boolean enabled) { + furnaceMode = enabled; + } + + @Override + public void saveNBTData(NBTTagCompound NBT) { + NBT.setBoolean("furnaceMode", furnaceMode); + super.saveNBTData(NBT); + } + + @Override + public void loadNBTData(final NBTTagCompound NBT) { + furnaceMode = NBT.getBoolean("furnaceMode"); + super.loadNBTData(NBT); + } + + @Override + public String[] getInfoData() { + ArrayList<String> str = new ArrayList<>(); + str.add( + "Progress: " + GREEN + + formatNumbers(mProgresstime / 20) + + RESET + + " s / " + + YELLOW + + formatNumbers(mMaxProgresstime / 20) + + RESET + + " s"); + str.add( + "Currently using: " + RED + + (getBaseMetaTileEntity().isActive() ? formatNumbers(EUt) : "0") + + RESET + + " EU/t"); + str.add(YELLOW + "Max Parallel: " + RESET + formatNumbers(getMaxParallel())); + str.add( + YELLOW + "Current Parallel: " + + RESET + + (getBaseMetaTileEntity().isActive() ? formatNumbers(currentParallel) : "0")); + str.add(YELLOW + "Heat Capacity: " + RESET + formatNumbers(getHeat())); + str.add(YELLOW + "Effective Heat Capacity: " + RESET + formatNumbers(getHeatForOC())); + str.add(YELLOW + "Recipe time multiplier: " + RESET + formatNumbers(getSpeedBonus())); + str.add(YELLOW + "Energy multiplier: " + RESET + formatNumbers(getEnergyDiscount())); + str.add(YELLOW + "Recipe time divisor per non-perfect OC: " + RESET + formatNumbers(getOverclockTimeFactor())); + return str.toArray(new String[0]); + } + + @Override + public MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addMachineType("Blast Furnace, Furnace") + .addInfo("This is a module of the Godforge.") + .addInfo("Must be part of a Godforge to function.") + .addInfo("Used for basic smelting operations at various temperatures.") + .addSeparator(EnumChatFormatting.AQUA, 74) + .addInfo("As the first of the Godforge modules, this module performs the most basic") + .addInfo("thermal processing, namely smelting materials identically to a furnace or blast furnace.") + .addInfo("The desired method of processing can be selected in the gui.") + .addInfo("This module is specialized towards speed and high heat levels.") + .beginStructureBlock(7, 7, 13, false) + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Singularity Reinforced Stellar Shielding Casing") + .addStructureInfo( + EnumChatFormatting.GOLD + "20" + + EnumChatFormatting.GRAY + + " Boundless Gravitationally Severed Structure Casing") + .addStructureInfo(EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Hypogen Coil Block") + .addStructureInfo( + EnumChatFormatting.GOLD + "5" + EnumChatFormatting.GRAY + " Celestial Matter Guidance Casing") + .addStructureInfo(EnumChatFormatting.GOLD + "1" + EnumChatFormatting.GRAY + " Stellar Energy Siphon Casing") + .toolTipFinisher(EnumChatFormatting.AQUA, 74); + return tt; + } + +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/ForgeOfGodsStarColor.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/ForgeOfGodsStarColor.java new file mode 100644 index 0000000000..9593c1db95 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/ForgeOfGodsStarColor.java @@ -0,0 +1,346 @@ +package tectech.thing.metaTileEntity.multi.godforge.color; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.Nullable; + +import com.cleanroommc.modularui.utils.Color; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.shapes.Rectangle; + +import tectech.thing.gui.TecTechUITextures; + +@SuppressWarnings("unused") // for the preset color fields +public class ForgeOfGodsStarColor { + + private static final int LATEST_VERSION = 1; + + // Preset colors + private static final Map<String, ForgeOfGodsStarColor> PRESETS = new LinkedHashMap<>(4); + + public static final int DEFAULT_RED = 179; + public static final int DEFAULT_GREEN = 204; + public static final int DEFAULT_BLUE = 255; + public static final float DEFAULT_GAMMA = 3.0f; + + public static final ForgeOfGodsStarColor DEFAULT = new ForgeOfGodsStarColor("Default") + .addColor(DEFAULT_RED, DEFAULT_GREEN, DEFAULT_BLUE, DEFAULT_GAMMA) + .registerPreset(); + + public static final ForgeOfGodsStarColor RAINBOW = new ForgeOfGodsStarColor("Rainbow").addColor(255, 0, 0, 3.0f) + .addColor(255, 255, 0, 3.0f) + .addColor(0, 255, 0, 3.0f) + .addColor(0, 255, 255, 3.0f) + .addColor(255, 0, 255, 3.0f) + .setCycleSpeed(1) + .setCustomDrawable(TecTechUITextures.PICTURE_RAINBOW_SQUARE) + .registerPreset(); + + public static final ForgeOfGodsStarColor CLOUD_PICK = new ForgeOfGodsStarColor("Cloud's Pick") + .addColor(DEFAULT_RED, DEFAULT_GREEN, DEFAULT_BLUE, DEFAULT_GAMMA) // todo @cloud + .registerPreset(); + + public static final ForgeOfGodsStarColor MAYA_PICK = new ForgeOfGodsStarColor("Maya's Pick") + .addColor(91, 206, 250, 3.0f) + .addColor(245, 169, 184, 3.0f) + .addColor(255, 255, 255, 3.0f) + .setCycleSpeed(1) + .registerPreset(); + + public static List<ForgeOfGodsStarColor> getDefaultColors() { + return new ArrayList<>(PRESETS.values()); + } + + // "Metadata" about this star color, not related to star rendering + private String name; + // version currently unused, but can be used to retain compatibility with old serialized star colors + // if the structure of the data changes significantly. + private final int version; + private boolean isPreset; + private IDrawable drawable; + + // Star render settings + private final List<StarColorSetting> settings = new ArrayList<>(); + private int cycleSpeed = 1; + + protected ForgeOfGodsStarColor(String name) { + this(name, LATEST_VERSION); + } + + private ForgeOfGodsStarColor(String name, int version) { + this.name = name; + this.version = version; + } + + private ForgeOfGodsStarColor registerPreset() { + this.isPreset = true; + PRESETS.put(getName(), this); + return this; + } + + public boolean isPresetColor() { + return isPreset; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ForgeOfGodsStarColor setCycleSpeed(int speed) { + this.cycleSpeed = speed; + return this; + } + + public int getCycleSpeed() { + return cycleSpeed; + } + + public ForgeOfGodsStarColor addColor(int r, int g, int b, float gamma) { + settings.add(new StarColorSetting(r, g, b, gamma)); + return this; + } + + public ForgeOfGodsStarColor addColor(StarColorSetting color) { + settings.add(color); + return this; + } + + private ForgeOfGodsStarColor addColors(List<StarColorSetting> colors) { + settings.addAll(colors); + return this; + } + + public int numColors() { + return settings.size(); + } + + public StarColorSetting getColor(int index) { + return settings.get(index); + } + + public void setColor(int index, StarColorSetting color) { + settings.set(index, color); + } + + public void removeColor(int index) { + settings.remove(index); + } + + public ForgeOfGodsStarColor setCustomDrawable(IDrawable drawable) { + this.drawable = drawable; + return this; + } + + /** @return a picture representation of this star color. */ + public IDrawable getDrawable() { + if (drawable == null) { + StarColorSetting setting = settings.get(0); + drawable = new Rectangle() + .setColor(Color.rgb(setting.getColorR(), setting.getColorG(), setting.getColorB())); + } + return drawable; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ForgeOfGodsStarColor that = (ForgeOfGodsStarColor) o; + + if (cycleSpeed != that.cycleSpeed) return false; + if (!name.equals(that.name)) return false; + if (settings.size() != that.settings.size()) return false; + for (int i = 0; i < settings.size(); i++) { + StarColorSetting thisSetting = settings.get(i); + StarColorSetting thatSetting = that.settings.get(i); + if (!thisSetting.equals(thatSetting)) return false; + } + return true; + } + + @Override + public String toString() { + return serializeToString(); + } + + public NBTTagCompound serializeToNBT() { + NBTTagCompound NBT = new NBTTagCompound(); + + if (isPresetColor()) { + // Known color, we can just do this with a simple key + NBT.setString("Preset", getName()); + return NBT; + } + + NBT.setString("Name", getName()); + NBT.setInteger("CycleSpeed", cycleSpeed); + NBT.setInteger("Version", version); + + if (!settings.isEmpty()) { + NBTTagCompound settingsNBT = new NBTTagCompound(); + settingsNBT.setInteger("Size", settings.size()); + + for (int i = 0; i < settings.size(); i++) { + StarColorSetting setting = settings.get(i); + settingsNBT.setTag(Integer.toString(i), setting.serialize()); + } + + NBT.setTag("Settings", settingsNBT); + } + + return NBT; + } + + public static ForgeOfGodsStarColor deserialize(NBTTagCompound NBT) { + if (NBT.hasKey("Preset")) { + return PRESETS.get(NBT.getString("Preset")); + } + + ForgeOfGodsStarColor color = new ForgeOfGodsStarColor(NBT.getString("Name")); + color.setCycleSpeed(NBT.getInteger("CycleSpeed")); + + if (NBT.hasKey("Settings")) { + NBTTagCompound settingsNBT = NBT.getCompoundTag("Settings"); + int size = settingsNBT.getInteger("Size"); + for (int i = 0; i < size; i++) { + NBTTagCompound colorNBT = settingsNBT.getCompoundTag(Integer.toString(i)); + StarColorSetting setting = StarColorSetting.deserialize(colorNBT); + color.settings.add(setting); + } + } + + return color; + } + + public String serializeToString() { + StringBuilder sb = new StringBuilder(); + sb.append("StarColorV1:{"); + sb.append("Name:"); + sb.append(getName()); + sb.append(",Cycle:"); + sb.append(getCycleSpeed()); + + for (StarColorSetting setting : settings) { + sb.append("|"); + sb.append("r:"); + sb.append(setting.getColorR()); + sb.append(",g:"); + sb.append(setting.getColorG()); + sb.append(",b:"); + sb.append(setting.getColorB()); + sb.append(",m:"); + sb.append(setting.getGamma()); + } + + sb.append("}"); + return sb.toString(); + } + + @Nullable + public static ForgeOfGodsStarColor deserialize(String raw) { + if (raw == null) return null; + if (!raw.startsWith("StarColorV1:{") || !raw.endsWith("}")) return null; + + // Wrap in try-catch for easy format "checking" + try { + String[] data = raw.substring(13, raw.length() - 1) + .split("\\|"); + + // Parse the header (name and cycle rate) + String header = data[0]; + String[] headerData = header.split(","); + + // Name + String name = null; + if (headerData[0].startsWith("Name:")) { + name = headerData[0].substring(5); + } + + // Cycle Rate + Integer cycleRate = null; + if (headerData[1].startsWith("Cycle:")) { + cycleRate = Integer.valueOf(headerData[1].substring(6)); + } + + List<StarColorSetting> colorSettings = new ArrayList<>(); + for (int i = 1; i < data.length; i++) { + String[] colorData = data[i].split(","); + int r = -1, g = -1, b = -1; + float m = -1; + for (String color : colorData) { + String[] singleData = color.split(":"); + switch (singleData[0]) { + case "r" -> r = Integer.parseInt(singleData[1]); + case "g" -> g = Integer.parseInt(singleData[1]); + case "b" -> b = Integer.parseInt(singleData[1]); + case "m" -> m = Float.parseFloat(singleData[1]); + } + } + if (r != -1 && g != -1 && b != -1 && m != -1) { + colorSettings.add(new StarColorSetting(r, g, b, m)); + } + } + + if (name != null && cycleRate != null && !colorSettings.isEmpty()) { + return new ForgeOfGodsStarColor(name).setCycleSpeed(cycleRate) + .addColors(colorSettings); + } + return null; + } catch (Throwable ignored) { + return null; + } + } + + public static void writeToBuffer(PacketBuffer buf, ForgeOfGodsStarColor color) { + buf.writeBoolean(color == null); + if (color != null) { + buf.writeBoolean(color.isPresetColor()); + try { + buf.writeStringToBuffer(color.name); + } catch (IOException ignored) {} + + if (!color.isPresetColor()) { + buf.writeInt(color.cycleSpeed); + buf.writeInt(color.settings.size()); + for (StarColorSetting setting : color.settings) { + StarColorSetting.writeToBuffer(buf, setting); + } + } + } + } + + public static ForgeOfGodsStarColor readFromBuffer(PacketBuffer buf) { + if (buf.readBoolean()) return null; + boolean isPresetColor = buf.readBoolean(); + String name; + try { + name = buf.readStringFromBuffer(32767); + } catch (IOException ignored) { + return null; + } + + if (isPresetColor) { + return PRESETS.get(name); + } + + ForgeOfGodsStarColor color = new ForgeOfGodsStarColor(name); + color.setCycleSpeed(buf.readInt()); + int size = buf.readInt(); + for (int i = 0; i < size; i++) { + color.addColor(StarColorSetting.readFromBuffer(buf)); + } + return color; + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/StarColorSetting.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/StarColorSetting.java new file mode 100644 index 0000000000..b096d80fbd --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/StarColorSetting.java @@ -0,0 +1,89 @@ +package tectech.thing.metaTileEntity.multi.godforge.color; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +public class StarColorSetting { + + private final int r, g, b; + private final float gamma; + + public StarColorSetting(int r, int g, int b, float gamma) { + this.r = r; + this.g = g; + this.b = b; + this.gamma = gamma; + } + + public int getColorR() { + return r; + } + + public int getColorG() { + return g; + } + + public int getColorB() { + return b; + } + + public float getGamma() { + return gamma; + } + + protected NBTTagCompound serialize() { + NBTTagCompound NBT = new NBTTagCompound(); + NBT.setInteger("R", r); + NBT.setInteger("G", g); + NBT.setInteger("B", b); + NBT.setFloat("Gamma", gamma); + return NBT; + } + + protected static StarColorSetting deserialize(NBTTagCompound NBT) { + int r = NBT.getInteger("R"); + int g = NBT.getInteger("G"); + int b = NBT.getInteger("B"); + float gamma = NBT.getFloat("Gamma"); + return new StarColorSetting(r, g, b, gamma); + } + + public static void writeToBuffer(PacketBuffer buf, StarColorSetting color) { + buf.writeInt(color.r); + buf.writeInt(color.g); + buf.writeInt(color.b); + buf.writeFloat(color.gamma); + } + + public static StarColorSetting readFromBuffer(PacketBuffer buf) { + int r = buf.readInt(); + int g = buf.readInt(); + int b = buf.readInt(); + float gamma = buf.readFloat(); + return new StarColorSetting(r, g, b, gamma); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + StarColorSetting that = (StarColorSetting) o; + + if (r != that.r) return false; + if (g != that.g) return false; + if (b != that.b) return false; + return gamma == that.gamma; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("r", r) + .append("g", g) + .append("b", b) + .append("gamma", gamma) + .build(); + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/StarColorStorage.java b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/StarColorStorage.java new file mode 100644 index 0000000000..a7a4e25298 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/godforge/color/StarColorStorage.java @@ -0,0 +1,130 @@ +package tectech.thing.metaTileEntity.multi.godforge.color; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; + +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; + +public class StarColorStorage { + + public static final int MAX_STAR_COLORS = 7; + private static final String NBT_LIST_KEY = "customStarColors"; + + private final Map<String, ForgeOfGodsStarColor> nameMapping = new HashMap<>(MAX_STAR_COLORS); + private List<ForgeOfGodsStarColor> indexMapping = new ArrayList<>(MAX_STAR_COLORS); + + public StarColorStorage() { + initPresets(); + } + + private void initPresets() { + List<ForgeOfGodsStarColor> presets = ForgeOfGodsStarColor.getDefaultColors(); + for (ForgeOfGodsStarColor preset : presets) { + nameMapping.put(preset.getName(), preset); + indexMapping.add(preset); + } + } + + public ForgeOfGodsStarColor newTemplateColor() { + String name = "New Star Color"; + for (int i = 0; i < MAX_STAR_COLORS; i++) { + if (nameMapping.containsKey(name)) { + name = "New Star Color " + (i + 1); + } else break; + } + return new ForgeOfGodsStarColor(name); + } + + /** Store a unique star color. Will append numbers to the name to guarantee a unique name. */ + public void store(ForgeOfGodsStarColor color) { + indexMapping.add(color); + if (!nameMapping.containsKey(color.getName())) { + nameMapping.put(color.getName(), color); + return; + } + for (int i = 0; i < MAX_STAR_COLORS; i++) { + String newName = color.getName() + " " + (i + 1); + if (!nameMapping.containsKey(newName)) { + nameMapping.put(newName, color); + color.setName(newName); + return; + } + } + } + + /** Insert a star color at a given position. */ + public void insert(ForgeOfGodsStarColor color, int pos) { + ForgeOfGodsStarColor existing = indexMapping.set(pos, color); + if (existing != null) { + nameMapping.remove(existing.getName()); + nameMapping.put(color.getName(), color); + } + } + + public void drop(ForgeOfGodsStarColor color) { + ForgeOfGodsStarColor existing = nameMapping.remove(color.getName()); + if (existing != null) { + indexMapping.remove(existing); + } + } + + public ForgeOfGodsStarColor getByName(String name) { + return nameMapping.get(name); + } + + public ForgeOfGodsStarColor getByIndex(int index) { + return indexMapping.get(index); + } + + public boolean isFull() { + return indexMapping.size() >= MAX_STAR_COLORS; + } + + public int size() { + return indexMapping.size(); + } + + public void serializeToNBT(NBTTagCompound NBT) { + NBTTagList tagList = new NBTTagList(); + for (ForgeOfGodsStarColor color : indexMapping) { + if (color.isPresetColor()) continue; + tagList.appendTag(color.serializeToNBT()); + } + if (tagList.tagCount() > 0) { + NBT.setTag(NBT_LIST_KEY, tagList); + } + } + + public void rebuildFromNBT(NBTTagCompound NBT) { + nameMapping.clear(); + indexMapping.clear(); + initPresets(); + + if (NBT.hasKey(NBT_LIST_KEY)) { + NBTTagList tagList = NBT.getTagList(NBT_LIST_KEY, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound colorNBT = tagList.getCompoundTagAt(i); + ForgeOfGodsStarColor color = ForgeOfGodsStarColor.deserialize(colorNBT); + if (!color.isPresetColor()) { + store(color); + } + } + } + } + + public FakeSyncWidget<?> getSyncer() { + return new FakeSyncWidget.ListSyncer<>(() -> indexMapping, val -> { + indexMapping = val; + nameMapping.clear(); + for (ForgeOfGodsStarColor color : indexMapping) { + nameMapping.put(color.getName(), color); + } + }, ForgeOfGodsStarColor::writeToBuffer, ForgeOfGodsStarColor::readFromBuffer); + } +} |