diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2d680e95b..f20874363 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -30,7 +30,7 @@ jobs: if: endswith(github.ref_name, 'master') && github.ref_protected && github.ref_type == 'branch' runs-on: ubuntu-latest env: - APPVEYOR_BUILD_VERSION: '3.6.1' + APPVEYOR_BUILD_VERSION: '3.6.2' CURSETOKEN: ${{ secrets.CURSETOKEN }} steps: - uses: actions/checkout@v3 diff --git a/changelog.md b/changelog.md index 0b7d3ae70..7dee7cd97 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,36 @@ # Changelog +## [1.18.2 - 3.6.2] +* feat: added train length signs +* feat: added trainnumber element +* feat: added configurable shunting pw color +* feat: added system to select pathway type when several are possible +* fix: problems with 'dead signal' +* fix: end is not a valid end point +* fix: disappearing signals in signalbox +* fix: issue in signal configs +* fix: skipping same signals +* fix: issue with names not shown every time +* fix: issue with trainnumbers +* fix: problem with shunting and normal pathway +* fix: UI line and background coloring +* fix: issue with delay intersignalbox pathway +* fix: issue with wrong feedback signal +* fix: intersignalbox can be added to saver +* fix: delay with shunting pathway +* fix: wn signals +* fix: item dropping +* fix: sh statuslight wrong lamp +* fix: issues with intersignalbox pathway +* fix: not updating signals in signalbox +* ref: remove CUSTOMNAME from saving into files +* ref: better signalbox UI +* ref: better error handling +* ref: better code performance +* ref: added arrow to possible shunting pathway end +* ref: better signalbox NBT saving +* ref: better signalbox loading system for names and signals + ## [1.18.2 - 3.6.1] * fix: issue with InterSignalBoxPathway diff --git a/guilib b/guilib index 1b09607c2..3f5cf814b 160000 --- a/guilib +++ b/guilib @@ -1 +1 @@ -Subproject commit 1b09607c2b91dbecbd91eb4fcc77b0c15a912459 +Subproject commit 3f5cf814b7689b745bc3280ca95bb9cacac3ca30 diff --git a/src/main/java/com/troblecodings/signals/blocks/BasicBlock.java b/src/main/java/com/troblecodings/signals/blocks/BasicBlock.java index bac211eb4..8ebfdf72d 100644 --- a/src/main/java/com/troblecodings/signals/blocks/BasicBlock.java +++ b/src/main/java/com/troblecodings/signals/blocks/BasicBlock.java @@ -1,7 +1,9 @@ package com.troblecodings.signals.blocks; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -9,17 +11,21 @@ import com.troblecodings.signals.core.TileEntitySupplierWrapper; import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.LootContext; public class BasicBlock extends Block implements EntityBlock { private static final Map BLOCK_NAMES = new HashMap<>(); - private static final Map> BLOCK_SUPPLIER = new HashMap<>(); - public static final Map> BLOCK_ENTITYS = new HashMap<>(); + private static final Map> BLOCK_SUPPLIER = + new HashMap<>(); + public static final Map> BLOCK_ENTITYS = + new HashMap<>(); public BasicBlock(final Properties properties) { super(properties); @@ -63,4 +69,11 @@ public static void prepare() { public BlockEntity newBlockEntity(final BlockPos pos, final BlockState state) { return getSupplierWrapper().map(type -> type.create(pos, state)).orElse(null); } + + @Override + public List getDrops(final BlockState state, final LootContext.Builder builder) { + List drops = new ArrayList(); + drops.add(new ItemStack(this.asBlock().asItem())); + return drops; + } } \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/config/ConfigHandler.java b/src/main/java/com/troblecodings/signals/config/ConfigHandler.java index 5f81fee5c..cae76ea4f 100644 --- a/src/main/java/com/troblecodings/signals/config/ConfigHandler.java +++ b/src/main/java/com/troblecodings/signals/config/ConfigHandler.java @@ -46,6 +46,8 @@ public static class Client { public final ConfigValue signalboxUsedColor; public final ConfigValue signalboxPreparedColor; public final ConfigValue signalboxTrainNumberColor; + public final ConfigValue signalboxShuntingColor; + public final ConfigValue signalboxTrainnumberBackgroundColor; public Client(final ForgeConfigSpec.Builder builder) { String desc; @@ -69,9 +71,17 @@ public Client(final ForgeConfigSpec.Builder builder) { signalboxPreparedColor = builder.comment(desc).define("Signalbox prepared color", 0xffff00); - desc = "Change the color of the TrainNumber in the UI. Default: -1"; - signalboxTrainNumberColor = builder.comment(desc).define("Signalbox TrainNumber color", - 0xFFFFFFFF); + desc = "Change the color of a selected shunting path. Default: -16711936"; + signalboxShuntingColor = builder.comment(desc).define("Signalbox shunting color", + 0xFF00FF00); + + desc = "Change the color of trainnumber in the signalbox. Default: -65536"; + signalboxTrainNumberColor = builder.comment(desc) + .define("Signalbox trainnumber text color", 0xFFFF0000); + + desc = "Change the background color of trainnumber in the signalbox. Default: -11534336"; + signalboxTrainnumberBackgroundColor = builder.comment(desc) + .define("Signalbox trainnumber background color", 0xFF500000); desc = "Change the color of a default text. Default: -16777216"; GuiConfigHandler.basicTextColor = builder.comment(desc).define("Basic text color", @@ -91,4 +101,4 @@ public Client(final ForgeConfigSpec.Builder builder) { } -} +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/contentpacks/ChangeConfigParser.java b/src/main/java/com/troblecodings/signals/contentpacks/ChangeConfigParser.java index 840c9be78..ba8eaf1a8 100644 --- a/src/main/java/com/troblecodings/signals/contentpacks/ChangeConfigParser.java +++ b/src/main/java/com/troblecodings/signals/contentpacks/ChangeConfigParser.java @@ -53,97 +53,105 @@ public static void loadChangeConfigs() { private static void loadConfigForPair(final String fileName, final String currentSignal, final String nextSignal, final Map savedPredicates, final Map> values) { - final Signal start = Signal.SIGNALS.get(currentSignal.toLowerCase()); - final Signal end = Signal.SIGNALS.get(nextSignal.toLowerCase()); - if (start == null || end == null) { - OpenSignalsMain.getLogger() - .warn("The signal '" + nextSignal + "' or the signal '" + nextSignal - + "' doen't exists! " + "This config with filename '" + fileName - + "' will be skiped!"); - return; - } - final Map.Entry pair = Maps.immutableEntry(start, end); - if (CHANGECONFIGS.containsKey(pair)) { - throw new LogicalParserException( - "A signalconfig with the signals [" + start.getSignalTypeName() + ", " - + end.getSignalTypeName() + "] does alredy exists! '" + fileName - + "' tried to register a chaneconfig for the same signalpair!"); - } - final FunctionParsingInfo startInfo = new FunctionParsingInfo(start); - final FunctionParsingInfo endInfo = new FunctionParsingInfo( - LogicParser.UNIVERSAL_TRANSLATION_TABLE, end); - final List properties = new ArrayList<>(); - - for (final Map.Entry> entry : values.entrySet()) { - - String valueToParse = entry.getKey().toLowerCase(); - Predicate, Object>> predicate = t -> true; - - if (valueToParse.contains("map(") && savedPredicates != null - && !savedPredicates.isEmpty()) { - final char[] chars = entry.getKey().toCharArray(); - String names = ""; - boolean readKey = false; - final StringBuilder builder = new StringBuilder(); - String mapKey = ""; - for (final char letter : chars) { - - final String current = builder.append(letter).toString(); - final boolean isOpenBracket = current.equals("("); - final boolean isCloseBracket = current.equals(")"); - builder.setLength(0); - - if (readKey) { - try { - if (isCloseBracket) { - valueToParse = valueToParse.replace("map(" + mapKey + ")", - "(" + savedPredicates.get(mapKey).toLowerCase() + ")"); - names = ""; - mapKey = ""; - readKey = false; + try { + + final Signal start = Signal.SIGNALS.get(currentSignal.toLowerCase()); + final Signal end = Signal.SIGNALS.get(nextSignal.toLowerCase()); + if (start == null || end == null) { + OpenSignalsMain.getLogger() + .warn("The signal '" + nextSignal + "' or the signal '" + nextSignal + + "' doen't exists! " + "This config with filename '" + fileName + + "' will be skiped!"); + return; + } + final Map.Entry pair = Maps.immutableEntry(start, end); + if (CHANGECONFIGS.containsKey(pair)) { + throw new LogicalParserException( + "A signalconfig with the signals [" + start.getSignalTypeName() + ", " + + end.getSignalTypeName() + "] does alredy exists! '" + fileName + + "' tried to register a chaneconfig for the same signalpair!"); + } + final FunctionParsingInfo startInfo = new FunctionParsingInfo(start); + final FunctionParsingInfo endInfo = new FunctionParsingInfo( + LogicParser.UNIVERSAL_TRANSLATION_TABLE, end); + final List properties = new ArrayList<>(); + + for (final Map.Entry> entry : values.entrySet()) { + + String valueToParse = entry.getKey().toLowerCase(); + Predicate, Object>> predicate = t -> true; + + if (valueToParse.contains("map(") && savedPredicates != null + && !savedPredicates.isEmpty()) { + final char[] chars = entry.getKey().toCharArray(); + String names = ""; + boolean readKey = false; + final StringBuilder builder = new StringBuilder(); + String mapKey = ""; + for (final char letter : chars) { + + final String current = builder.append(letter).toString(); + final boolean isOpenBracket = current.equals("("); + final boolean isCloseBracket = current.equals(")"); + builder.setLength(0); + + if (readKey) { + try { + if (isCloseBracket) { + valueToParse = valueToParse.replace("map(" + mapKey + ")", + "(" + savedPredicates.get(mapKey).toLowerCase() + ")"); + names = ""; + mapKey = ""; + readKey = false; + continue; + } + mapKey += current; continue; + } catch (final Exception e) { + OpenSignalsMain.exitMinecraftWithMessage( + "Something went wrong with the predicate saver in " + + fileName + "! Did you used it correctly?"); } - mapKey += current; + } + if (current.equals("(") && names.equals("map")) { + readKey = true; + mapKey = ""; continue; - } catch (final Exception e) { - OpenSignalsMain.exitMinecraftWithMessage( - "Something went wrong with the predicate saver in " + fileName - + "! Did you used it correctly?"); } + final boolean isBracket = isCloseBracket || isOpenBracket; + if (Character.isWhitespace(letter) || current.equals("!") || isBracket) { + names = ""; + mapKey = ""; + continue; + } + names += current; } - if (current.equals("(") && names.equals("map")) { - readKey = true; - mapKey = ""; - continue; - } - final boolean isBracket = isCloseBracket || isOpenBracket; - if (Character.isWhitespace(letter) || current.equals("!") || isBracket) { - names = ""; - mapKey = ""; - continue; - } - names += current; } - } - if (valueToParse != null && !valueToParse.isEmpty() - && !valueToParse.equalsIgnoreCase("true")) { - predicate = LogicParser.predicate(valueToParse, endInfo); - } + if (valueToParse != null && !valueToParse.isEmpty() + && !valueToParse.equalsIgnoreCase("true")) { + predicate = LogicParser.predicate(valueToParse, endInfo); + } - final Map propertiesToSet = new HashMap<>(); + final Map propertiesToSet = new HashMap<>(); - for (final String value : entry.getValue()) { + for (final String value : entry.getValue()) { - final String[] valuetoChange = value.split("\\."); - final SEProperty property = (SEProperty) startInfo.getProperty(valuetoChange[0]); - propertiesToSet.put(property, valuetoChange[1]); - } + final String[] valuetoChange = value.split("\\."); + final SEProperty property = (SEProperty) startInfo + .getProperty(valuetoChange[0]); + propertiesToSet.put(property, valuetoChange[1]); + } - properties.add(new ConfigProperty(predicate, propertiesToSet)); + properties.add(new ConfigProperty(predicate, propertiesToSet)); + } + CHANGECONFIGS.put(pair, properties); + } catch (final Exception e) { + OpenSignalsMain.getLogger().error("There was a problem loading the ChangeConfig [" + + fileName + "]! Please check the file!"); + e.printStackTrace(); } - CHANGECONFIGS.put(pair, properties); } private static class ChangeConfigParserV2 { diff --git a/src/main/java/com/troblecodings/signals/contentpacks/OneSignalNonPredicateConfigParser.java b/src/main/java/com/troblecodings/signals/contentpacks/OneSignalNonPredicateConfigParser.java index 94f0ada7e..070794509 100644 --- a/src/main/java/com/troblecodings/signals/contentpacks/OneSignalNonPredicateConfigParser.java +++ b/src/main/java/com/troblecodings/signals/contentpacks/OneSignalNonPredicateConfigParser.java @@ -59,38 +59,45 @@ public static void loadOneSignalNonPredicateConfig(final Map> map, - final String fileName, final String currentSignal, final List values) { - final Signal signal = checkSignal(currentSignal, fileName); - if (signal == null) - return; - - if (map.containsKey(signal)) { - throw new LogicalParserException("A signalconfig with the signals [" - + signal.getSignalTypeName() + "] does alredy exists! '" + fileName - + "' tried to register the same signalconfig!"); - } + final String fileName, final String currentSignal, final List values, + final String path) { + try { + final Signal signal = checkSignal(currentSignal, fileName); + if (signal == null) + return; + + if (map.containsKey(signal)) { + throw new LogicalParserException("A signalconfig with the signals [" + + signal.getSignalTypeName() + "] does alredy exists! '" + fileName + + "' tried to register the same signalconfig!"); + } - final FunctionParsingInfo info = new FunctionParsingInfo(signal); - final List propertes = new ArrayList<>(); - for (final String property : values) { - final String[] value = property.split("\\."); - propertes.add(new ConfigProperty(t -> true, - ImmutableMap.of((SEProperty) info.getProperty(value[0]), value[1]))); + final FunctionParsingInfo info = new FunctionParsingInfo(signal); + final List propertes = new ArrayList<>(); + for (final String property : values) { + final String[] value = property.split("\\."); + propertes.add(new ConfigProperty(t -> true, + ImmutableMap.of((SEProperty) info.getProperty(value[0]), value[1]))); + } + map.put(signal, propertes); + } catch (final Exception e) { + OpenSignalsMain.getLogger().error("There was a problem loading the config [" + fileName + + "] located in [" + path + "]! Please check the file!"); + e.printStackTrace(); } - map.put(signal, propertes); } private static Signal checkSignal(final String signalName, final String filename) { diff --git a/src/main/java/com/troblecodings/signals/contentpacks/OneSignalPredicateConfigParser.java b/src/main/java/com/troblecodings/signals/contentpacks/OneSignalPredicateConfigParser.java index b977c0925..35fcce73c 100644 --- a/src/main/java/com/troblecodings/signals/contentpacks/OneSignalPredicateConfigParser.java +++ b/src/main/java/com/troblecodings/signals/contentpacks/OneSignalPredicateConfigParser.java @@ -47,7 +47,7 @@ public static void loadOneSignalPredicateConfigEntry( OneSignalPredicateConfigParserV2.class); for (final String currentSignal : parser.currentSignals) { loadConfig(map, files.getKey(), currentSignal, parser.savedPredicates, - parser.values); + parser.values, path); } } catch (final Exception e) { OpenSignalsMain.getLogger().error("Please update your config [" + files.getKey() @@ -55,99 +55,108 @@ public static void loadOneSignalPredicateConfigEntry( final OneSignalPredicateConfigParser parser = GSON.fromJson(files.getValue(), OneSignalPredicateConfigParser.class); loadConfig(map, files.getKey(), parser.currentSignal, parser.savedPredicates, - parser.values); + parser.values, path); } } private static void loadConfig(final Map> map, final String fileName, final String currentSignal, - final Map savedPredicates, final Map> values) { - final Signal signal = Signal.SIGNALS.get(currentSignal.toLowerCase()); - if (signal == null) { - OpenSignalsMain.getLogger().warn("The signal '" + currentSignal + "' doesn't exists! " - + "This config with the filename '" + fileName + "' will be skiped!"); - return; - } - if (map.containsKey(signal)) { - throw new LogicalParserException("A signalconfig with the signals [" - + signal.getSignalTypeName() + "] does alredy exists! '" + fileName - + "' tried to register a defaultconfig for the same signal!"); - } - final FunctionParsingInfo info = new FunctionParsingInfo( - LogicParser.UNIVERSAL_TRANSLATION_TABLE, signal); - final List properties = new ArrayList<>(); - - for (final Map.Entry> entry : values.entrySet()) { - - String valueToParse = entry.getKey().toLowerCase(); - Predicate, Object>> predicate = t -> true; - - if (valueToParse.contains("map(") && savedPredicates != null - && !savedPredicates.isEmpty()) { - final char[] chars = entry.getKey().toCharArray(); - String names = ""; - boolean readKey = false; - final StringBuilder builder = new StringBuilder(); - String mapKey = ""; - for (final char letter : chars) { - - final String current = builder.append(letter).toString(); - final boolean isOpenBracket = current.equals("("); - final boolean isCloseBracket = current.equals(")"); - builder.setLength(0); - - if (readKey) { - try { - if (isCloseBracket) { - valueToParse = valueToParse.replace("map(" + mapKey + ")", - "(" + savedPredicates.get(mapKey).toLowerCase() + ")"); - names = ""; - mapKey = ""; - readKey = false; + final Map savedPredicates, final Map> values, + final String path) { + try { + final Signal signal = Signal.SIGNALS.get(currentSignal.toLowerCase()); + if (signal == null) { + OpenSignalsMain.getLogger() + .warn("The signal '" + currentSignal + "' doesn't exists! " + + "This config with the filename '" + fileName + + "' will be skiped!"); + return; + } + if (map.containsKey(signal)) { + throw new LogicalParserException("A signalconfig with the signals [" + + signal.getSignalTypeName() + "] does alredy exists! '" + fileName + + "' tried to register a defaultconfig for the same signal!"); + } + final FunctionParsingInfo info = new FunctionParsingInfo( + LogicParser.UNIVERSAL_TRANSLATION_TABLE, signal); + final List properties = new ArrayList<>(); + + for (final Map.Entry> entry : values.entrySet()) { + + String valueToParse = entry.getKey().toLowerCase(); + Predicate, Object>> predicate = t -> true; + + if (valueToParse.contains("map(") && savedPredicates != null + && !savedPredicates.isEmpty()) { + final char[] chars = entry.getKey().toCharArray(); + String names = ""; + boolean readKey = false; + final StringBuilder builder = new StringBuilder(); + String mapKey = ""; + for (final char letter : chars) { + + final String current = builder.append(letter).toString(); + final boolean isOpenBracket = current.equals("("); + final boolean isCloseBracket = current.equals(")"); + builder.setLength(0); + + if (readKey) { + try { + if (isCloseBracket) { + valueToParse = valueToParse.replace("map(" + mapKey + ")", + "(" + savedPredicates.get(mapKey).toLowerCase() + ")"); + names = ""; + mapKey = ""; + readKey = false; + continue; + } + mapKey += current; continue; + } catch (final Exception e) { + OpenSignalsMain.exitMinecraftWithMessage( + "Something went wrong with the predicate saver in " + + fileName + "! Did you used it correctly?"); } - mapKey += current; + } + if (current.equals("(") && names.equals("map")) { + readKey = true; + mapKey = ""; continue; - } catch (final Exception e) { - OpenSignalsMain.exitMinecraftWithMessage( - "Something went wrong with the predicate saver in " + fileName - + "! Did you used it correctly?"); } + final boolean isBracket = isCloseBracket || isOpenBracket; + if (Character.isWhitespace(letter) || current.equals("!") || isBracket) { + names = ""; + mapKey = ""; + continue; + } + names += current; } - if (current.equals("(") && names.equals("map")) { - readKey = true; - mapKey = ""; - continue; - } - final boolean isBracket = isCloseBracket || isOpenBracket; - if (Character.isWhitespace(letter) || current.equals("!") || isBracket) { - names = ""; - mapKey = ""; - continue; - } - names += current; } - } - if (valueToParse != null && !valueToParse.isEmpty() - && !valueToParse.equalsIgnoreCase("true")) { - predicate = LogicParser.predicate(valueToParse, info); - } + if (valueToParse != null && !valueToParse.isEmpty() + && !valueToParse.equalsIgnoreCase("true")) { + predicate = LogicParser.predicate(valueToParse, info); + } - final Map propertiesToSet = new HashMap<>(); + final Map propertiesToSet = new HashMap<>(); - for (final String value : entry.getValue()) { + for (final String value : entry.getValue()) { - final String[] valuetoChange = value.split("\\."); - final SEProperty property = (SEProperty) info.getProperty(valuetoChange[0]); - propertiesToSet.put(property, valuetoChange[1]); - } + final String[] valuetoChange = value.split("\\."); + final SEProperty property = (SEProperty) info.getProperty(valuetoChange[0]); + propertiesToSet.put(property, valuetoChange[1]); + } - properties.add(new ConfigProperty(predicate, propertiesToSet)); + properties.add(new ConfigProperty(predicate, propertiesToSet)); + } + map.put(signal, properties); + } catch (final Exception e) { + OpenSignalsMain.getLogger().error("There was a problem loading the config [" + fileName + + "] located in [" + path + "]! Please check the file!"); + e.printStackTrace(); } - map.put(signal, properties); } private static class OneSignalPredicateConfigParserV2 { diff --git a/src/main/java/com/troblecodings/signals/contentpacks/SubsidiarySignalParser.java b/src/main/java/com/troblecodings/signals/contentpacks/SubsidiarySignalParser.java index 779d254d8..0535ea408 100644 --- a/src/main/java/com/troblecodings/signals/contentpacks/SubsidiarySignalParser.java +++ b/src/main/java/com/troblecodings/signals/contentpacks/SubsidiarySignalParser.java @@ -34,27 +34,33 @@ private static void loadSubsidiaryStates() { OldSubsidiaryEnumParser.class); parser.subsidiaryStates.forEach(name -> new SubsidiaryState(name)); } - }); } public static void loadAllSubsidiarySignals() { loadSubsidiaryStates(); OpenSignalsMain.contentPacks.getFiles("signalconfigs/subsidiary").forEach(entry -> { - final SubsidiarySignalParser parser = GSON.fromJson(entry.getValue(), - SubsidiarySignalParser.class); - final Signal signal = Signal.SIGNALS.get(parser.currentSignal.toLowerCase()); - if (signal == null) - OpenSignalsMain.exitMinecraftWithMessage( - "There doesn't exists a signal with the name '" + parser.currentSignal - + "'! Valid Signals are: " + Signal.SIGNALS.keySet()); - if (SUBSIDIARY_SIGNALS.containsKey(signal)) - OpenSignalsMain.exitMinecraftWithMessage( - "There already exists a Subsidiary Config for " + signal + "!"); - final FunctionParsingInfo info = new FunctionParsingInfo(signal); - parser.allStates.forEach((name, properties) -> { - convertToProperites(signal, info, properties, name); - }); + try { + final SubsidiarySignalParser parser = GSON.fromJson(entry.getValue(), + SubsidiarySignalParser.class); + final Signal signal = Signal.SIGNALS.get(parser.currentSignal.toLowerCase()); + if (signal == null) + OpenSignalsMain.exitMinecraftWithMessage( + "There doesn't exists a signal with the name '" + parser.currentSignal + + "'! Valid Signals are: " + Signal.SIGNALS.keySet()); + if (SUBSIDIARY_SIGNALS.containsKey(signal)) + OpenSignalsMain.exitMinecraftWithMessage( + "There already exists a Subsidiary Config for " + signal + "!"); + final FunctionParsingInfo info = new FunctionParsingInfo(signal); + parser.allStates.forEach((name, properties) -> { + convertToProperites(signal, info, properties, name); + }); + } catch (final Exception e) { + OpenSignalsMain.getLogger().error("There was a problem loading the config [" + + entry.getKey() + + "] located in [signalconfigs/subsidiary]! Please check the file!"); + e.printStackTrace(); + } }); } diff --git a/src/main/java/com/troblecodings/signals/core/BlockPosSignalHolder.java b/src/main/java/com/troblecodings/signals/core/BlockPosSignalHolder.java new file mode 100644 index 000000000..7edecffec --- /dev/null +++ b/src/main/java/com/troblecodings/signals/core/BlockPosSignalHolder.java @@ -0,0 +1,46 @@ +package com.troblecodings.signals.core; + +import java.util.Objects; + +import net.minecraft.core.BlockPos; + +public class BlockPosSignalHolder { + + public final BlockPos pos; + private boolean turnSignalOff; + + public BlockPosSignalHolder(final BlockPos pos) { + this(pos, false); + } + + public BlockPosSignalHolder(final BlockPos pos, final boolean turnSignalOff) { + this.pos = pos; + this.turnSignalOff = turnSignalOff; + } + + public void setTurnSignalOff() { + turnSignalOff = true; + } + + public boolean shouldTurnSignalOff() { + return turnSignalOff; + } + + @Override + public int hashCode() { + return Objects.hash(pos, turnSignalOff); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final BlockPosSignalHolder other = (BlockPosSignalHolder) obj; + return Objects.equals(pos, other.pos) && turnSignalOff == other.turnSignalOff; + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/core/NameStateListener.java b/src/main/java/com/troblecodings/signals/core/NameStateListener.java new file mode 100644 index 000000000..2478e1c96 --- /dev/null +++ b/src/main/java/com/troblecodings/signals/core/NameStateListener.java @@ -0,0 +1,9 @@ +package com.troblecodings.signals.core; + +import com.troblecodings.signals.enums.ChangedState; + +public interface NameStateListener { + + public void update(final StateInfo info, final String name, final ChangedState state); + +} diff --git a/src/main/java/com/troblecodings/signals/core/SignalStateListener.java b/src/main/java/com/troblecodings/signals/core/SignalStateListener.java index 5f8dc0427..f186aff73 100644 --- a/src/main/java/com/troblecodings/signals/core/SignalStateListener.java +++ b/src/main/java/com/troblecodings/signals/core/SignalStateListener.java @@ -10,4 +10,11 @@ public interface SignalStateListener { public void update(final SignalStateInfo info, final Map changedProperties, final ChangedState changedState); + + default SignalStateListener andThen(final SignalStateListener otherTask) { + return (info, properties, state) -> { + this.update(info, properties, state); + otherTask.update(info, properties, state); + }; + } } \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/enums/EnumGuiMode.java b/src/main/java/com/troblecodings/signals/enums/EnumGuiMode.java index dc4ab5905..8a6765c6a 100644 --- a/src/main/java/com/troblecodings/signals/enums/EnumGuiMode.java +++ b/src/main/java/com/troblecodings/signals/enums/EnumGuiMode.java @@ -4,7 +4,9 @@ import com.troblecodings.guilib.ecs.entitys.render.UILines; import com.troblecodings.guilib.ecs.entitys.render.UITexture; import com.troblecodings.signals.core.OSSupplier; +import com.troblecodings.signals.guis.GuiSignalBox; import com.troblecodings.signals.guis.UISignalBoxTile; +import com.troblecodings.signals.signalbox.SignalBoxUtil; public enum EnumGuiMode { STRAIGHT(new float[] { @@ -13,32 +15,38 @@ public enum EnumGuiMode { 0, 0.5f, 0.5f, 1 }), END(new float[] { 0.9f, 0.2f, 0.9f, 0.8f - }), PLATFORM((state) -> new UILines(new float[] { + }, PathwayModeType.END, 0), PLATFORM((state) -> new UILines(new float[] { 0, 0.15f, 1, 0.15f - }, 3), PathwayModeType.NONE), BUE(new float[] { + }, 3).setColor(SignalBoxUtil.FREE_COLOR), PathwayModeType.NONE, 0), BUE(new float[] { 0.3f, 0, 0.3f, 1, 0.7f, 0, 0.7f, 1 - }), HP(0, true, PathwayModeType.START_END), VP(1, true, PathwayModeType.NONE), - RS(2, true, PathwayModeType.START_END), RA10(3, PathwayModeType.END), - SH2(4, PathwayModeType.NONE), - IN_CONNECTION((_u) -> new UITexture(UISignalBoxTile.INCOMING_ICON), PathwayModeType.START), - OUT_CONNECTION((_u) -> new UITexture(UISignalBoxTile.OUTGOING_ICON), PathwayModeType.END), - ARROW((_u) -> new UITexture(UISignalBoxTile.ARROW_ICON), PathwayModeType.END), - NE1((_u) -> new UITexture(UISignalBoxTile.NE1_ICON), PathwayModeType.START_END), - NE5((_u) -> new UITexture(UISignalBoxTile.NE5_ICON), PathwayModeType.START_END), - ZS3((_u) -> new UITexture(UISignalBoxTile.ZS3_ICON), PathwayModeType.NONE); + }), HP(0, true, PathwayModeType.START_END, 2), VP(1, true, PathwayModeType.NONE, 1), + RS(2, true, PathwayModeType.START_END, 1), RA10(3, PathwayModeType.END, 1), + SH2(4, PathwayModeType.NONE, 1), + IN_CONNECTION((_u) -> new UITexture(UISignalBoxTile.INCOMING_ICON), PathwayModeType.START, 1), + OUT_CONNECTION((_u) -> new UITexture(UISignalBoxTile.OUTGOING_ICON), PathwayModeType.END, 1), + ARROW((_u) -> new UITexture(UISignalBoxTile.ARROW_ICON), PathwayModeType.END, 1), + NE1((_u) -> new UITexture(UISignalBoxTile.NE1_ICON), PathwayModeType.START_END, 1), + NE5((_u) -> new UITexture(UISignalBoxTile.NE5_ICON), PathwayModeType.START_END, 1), + ZS3((_u) -> new UITexture(UISignalBoxTile.ZS3_ICON), PathwayModeType.NONE, 1), + TRAIN_NUMBER((_u) -> new UILines(new float[] { + 0, 0.5f, 2, 0.5f + }, 6).setColor(GuiSignalBox.TRAIN_NUMBER_BACKGROUND_COLOR), PathwayModeType.NONE, 2); /** * Naming */ public final OSSupplier consumer; + public final int translation; private final PathwayModeType type; - private EnumGuiMode(final int id, final PathwayModeType type) { - this((_u) -> new UITexture(UISignalBoxTile.ICON, id * 0.2, 0, id * 0.2 + 0.2, 0.5), type); + private EnumGuiMode(final int id, final PathwayModeType type, final int translation) { + this((_u) -> new UITexture(UISignalBoxTile.ICON, id * 0.2, 0, id * 0.2 + 0.2, 0.5), type, + translation); } - private EnumGuiMode(final int id, final boolean unused, final PathwayModeType type) { + private EnumGuiMode(final int id, final boolean unused, final PathwayModeType type, + final int translation) { this((state) -> { switch (state) { case GREEN: { @@ -71,16 +79,22 @@ private EnumGuiMode(final int id, final boolean unused, final PathwayModeType ty default: return new UITexture(UISignalBoxTile.SIGNALS); } - }, type); + }, type, translation); } private EnumGuiMode(final float[] array) { - this((_u) -> new UILines(array, 2), PathwayModeType.NONE); + this(array, PathwayModeType.NONE, 0); } - private EnumGuiMode(final OSSupplier consumer, final PathwayModeType type) { + private EnumGuiMode(final float[] array, final PathwayModeType type, final int translation) { + this((_u) -> new UILines(array, 2).setColor(SignalBoxUtil.FREE_COLOR), type, translation); + } + + private EnumGuiMode(final OSSupplier consumer, final PathwayModeType type, + final int translation) { this.consumer = consumer; this.type = type; + this.translation = translation; } public PathwayModeType getModeType() { @@ -90,4 +104,4 @@ public PathwayModeType getModeType() { public static EnumGuiMode of(final ReadBuffer buffer) { return values()[buffer.getByteToUnsignedInt()]; } -} \ No newline at end of file +} diff --git a/src/main/java/com/troblecodings/signals/enums/EnumPathUsage.java b/src/main/java/com/troblecodings/signals/enums/EnumPathUsage.java index b6771b0f2..db71637f5 100644 --- a/src/main/java/com/troblecodings/signals/enums/EnumPathUsage.java +++ b/src/main/java/com/troblecodings/signals/enums/EnumPathUsage.java @@ -3,12 +3,13 @@ import static com.troblecodings.signals.signalbox.SignalBoxUtil.FREE_COLOR; import static com.troblecodings.signals.signalbox.SignalBoxUtil.PREPARED_COLOR; import static com.troblecodings.signals.signalbox.SignalBoxUtil.SELECTED_COLOR; +import static com.troblecodings.signals.signalbox.SignalBoxUtil.SHUNTING_COLOR; import static com.troblecodings.signals.signalbox.SignalBoxUtil.USED_COLOR; public enum EnumPathUsage { FREE(FREE_COLOR), SELECTED(SELECTED_COLOR), BLOCKED(USED_COLOR), PREPARED(PREPARED_COLOR), - PROTECTED(PREPARED_COLOR); + PROTECTED(PREPARED_COLOR), SHUNTING(SHUNTING_COLOR); private final int color; diff --git a/src/main/java/com/troblecodings/signals/enums/PathType.java b/src/main/java/com/troblecodings/signals/enums/PathType.java index badf44852..f7e928739 100644 --- a/src/main/java/com/troblecodings/signals/enums/PathType.java +++ b/src/main/java/com/troblecodings/signals/enums/PathType.java @@ -6,7 +6,7 @@ public enum PathType { NORMAL(EnumGuiMode.HP, EnumGuiMode.END, EnumGuiMode.IN_CONNECTION, EnumGuiMode.OUT_CONNECTION, EnumGuiMode.NE1, EnumGuiMode.NE5, EnumGuiMode.ARROW), - SHUNTING(EnumGuiMode.RS, EnumGuiMode.RA10, EnumGuiMode.END), NONE(); + SHUNTING(EnumGuiMode.RS, EnumGuiMode.RA10, EnumGuiMode.END, EnumGuiMode.ARROW), NONE(); private final EnumGuiMode[] modes; diff --git a/src/main/java/com/troblecodings/signals/enums/SignalBoxNetwork.java b/src/main/java/com/troblecodings/signals/enums/SignalBoxNetwork.java index 86261f58c..d82d8842a 100644 --- a/src/main/java/com/troblecodings/signals/enums/SignalBoxNetwork.java +++ b/src/main/java/com/troblecodings/signals/enums/SignalBoxNetwork.java @@ -6,6 +6,7 @@ public enum SignalBoxNetwork { SEND_PW_UPDATE, RESET_ALL_PW, SEND_CHANGED_MODES, REQUEST_LINKED_POS, PW_REQUEST_RESPONSE, REQUEST_SUBSIDIARY, SEND_ZS2_ENTRY, UPDATE_RS_OUTPUT, OUTPUT_UPDATE, RESET_SUBSIDIARY, SET_AUTO_POINT, SEND_NAME, SEND_BOOL_ENTRY, ADDED_TO_SAVER, REMOVE_SAVEDPW, SEND_POINT_ENTRY, - SET_SIGNALS, SEND_COUNTER, SEND_TRAIN_NUMBER, RESET_ALL_SIGNALS, SEND_POSIDENT_LIST; + SET_SIGNALS, SEND_COUNTER, SEND_TRAIN_NUMBER, RESET_ALL_SIGNALS, SEND_POSIDENT_LIST, + SEND_CONNECTED_TRAINNUMBERS; } \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/guis/ContainerSignalBox.java b/src/main/java/com/troblecodings/signals/guis/ContainerSignalBox.java index 7a95029d9..8368c99b4 100644 --- a/src/main/java/com/troblecodings/signals/guis/ContainerSignalBox.java +++ b/src/main/java/com/troblecodings/signals/guis/ContainerSignalBox.java @@ -24,6 +24,7 @@ import com.troblecodings.signals.core.TrainNumber; import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.enums.LinkType; +import com.troblecodings.signals.enums.PathType; import com.troblecodings.signals.enums.PathwayRequestResult; import com.troblecodings.signals.enums.SignalBoxNetwork; import com.troblecodings.signals.handler.SignalBoxHandler; @@ -49,7 +50,7 @@ public class ContainerSignalBox extends ContainerBase implements UIClientSync, I protected final Map> greenSignals = new HashMap<>(); protected final Map> possibleSubsidiaries = new HashMap<>(); protected final Map> enabledSubsidiaryTypes = new HashMap<>(); - protected final List> nextPathways = new ArrayList<>(); + protected final Map, PathType> nextPathways = new HashMap<>(); protected final Map> validInConnections = new HashMap<>(); protected SignalBoxGrid grid; private final Map propertiesForType = new HashMap<>(); @@ -90,11 +91,12 @@ public void sendAllDataToRemote() { buffer.putBlockPos(pos); buffer.putByte((byte) type.ordinal()); }); - final List> nextPathways = grid.getNextPathways(); + final Map, PathType> nextPathways = grid.getNextPathways(); buffer.putByte((byte) nextPathways.size()); - nextPathways.forEach(entry -> { + nextPathways.forEach((entry, pathType) -> { entry.getKey().writeNetwork(buffer); entry.getValue().writeNetwork(buffer); + buffer.putEnumValue(pathType); }); final Map> validInConnections = new HashMap<>(); positions.entrySet().stream().filter(entry -> entry.getValue().equals(LinkType.SIGNALBOX)) @@ -159,7 +161,8 @@ public void deserializeClient(final ReadBuffer buffer) { for (int i = 0; i < nextPathwaySize; i++) { final Point start = Point.of(buffer); final Point end = Point.of(buffer); - nextPathways.add(Maps.immutableEntry(start, end)); + final PathType type = buffer.getEnumValue(PathType.class); + nextPathways.put(Maps.immutableEntry(start, end), type); } final int validInConnectionsSize = buffer.getByteToUnsignedInt(); for (int i = 0; i < validInConnectionsSize; i++) { @@ -203,7 +206,7 @@ public void deserializeClient(final ReadBuffer buffer) { break; } case SEND_PW_UPDATE: { - colorUpdates.accept(grid.readUpdateNetwork(buffer, false)); + colorUpdates.accept(grid.readUpdateNetwork(buffer, true)); break; } case PW_REQUEST_RESPONSE: { @@ -215,7 +218,8 @@ public void deserializeClient(final ReadBuffer buffer) { final PathwayRequestResult result = buffer.getEnumValue(PathwayRequestResult.class); final Point start = Point.of(buffer); final Point end = Point.of(buffer); - nextPathways.add(Maps.immutableEntry(start, end)); + final PathType type = buffer.getEnumValue(PathType.class); + nextPathways.put(Maps.immutableEntry(start, end), type); infoUpdates.accept(I18Wrapper.format("error." + result.getName()) + " - " + I18Wrapper.format("info.pathwaysaver")); break; @@ -278,8 +282,7 @@ public void deserializeClient(final ReadBuffer buffer) { final int size = buffer.getInt(); for (int i = 0; i < size; i++) { final Point point = Point.of(buffer); - final TrainNumber number = TrainNumber.of(buffer); - grid.getNode(point).setTrainNumber(number); + grid.getNode(point).readNetwork(buffer); updates.add(point); } trainNumberUpdater.accept(updates); @@ -341,14 +344,18 @@ public void deserializeServer(final ReadBuffer buffer) { case REQUEST_PW: { final Point start = Point.of(buffer); final Point end = Point.of(buffer); - final PathwayRequestResult request = grid.requestWay(start, end); + final PathType type = buffer.getEnumValue(PathType.class); + final PathwayRequestResult request = grid.requestWay(start, end, type); if (!request.isPass()) { - if (request.canBeAddedToSaver() && grid.addNextPathway(start, end)) { + final SignalBoxNode endNode = grid.getNode(end); + if (request.canBeAddedToSaver() && !endNode.containsOutConnection() + && grid.addNextPathway(start, end, type)) { final WriteBuffer sucess = new WriteBuffer(); sucess.putEnumValue(SignalBoxNetwork.ADDED_TO_SAVER); sucess.putEnumValue(request); start.writeNetwork(sucess); end.writeNetwork(sucess); + sucess.putEnumValue(type); OpenSignalsMain.network.sendTo(info.player, sucess); break; } @@ -441,6 +448,10 @@ public void deserializeServer(final ReadBuffer buffer) { deserializeEntry(buffer, list); break; } + case SEND_CONNECTED_TRAINNUMBERS: { + deserializeEntry(buffer, ModeIdentifier.of(buffer)); + break; + } default: break; } diff --git a/src/main/java/com/troblecodings/signals/guis/GuiSignalBox.java b/src/main/java/com/troblecodings/signals/guis/GuiSignalBox.java index 8922ba9e7..23d767fcf 100644 --- a/src/main/java/com/troblecodings/signals/guis/GuiSignalBox.java +++ b/src/main/java/com/troblecodings/signals/guis/GuiSignalBox.java @@ -47,6 +47,8 @@ import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.enums.EnumPathUsage; import com.troblecodings.signals.enums.LinkType; +import com.troblecodings.signals.enums.PathType; +import com.troblecodings.signals.enums.PathwayRequestResult; import com.troblecodings.signals.enums.ShowTypes; import com.troblecodings.signals.enums.SignalBoxNetwork; import com.troblecodings.signals.enums.SignalBoxPage; @@ -73,6 +75,8 @@ public class GuiSignalBox extends GuiBase { public static final int GRID_COLOR = 0xFF5B5B5B; public static final int EDIT_COLOR = 0x5000A2FF; public static final int OUTPUT_COLOR = 0xffff00; + public static final int TRAIN_NUMBER_BACKGROUND_COLOR = ConfigHandler.CLIENT.signalboxTrainnumberBackgroundColor + .get(); public static final ResourceLocation REDSTONE_OFF = new ResourceLocation(OpenSignalsMain.MODID, "gui/textures/redstone_off.png"); @@ -115,7 +119,7 @@ private static float[] getLines() { private UIEntity mainButton; private final GuiInfo info; private final Map changedModes = new HashMap<>(); - private UIEntity splitter = new UIEntity(); + private final UIEntity splitter = new UIEntity(); private boolean allPacketsRecived = false; protected final Map allTiles = new HashMap<>(); private SidePanel helpPage; @@ -168,7 +172,9 @@ public void updateSignals(final Iterable updated) { private void updateTrainNumber(final List points) { points.forEach(point -> { final UISignalBoxTile tile = allTiles.get(point); - tile.updateTrainNumber(); + if (tile == null) + return; + tile.setNode(tile.getNode()); }); lowerEntity.update(); } @@ -284,7 +290,7 @@ private void tileNormal(final UIEntity tile, final UISignalBoxTile currentTile) return; } if (currentTile.isValidEnd()) { - sendPWRequest(currentTile.getNode()); + checkForMultiplePathTypes(lastTile.getNode(), currentTile.getNode()); this.resetTileSelection(); return; } @@ -293,6 +299,29 @@ private void tileNormal(final UIEntity tile, final UISignalBoxTile currentTile) tile.add(new UIClickable(e -> openNodeShortcuts(currentTile.getNode(), e), 1)); } + private void checkForMultiplePathTypes(final SignalBoxNode start, final SignalBoxNode end) { + final List possibleTypes = start.getPossibleTypes(end); + if (possibleTypes.isEmpty()) { + infoUpdate(I18Wrapper + .format("error." + PathwayRequestResult.NO_EQUAL_PATH_TYPE.getName())); + } else if (possibleTypes.size() == 1) { + sendPWRequest(lastTile.getPoint(), end.getPoint(), possibleTypes.get(0)); + } else if (possibleTypes.size() > 1) { + push(GuiElements.createScreen(entity -> { + entity.add(GuiElements.createButton(I18Wrapper.format("btn.return"), e -> pop())); + entity.add(GuiElements.createSpacerV(10)); + entity.add(GuiElements.createLabel(I18Wrapper.format("gui.signalbox.choosetypes"), + 0xffffff)); + entity.add(GuiElements.createSpacerV(10)); + possibleTypes + .forEach(type -> entity.add(GuiElements.createButton(type.name(), e -> { + sendPWRequest(start.getPoint(), end.getPoint(), type); + pop(); + }))); + })); + } + } + private void resetSelection(final UIEntity entity) { final UIEntity parent = entity.getParent(); parent.findRecursive(UIClickable.class).forEach(click -> click.setVisible(true)); @@ -399,35 +428,27 @@ private void initializePageSettings(final UIEntity entity, break; } case INPUT: { - initializePageSettings(entity, - container.getPositionForTypes().entrySet().stream() - .filter(entry -> entry.getValue().equals(LinkType.INPUT)) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + initializePageSettings(entity, container.getPositionForTypes().entrySet() + .stream().filter(entry -> entry.getValue().equals(LinkType.INPUT)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); break; } case OUTPUT: { - initializePageSettings(entity, - container.getPositionForTypes().entrySet().stream() - .filter(entry -> entry.getValue().equals(LinkType.OUTPUT)) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + initializePageSettings(entity, container.getPositionForTypes().entrySet() + .stream().filter(entry -> entry.getValue().equals(LinkType.OUTPUT)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); break; } case SIGNAL: { - initializePageSettings(entity, - container.getPositionForTypes().entrySet().stream() - .filter(entry -> entry.getValue().equals(LinkType.SIGNAL)) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + initializePageSettings(entity, container.getPositionForTypes().entrySet() + .stream().filter(entry -> entry.getValue().equals(LinkType.SIGNAL)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); break; } case SIGNALBOX: { - initializePageSettings(entity, - container.getPositionForTypes().entrySet().stream() - .filter(entry -> entry.getValue().equals(LinkType.SIGNALBOX)) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + initializePageSettings(entity, container.getPositionForTypes().entrySet() + .stream().filter(entry -> entry.getValue().equals(LinkType.SIGNALBOX)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); break; } default: @@ -529,11 +550,9 @@ private void initializeFieldEdit(final UIEntity entity) { helpPage.updateNextNode(menu.getSelection(), menu.getRotation()); this.lastTile = null; - bottomEntity.setHeight(24); - bottomEntity.setWidth(22 * EnumGuiMode.values().length + 2); - bottomEntity.add(new UIColor(BACKGROUND_COLOR)); + bottomEntity.setHeight(34); + bottomEntity.add(new UIColor(0xFF8B8B8B)); bottomEntity.add(new UIBorder(0xFF000000, 2)); - bottomEntity.add(menu); bottomEntity.getParent().update(); }); @@ -556,7 +575,7 @@ private void initializeFieldTemplate(final BiConsumer plane.setWidth(TILE_COUNT * TILE_WIDTH); plane.setHeight(TILE_COUNT * TILE_WIDTH); splitter.add(new UIScroll(s -> { - final float newScale = (float) (plane.getScaleX() + s * 0.05f); + final float newScale = (float) (plane.getScaleX() + s * 0.001f); if (newScale <= 0) return; plane.setScaleX(newScale); @@ -590,8 +609,9 @@ private void initializeFieldTemplate(final BiConsumer node = new SignalBoxNode(name); } final UISignalBoxTile sbt = new UISignalBoxTile(node); - if (!node.isEmpty()) + if (!node.isEmpty()) { allTiles.put(name, sbt); + } tile.add(sbt); sbt.setGreenSignals(container.greenSignals.getOrDefault(name, new ArrayList<>())); if (!node.getCustomText().isEmpty()) { @@ -605,7 +625,6 @@ private void initializeFieldTemplate(final BiConsumer } consumer.accept(tile, sbt); row.add(tile); - sbt.updateTrainNumber(); } plane.add(row); } @@ -652,10 +671,7 @@ private void initializeBasicUI() { header.add(mainButton); resetSelection(mainButton); - bottomEntity.setWidth(22 * EnumGuiMode.values().length); bottomEntity.setHeight(0); - bottomEntity.setX(-7); - bottomEntity.setScale(0.95f); final UIEntity middlePart = new UIEntity(); middlePart.setInheritHeight(true); @@ -674,6 +690,8 @@ private void initializeBasicUI() { this.entity.add(GuiElements.createSpacerH(10)); this.entity.add(new UIBox(UIBox.HBOX, 1)); helpPage.helpUsageMode(null); + + bottomEntity.setWidth(middlePart.getWidth() - 4); } private void disableBottomEntity() { @@ -682,13 +700,14 @@ private void disableBottomEntity() { bottomEntity.getParent().update(); } - private void sendPWRequest(final SignalBoxNode currentNode) { + private void sendPWRequest(final Point start, final Point end, final PathType type) { if (!allPacketsRecived) return; final WriteBuffer buffer = new WriteBuffer(); buffer.putEnumValue(SignalBoxNetwork.REQUEST_PW); - lastTile.getPoint().writeNetwork(buffer); - currentNode.getPoint().writeNetwork(buffer); + start.writeNetwork(buffer); + end.writeNetwork(buffer); + buffer.putEnumValue(type); OpenSignalsMain.network.sendTo(info.player, buffer); } @@ -930,6 +949,20 @@ protected void sendPosIdentList(final List list, final SignalBoxN OpenSignalsMain.network.sendTo(info.player, buffer); } + protected void sendConnetedTrainNumbers(final ModeIdentifier ident, final SignalBoxNode node, + final EnumGuiMode mode, final Rotation rotation) { + if (!allPacketsRecived) + return; + final WriteBuffer buffer = new WriteBuffer(); + buffer.putEnumValue(SignalBoxNetwork.SEND_CONNECTED_TRAINNUMBERS); + ident.writeNetwork(buffer); + node.getPoint().writeNetwork(buffer); + buffer.putByte((byte) mode.ordinal()); + buffer.putByte((byte) rotation.ordinal()); + buffer.putByte((byte) PathEntryType.CONNECTED_TRAINNUMBER.getID()); + OpenSignalsMain.network.sendTo(info.player, buffer); + } + private void reset() { lowerEntity.clear(); } @@ -960,6 +993,8 @@ private void buildColors(final List nodes) { nodes.forEach(node -> { final UISignalBoxTile tile = allTiles.get(node.getPoint()); node.forEach(mode -> { + if (!(mode.mode == EnumGuiMode.STRAIGHT || mode.mode == EnumGuiMode.CORNER)) + return; if (node.containsManuellOutput(mode)) { tile.setColor(mode, OUTPUT_COLOR); return; @@ -975,10 +1010,22 @@ private void resetColors(final List nodes) { nodes.forEach(node -> { final UISignalBoxTile tile = allTiles.get(node.getPoint()); node.forEach(mode -> { - tile.setColor(mode, SignalBoxUtil.FREE_COLOR); + final EnumGuiMode guiMode = mode.mode; final PathOptionEntry entry = node.getOption(mode).get(); - entry.getEntry(PathEntryType.PATHUSAGE).ifPresent( - _u -> entry.setEntry(PathEntryType.PATHUSAGE, EnumPathUsage.FREE)); + switch (guiMode) { + case STRAIGHT: + case CORNER: + tile.setColor(mode, SignalBoxUtil.FREE_COLOR); + entry.getEntry(PathEntryType.PATHUSAGE).ifPresent( + _u -> entry.setEntry(PathEntryType.PATHUSAGE, EnumPathUsage.FREE)); + break; + case TRAIN_NUMBER: + entry.getEntry(PathEntryType.TRAINNUMBER) + .ifPresent(_u -> entry.removeEntry(PathEntryType.TRAINNUMBER)); + break; + default: + break; + } }); }); } @@ -990,8 +1037,9 @@ private void applyColorChanges(final List listOfNodes) { final Path path = new Path(oldPos, newPos); final SignalBoxNode current = listOfNodes.get(i); final UISignalBoxTile uiTile = allTiles.get(current.getPoint()); - if (uiTile == null) + if (uiTile == null) { continue; + } final ModeSet modeSet = current.getMode(path); current.getOption(modeSet) .ifPresent(poe -> uiTile.setColor(modeSet, poe.getEntry(PathEntryType.PATHUSAGE) diff --git a/src/main/java/com/troblecodings/signals/guis/GuiSignalBridge.java b/src/main/java/com/troblecodings/signals/guis/GuiSignalBridge.java index 9e8db4e2d..e63af2932 100644 --- a/src/main/java/com/troblecodings/signals/guis/GuiSignalBridge.java +++ b/src/main/java/com/troblecodings/signals/guis/GuiSignalBridge.java @@ -622,7 +622,7 @@ private void checkMaxAndMins(final VectorWrapper vector) { } private static void checkEnableAndDisable(final AxisDirection axisDirection, final int min, - final int max, final int value, final UIEntity button) { + final int max, final float value, final UIEntity button) { if (value >= max && axisDirection == AxisDirection.POSITIVE) { disableSelection(button); } else if (value <= min && axisDirection == AxisDirection.NEGATIVE) { diff --git a/src/main/java/com/troblecodings/signals/guis/ModeDropDownBoxUI.java b/src/main/java/com/troblecodings/signals/guis/ModeDropDownBoxUI.java index 2c5a03fd8..82b44f227 100644 --- a/src/main/java/com/troblecodings/signals/guis/ModeDropDownBoxUI.java +++ b/src/main/java/com/troblecodings/signals/guis/ModeDropDownBoxUI.java @@ -2,10 +2,12 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map.Entry; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; import com.troblecodings.core.I18Wrapper; import com.troblecodings.guilib.ecs.DrawUtil.BoolIntegerables; @@ -14,6 +16,7 @@ import com.troblecodings.guilib.ecs.GuiElements; import com.troblecodings.guilib.ecs.entitys.UIBox; import com.troblecodings.guilib.ecs.entitys.UIEntity; +import com.troblecodings.guilib.ecs.entitys.UIEnumerable; import com.troblecodings.guilib.ecs.entitys.input.UIClickable; import com.troblecodings.guilib.ecs.entitys.render.UIColor; import com.troblecodings.guilib.ecs.entitys.render.UILabel; @@ -21,12 +24,14 @@ import com.troblecodings.guilib.ecs.entitys.transform.UIScale; import com.troblecodings.guilib.ecs.interfaces.IIntegerable; import com.troblecodings.signals.core.JsonEnumHolder; +import com.troblecodings.signals.core.ModeIdentifier; import com.troblecodings.signals.core.PosIdentifier; import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.enums.EnumPathUsage; import com.troblecodings.signals.enums.LinkType; import com.troblecodings.signals.signalbox.ModeSet; import com.troblecodings.signals.signalbox.Point; +import com.troblecodings.signals.signalbox.SignalBoxGrid; import com.troblecodings.signals.signalbox.SignalBoxNode; import com.troblecodings.signals.signalbox.SignalBoxUtil; import com.troblecodings.signals.signalbox.entrys.PathEntryType; @@ -37,11 +42,11 @@ public class ModeDropDownBoxUI { - private final ModeSet modeSet; + private ModeSet modeSet = null; private final Runnable update; - private final PathOptionEntry option; - private final GuiSignalBox gui; - private final SignalBoxNode node; + private PathOptionEntry option = null; + private GuiSignalBox gui = null; + private SignalBoxNode node = null; private boolean open = false; public ModeDropDownBoxUI(final ModeSet modeSet, final PathOptionEntry option, @@ -55,19 +60,19 @@ public ModeDropDownBoxUI(final ModeSet modeSet, final PathOptionEntry option, public UIEntity getTop() { final String modeName = I18Wrapper.format("property." + modeSet.mode.name()); - final String rotationName = - I18Wrapper.format("property." + modeSet.rotation.name() + ".rotation"); + final String rotationName = I18Wrapper + .format("property." + modeSet.rotation.name() + ".rotation"); final UIEntity top = new UIEntity(); top.setInheritWidth(true); top.setHeight(20); top.add(new UIBox(UIBox.HBOX, 5)); - top.add(new UIColor(GuiSignalBox.BACKGROUND_COLOR)); + top.add(new UIColor(0xFF8B8B8B)); if (open) { - top.add(GuiElements.createButton("↓", 20, e -> changeShowState())); + top.add(GuiElements.createButton("-", 20, e -> changeShowState())); } else { - top.add(GuiElements.createButton("→", 20, e -> changeShowState())); + top.add(GuiElements.createButton("+", 20, e -> changeShowState())); } final UIEntity modeInfo = new UIEntity(); @@ -84,15 +89,15 @@ public UIEntity getTop() { public void addElements(final UIEntity parent) { if (!open) return; - final Set> entrySet = - gui.container.getPositionForTypes().entrySet(); + final Set> entrySet = gui.container.getPositionForTypes() + .entrySet(); final EnumGuiMode mode = modeSet.mode; final Rotation rotation = modeSet.rotation; switch (mode) { case CORNER: case STRAIGHT: { - final EnumPathUsage path = - option.getEntry(PathEntryType.PATHUSAGE).orElse(EnumPathUsage.FREE); + final EnumPathUsage path = option.getEntry(PathEntryType.PATHUSAGE) + .orElse(EnumPathUsage.FREE); final UIEntity stateEntity = new UIEntity(); stateEntity.setInheritWidth(true); stateEntity.setHeight(15); @@ -109,7 +114,7 @@ public void addElements(final UIEntity parent) { gui.removeEntryFromServer(node, mode, rotation, PathEntryType.SPEED); option.removeEntry(PathEntryType.SPEED); } else if ((opt.isPresent() && opt.get() != speed) - || (opt.isEmpty() && speed != 127)) { + || (!opt.isPresent() && speed != 127)) { gui.sendIntEntryToServer(speed, node, mode, rotation, PathEntryType.SPEED); option.setEntry(PathEntryType.SPEED, speed); } @@ -119,8 +124,8 @@ public void addElements(final UIEntity parent) { gui.selectLink(parent, node, option, entrySet, LinkType.OUTPUT, PathEntryType.OUTPUT, mode, rotation); - final SizeIntegerables pathwayCosts = - new SizeIntegerables<>("pathway_costs", 20, i -> i); + final SizeIntegerables pathwayCosts = new SizeIntegerables<>( + "pathway_costs", 20, i -> i); final UIEntity costSelection = GuiElements.createEnumElement(pathwayCosts, i -> { option.setEntry(PathEntryType.PATHWAY_COSTS, i); gui.sendIntEntryToServer(i, node, mode, rotation, PathEntryType.PATHWAY_COSTS); @@ -158,8 +163,8 @@ public void addElements(final UIEntity parent) { }, opt.isPresent() && opt.get() ? 1 : 0)); break; case HP: { - final List preSignalsList = - option.getEntry(PathEntryType.PRESIGNALS).orElse(new ArrayList<>()); + final List preSignalsList = option.getEntry(PathEntryType.PRESIGNALS) + .orElse(new ArrayList<>()); final UIEntity preSignalEntity = GuiElements .createButton(I18Wrapper.format("property.presignals.name"), e -> { final UIEntity screen = new UIEntity(); @@ -169,8 +174,7 @@ public void addElements(final UIEntity parent) { e1 -> gui.pop())); SignalBoxUIHelper.initializeGrid(screen, gui.container.grid, (tile, sbt) -> { - final AtomicReference vp = - new AtomicReference<>(); + final AtomicReference vp = new AtomicReference<>(); sbt.getNode().getModes().forEach((nodeMode, entry) -> { if (!(nodeMode.mode.equals(EnumGuiMode.VP) || nodeMode.mode.equals(EnumGuiMode.ZS3))) @@ -185,8 +189,8 @@ public void addElements(final UIEntity parent) { final PosIdentifier ident = vp.get(); if (ident == null) return; - final UIColor color = - new UIColor(GuiSignalBox.SELECTION_COLOR); + final UIColor color = new UIColor( + GuiSignalBox.SELECTION_COLOR); tile.add(new UIClickable(e1 -> { if (preSignalsList.contains(ident)) { preSignalsList.remove(ident); @@ -215,8 +219,8 @@ public void addElements(final UIEntity parent) { preSignalEntity.add(new UIToolTip(I18Wrapper.format("property.presignals.desc"))); parent.add(preSignalEntity); - final Point selcetedPoint = - option.getEntry(PathEntryType.PROTECTIONWAY_END).orElse(new Point(-1, -1)); + final Point selcetedPoint = option.getEntry(PathEntryType.PROTECTIONWAY_END) + .orElse(new Point(-1, -1)); final UIEntity protectionWay = GuiElements .createButton(I18Wrapper.format("property.protectionway.name"), e -> { final UIEntity screen = new UIEntity(); @@ -230,13 +234,16 @@ public void addElements(final UIEntity parent) { if (sbt.getNode().isEmpty()) return; final Point point = sbt.getPoint(); - final UIColor color = - new UIColor(GuiSignalBox.SELECTION_COLOR); + final UIColor color = new UIColor( + GuiSignalBox.SELECTION_COLOR); if (point.equals(selcetedPoint)) { tile.add(color); previous.set(tile); } tile.add(new UIClickable(e1 -> { + if (!tile.getParent().getParent().getParent() + .isHovered()) + return; if (previous.get() != null) { previous.get().findRecursive(UIColor.class) .forEach(previous.get()::remove); @@ -349,11 +356,156 @@ public void addElements(final UIEntity parent) { PathEntryType.SIGNAL, mode, rotation); break; } + case TRAIN_NUMBER: { + final UIEntity button = GuiElements + .createButton(I18Wrapper.format("btn.connect.trainnumber"), e -> { + final ModeIdentifier identifier = option + .getEntry(PathEntryType.CONNECTED_TRAINNUMBER) + .orElse(new ModeIdentifier(new Point(-1, -1), null)); + final UIEntity screen = new UIEntity(); + screen.setInherits(true); + screen.add(new UIBox(UIBox.VBOX, 5)); + screen.add(GuiElements.createButton(I18Wrapper.format("btn.return"), + e1 -> gui.pop())); + SignalBoxUIHelper.initializeGrid(screen, gui.container.grid, + (nodeEntity, tile) -> { + if (tile.getPoint().equals(identifier.point)) { + nodeEntity + .add(new UIColor(GuiSignalBox.SELECTION_COLOR)); + } + final SignalBoxNode node = tile.getNode(); + if (node.isEmpty()) + return; + nodeEntity.add(new UIClickable(e1 -> { + final Set pathModesSet = node + .toPathIdentifier().stream() + .map(ident -> ident.getMode()) + .collect(Collectors.toSet()); + if (pathModesSet.isEmpty()) { + final UIToolTip tip = new UIToolTip( + I18Wrapper.format("gui.tile.notvalid"), + true); + screen.add(tip); + new Thread(() -> { + try { + Thread.sleep(3000); + } catch (final InterruptedException ex) { + } + screen.remove(tip); + }).start(); + return; + } + final List pathModes = new ArrayList<>( + pathModesSet); + if (pathModes.size() > 1) { + final UIEnumerable enumerable = new UIEnumerable( + pathModes.size(), "mode_select"); + enumerable.setMin(-1); + enumerable.setIndex(-1); + enumerable.setOnChange(i -> { + if (i < 0) + return; + consumer.accept(node, pathModes.get(i)); + enumerable.setIndex(-1); + }); + final UIEntity entity = GuiElements + .createSelectionScreen(enumerable, + SizeIntegerables.of("mode_select", + pathModes.size(), get -> { + final ModeSet modeSet = pathModes + .get(get); + return modeSet.mode + .toString(); + })); + entity.setInherits(true); + gui.push(entity); + } else { + consumer.accept(node, pathModes.get(0)); + } + })); + }); + gui.push(GuiElements.createScreen(e1 -> e1.add(screen))); + }); + parent.add(button); + break; + } default: break; } } + private final BiConsumer consumer = (node, mode) -> { + final PathOptionEntry optionEntry = node.getOption(mode).get(); + final ModeIdentifier thisIdent = new ModeIdentifier(this.node.getPoint(), modeSet); + if (optionEntry.containsEntry(PathEntryType.CONNECTED_TRAINNUMBER)) { + final ModeIdentifier otherIdent = optionEntry + .getEntry(PathEntryType.CONNECTED_TRAINNUMBER).get(); + if (!thisIdent.equals(otherIdent)) { + gui.pop(); + gui.push(GuiElements.createScreen(screen -> { + final UIEntity entity = new UIEntity(); + entity.setInherits(true); + entity.add(new UIBox(UIBox.VBOX, 5)); + entity.add(new UIColor(GuiSignalBox.BACKGROUND_COLOR)); + entity.add(GuiElements.createSpacerV(30)); + entity.add(GuiElements.createLabel(I18Wrapper.format("info.key.removeother"))); + entity.add(GuiElements.createSpacerV(30)); + + final UIEntity lowerEntity = new UIEntity(); + lowerEntity.setInherits(true); + lowerEntity.add(new UIBox(UIBox.HBOX, 5)); + lowerEntity.add(GuiElements.createSpacerH(10)); + lowerEntity.add(GuiElements.createButton(I18Wrapper.format("btn.yes"), e -> { + disconnectFromEachOther(thisIdent, otherIdent, gui.container.grid, gui); + connectToEachOther(thisIdent, new ModeIdentifier(node.getPoint(), mode), + gui.container.grid, gui); + gui.pop(); + })); + lowerEntity.add(GuiElements.createSpacerH(20)); + lowerEntity.add(GuiElements.createButton(I18Wrapper.format("btn.no"), e -> { + gui.pop(); + })); + entity.add(lowerEntity); + screen.add(entity); + })); + return; + } + disconnectFromEachOther(thisIdent, new ModeIdentifier(node.getPoint(), mode), + gui.container.grid, gui); + gui.pop(); + } else { + connectToEachOther(new ModeIdentifier(node.getPoint(), mode), thisIdent, + gui.container.grid, gui); + gui.pop(); + } + }; + + private static void connectToEachOther(final ModeIdentifier ident1, final ModeIdentifier ident2, + final SignalBoxGrid grid, final GuiSignalBox gui) { + final SignalBoxNode node1 = grid.getNode(ident1.point); + node1.getOption(ident1.mode).get().setEntry(PathEntryType.CONNECTED_TRAINNUMBER, ident2); + gui.sendConnetedTrainNumbers(ident2, node1, ident1.mode.mode, ident1.mode.rotation); + + final SignalBoxNode node2 = grid.getNode(ident2.point); + node2.getOption(ident2.mode).get().setEntry(PathEntryType.CONNECTED_TRAINNUMBER, ident1); + gui.sendConnetedTrainNumbers(ident1, node2, ident2.mode.mode, ident2.mode.rotation); + } + + private static void disconnectFromEachOther(final ModeIdentifier ident1, + final ModeIdentifier ident2, final SignalBoxGrid grid, final GuiSignalBox gui) { + final SignalBoxNode node1 = grid.getNode(ident1.point); + node1.getOption(ident1.mode) + .ifPresent(entry -> entry.removeEntry(PathEntryType.CONNECTED_TRAINNUMBER)); + gui.removeEntryFromServer(node1, ident1.mode.mode, ident1.mode.rotation, + PathEntryType.CONNECTED_TRAINNUMBER); + + final SignalBoxNode node2 = grid.getNode(ident2.point); + node2.getOption(ident2.mode) + .ifPresent(entry -> entry.removeEntry(PathEntryType.CONNECTED_TRAINNUMBER)); + gui.removeEntryFromServer(node2, ident2.mode.mode, ident2.mode.rotation, + PathEntryType.CONNECTED_TRAINNUMBER); + } + private void changeShowState() { open = !open; update.run(); diff --git a/src/main/java/com/troblecodings/signals/guis/SidePanel.java b/src/main/java/com/troblecodings/signals/guis/SidePanel.java index 1b6f6dc2a..f92e17bfb 100644 --- a/src/main/java/com/troblecodings/signals/guis/SidePanel.java +++ b/src/main/java/com/troblecodings/signals/guis/SidePanel.java @@ -4,7 +4,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -85,7 +84,7 @@ public SidePanel(final UIEntity lowerEntity, final GuiSignalBox gui) { helpPage.add(new UIBox(UIBox.VBOX, 2)); final UIRotate rotate = new UIRotate(); - rotate.setRotateZ((float) Math.PI / 2.0f); + rotate.setRotateZ(90); label.add(rotate); final UILabel labelComponent = new UILabel(I18Wrapper.format("info.infolabel")); labelComponent.setTextColor(new UIEntity().getBasicTextColor()); @@ -112,7 +111,7 @@ public SidePanel(final UIEntity lowerEntity, final GuiSignalBox gui) { spacerEntity.add(new UIBox(UIBox.VBOX, 0)); spacerEntity.add(button); spacerEntity.add(entity); - spacerEntity.add(new UIColor(GuiSignalBox.BACKGROUND_COLOR)); + spacerEntity.add(new UIColor(0xFF8B8B8B)); lowerEntity.add(spacerEntity); helpPageSpacer.setHeight(5); @@ -120,13 +119,13 @@ public SidePanel(final UIEntity lowerEntity, final GuiSignalBox gui) { public void addHelpPageToPlane() { if (showHelpPage) { - helpPageButton.setText(I18Wrapper.format("info.info") + " →"); + helpPageButton.setText(I18Wrapper.format("info.info") + " ->"); spacerEntity.setWidth(85); helpPage.clearChildren(); helpPage.add(infoEntity); lowerEntity.update(); } else { - helpPageButton.setText("←"); + helpPageButton.setText("<-"); helpPage.clearChildren(); helpPage.add(helpPageSpacer); helpPage.add(getIcons()); @@ -143,9 +142,8 @@ public void addHelpPageToPlane() { private UIEntity getIcons() { final SignalBoxPage page = gui.getPage(); - if (page.equals(SignalBoxPage.EDITOR)) { + if (page.equals(SignalBoxPage.EDITOR)) return GuiElements.createSpacerV(25); - } final UIEntity list = new UIEntity(); list.setInheritWidth(true); list.setHeight(100); @@ -196,8 +194,9 @@ public void updateNextNode(final int selection, final int rotation) { new UIEntity().getBasicTextColor(), 0.8f)); final UIEntity preview = new UIEntity(); - preview.setWidth(70); - preview.setHeight(70); + preview.setWidth(60); + preview.setHeight(60); + preview.setX(7); preview.add(new UIColor(0xFFAFAFAF)); final SignalBoxNode node = new SignalBoxNode(new Point(-1, -1)); final EnumGuiMode modes = EnumGuiMode.values()[selection]; @@ -213,6 +212,7 @@ public void updateNextNode(final int selection, final int rotation) { preview.add(sbtEntity); preview.add(new UIBorder(new UIEntity().getBasicTextColor())); + preview.add(new UIScale(0.9f, 0.9f, 0)); infoEntity.add(preview); infoEntity.add(getSpacerLine()); @@ -397,8 +397,9 @@ public void helpUsageMode(final SignalBoxNode node) { (signalName.isEmpty() ? "Rotaion: " + mode.rotation.toString() : signalName) + " - " + mode.mode.toString(), new UIEntity().getBasicTextColor(), 0.8f)); - if (!(mode.mode == EnumGuiMode.HP || mode.mode == EnumGuiMode.RS)) + if (!(mode.mode == EnumGuiMode.HP || mode.mode == EnumGuiMode.RS)) { continue; + } final UIEntity entity = GuiElements .createButton(I18Wrapper.format("btn.subsidiary"), e -> { final UIBox hbox = new UIBox(UIBox.VBOX, 1); @@ -444,8 +445,9 @@ public void helpUsageMode(final SignalBoxNode node) { identifier.getPoint(), _u -> new ArrayList<>()); if (entry.state) { - if (greenSignals.contains(identifier)) + if (greenSignals.contains(identifier)) { greenSignals.remove(identifier); + } greenSignals.add(identifier); } else { greenSignals.remove(identifier); @@ -485,8 +487,9 @@ public void helpUsageMode(final SignalBoxNode node) { final UIEntity manuelButtonEntity = GuiElements .createButton(I18Wrapper.format("info.usage.manuel") + " : " + modeName + " - " + rotationName, e1 -> { - final Optional usage = option - .getEntry(PathEntryType.PATHUSAGE); + final EnumPathUsage usage = option + .getEntry(PathEntryType.PATHUSAGE) + .orElse(EnumPathUsage.FREE); final UIEntity info = new UIEntity(); info.setInherits(true); info.add(new UIBox(UIBox.VBOX, 5)); @@ -508,8 +511,7 @@ public void helpUsageMode(final SignalBoxNode node) { new UITexture(GuiSignalBox.REDSTONE_OFF)); } } else { - if (usage.isPresent() - && !usage.get().equals(EnumPathUsage.FREE)) { + if (!usage.equals(EnumPathUsage.FREE)) { textureEntity.add(new UITexture( GuiSignalBox.REDSTONE_ON_BLOCKED)); } else { @@ -518,11 +520,13 @@ public void helpUsageMode(final SignalBoxNode node) { } } info.add(textureEntity); - final UILabel outputStatus = new UILabel(((usage.isPresent() - && !usage.get().equals(EnumPathUsage.FREE)) - || node.containsManuellOutput(mode)) - ? I18Wrapper.format("info.usage.rs.true") - : I18Wrapper.format("info.usage.rs.false")); + final UILabel outputStatus = new UILabel( + ((!usage.equals(EnumPathUsage.FREE)) + || node.containsManuellOutput(mode)) + ? I18Wrapper.format( + "info.usage.rs.true") + : I18Wrapper.format( + "info.usage.rs.false")); outputStatus.setCenterY(false); outputStatus .setTextColor(new UIEntity().getBasicTextColor()); @@ -567,7 +571,7 @@ public void helpUsageMode(final SignalBoxNode node) { } final EnumPathUsage path = option.getEntry(PathEntryType.PATHUSAGE) .orElse(EnumPathUsage.FREE); - if (path.equals(EnumPathUsage.BLOCKED)) { + if (!(path.equals(EnumPathUsage.FREE) || path.equals(EnumPathUsage.PROTECTED))) { isPathBlocked = true; } } @@ -738,9 +742,9 @@ private void addManuellRStoUI() { statusEntity.add(currentStatus); final AtomicBoolean canBeManuelChanged = new AtomicBoolean(true); currentNode.getModes().forEach((mode, entry) -> { - final Optional pathUsage = entry - .getEntry(PathEntryType.PATHUSAGE); - if (pathUsage.isPresent() && !pathUsage.get().equals(EnumPathUsage.FREE)) { + final EnumPathUsage pathUsage = entry.getEntry(PathEntryType.PATHUSAGE) + .orElse(EnumPathUsage.FREE); + if (!pathUsage.equals(EnumPathUsage.FREE)) { currentStatus.setText(I18Wrapper.format("info.usage.status") + " : " + I18Wrapper.format("info.usage.status.blocked")); canBeManuelChanged.set(false); @@ -770,19 +774,18 @@ private void addManuellRStoUI() { textureEntity.add(new UITexture(GuiSignalBox.REDSTONE_OFF)); } } else { - if (pathUsage.isPresent() - && !pathUsage.get().equals(EnumPathUsage.FREE)) { + if (!pathUsage.equals(EnumPathUsage.FREE)) { textureEntity.add(new UITexture(GuiSignalBox.REDSTONE_ON_BLOCKED)); } else { textureEntity.add(new UITexture(GuiSignalBox.REDSTONE_OFF_BLOCKED)); } } info.add(textureEntity); - final UILabel outputStatus = new UILabel(((pathUsage.isPresent() - && !pathUsage.get().equals(EnumPathUsage.FREE)) - || currentNode.containsManuellOutput(mode)) - ? I18Wrapper.format("info.usage.rs.true") - : I18Wrapper.format("info.usage.rs.false")); + final UILabel outputStatus = new UILabel( + ((!pathUsage.equals(EnumPathUsage.FREE)) + || currentNode.containsManuellOutput(mode)) + ? I18Wrapper.format("info.usage.rs.true") + : I18Wrapper.format("info.usage.rs.false")); outputStatus.setCenterY(false); outputStatus.setTextColor(new UIEntity().getBasicTextColor()); final UIEntity outputEntity = new UIEntity(); @@ -862,14 +865,13 @@ private void addSavedPathsToUI() { final UIScrollBox scrollbox = new UIScrollBox(UIBox.VBOX, 2); list.add(scrollbox); - gui.container.nextPathways.forEach(entry -> { + gui.container.nextPathways.forEach((entry, pathType) -> { final UIEntity layout = new UIEntity(); layout.setHeight(20); layout.setInheritWidth(true); layout.add(new UIBox(UIBox.HBOX, 2)); - final UIEntity button = GuiElements - .createButton("Start: " + entry.getKey().toShortString() + ", End: " - + entry.getValue().toShortString()); + final UIEntity button = GuiElements.createButton(entry.getKey().toShortString() + + " to " + entry.getValue().toShortString() + " as " + pathType.name()); layout.add(button); layout.add( GuiElements.createButton(I18Wrapper.format("info.usage.show"), 40, _u -> { diff --git a/src/main/java/com/troblecodings/signals/guis/UIMenu.java b/src/main/java/com/troblecodings/signals/guis/UIMenu.java index 246457086..41435de50 100644 --- a/src/main/java/com/troblecodings/signals/guis/UIMenu.java +++ b/src/main/java/com/troblecodings/signals/guis/UIMenu.java @@ -4,13 +4,17 @@ import java.util.Map; import java.util.function.BiConsumer; +import com.troblecodings.guilib.ecs.GuiElements; import com.troblecodings.guilib.ecs.entitys.UIBox; import com.troblecodings.guilib.ecs.entitys.UIComponentEntity; import com.troblecodings.guilib.ecs.entitys.UIEntity; import com.troblecodings.guilib.ecs.entitys.UIEntity.KeyEvent; +import com.troblecodings.guilib.ecs.entitys.UIScrollBox; import com.troblecodings.guilib.ecs.entitys.input.UIClickable; +import com.troblecodings.guilib.ecs.entitys.input.UIScroll; import com.troblecodings.guilib.ecs.entitys.render.UIBorder; import com.troblecodings.guilib.ecs.entitys.render.UIColor; +import com.troblecodings.guilib.ecs.entitys.render.UIScissor; import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.signalbox.ModeSet; import com.troblecodings.signals.signalbox.Point; @@ -29,11 +33,17 @@ public class UIMenu extends UIComponentEntity { public UIMenu() { super(new UIEntity()); - entity.setHeight(20); - entity.setWidth(22 * EnumGuiMode.values().length); - entity.setX(2); - entity.setY(2); - entity.add(new UIBox(UIBox.HBOX, 2)); + entity.setInheritWidth(true); + entity.setHeight(32); + entity.add(new UIBox(UIBox.VBOX, 0)); + entity.add(new UIScissor()); + + final UIEntity list = new UIEntity(); + entity.add(list); + list.setInherits(true); + + final UIScrollBox scrollbox = new UIScrollBox(UIBox.HBOX, 2); + list.add(scrollbox); for (final EnumGuiMode mode : EnumGuiMode.values()) { final UIEntity preview = new UIEntity(); preview.add(new UIColor(0xFFAFAFAF)); @@ -46,9 +56,15 @@ public UIMenu() { if (mode.ordinal() == this.selection) preview.add(new UIBorder(0xFF00FF00, 1)); preview.add(new UIClickable(e -> updateSelection(mode))); - entity.add(preview); + list.add(preview); modeForEntity.put(mode, preview); } + final UIScroll scroll = new UIScroll(); + final UIEntity scrollBar = GuiElements.createScrollBar(scrollbox, 10, scroll); + scrollbox.setConsumer(i -> { + }); + entity.add(scroll); + entity.add(scrollBar); } private void updateSelection(final EnumGuiMode newMode) { @@ -65,7 +81,11 @@ private void updateSelection(final EnumGuiMode newMode) { @Override public void update() { this.entity.onAdd(this.getParent()); - super.update(); + entity.setHeight(32); + entity.setWidth(parent.getWidth() - 4); + entity.setX(entity.getX() + 1); + entity.setY(entity.getY() + 1); + entity.update(); } public int getSelection() { diff --git a/src/main/java/com/troblecodings/signals/guis/UISignalBoxTile.java b/src/main/java/com/troblecodings/signals/guis/UISignalBoxTile.java index 31263074a..586d62b88 100644 --- a/src/main/java/com/troblecodings/signals/guis/UISignalBoxTile.java +++ b/src/main/java/com/troblecodings/signals/guis/UISignalBoxTile.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; +import com.troblecodings.guilib.ecs.GuiElements; import com.troblecodings.guilib.ecs.entitys.UIComponent; import com.troblecodings.guilib.ecs.entitys.UIComponentEntity; import com.troblecodings.guilib.ecs.entitys.UIEntity; @@ -12,6 +13,7 @@ import com.troblecodings.guilib.ecs.entitys.transform.UIIndependentTranslate; import com.troblecodings.guilib.ecs.entitys.transform.UIRotate; import com.troblecodings.signals.OpenSignalsMain; +import com.troblecodings.signals.config.ConfigHandler; import com.troblecodings.signals.core.TrainNumber; import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.signalbox.MainSignalIdentifier; @@ -19,6 +21,7 @@ import com.troblecodings.signals.signalbox.ModeSet; import com.troblecodings.signals.signalbox.Point; import com.troblecodings.signals.signalbox.SignalBoxNode; +import com.troblecodings.signals.signalbox.entrys.PathEntryType; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Rotation; @@ -45,7 +48,6 @@ public class UISignalBoxTile extends UIComponentEntity { private SignalBoxNode node; private final Map setToEntity = new HashMap<>(); private final Map greenSignals = new HashMap<>(); - private final UITrainNumber uiTrainNumber = new UITrainNumber(); public UISignalBoxTile(final SignalBoxNode node) { super(new UIEntity()); @@ -85,10 +87,10 @@ private void localAdd(final ModeSet modeSet) { final UIEntity entity = new UIEntity(); if (!modeSet.rotation.equals(Rotation.NONE)) { final UIRotate rotation = new UIRotate(); - rotation.setRotateZ(modeSet.rotation.ordinal() * ((float) Math.PI / 2.0f)); + rotation.setRotateZ(modeSet.rotation.ordinal() * ((float) 90)); entity.add(rotation); } - entity.add(new UIIndependentTranslate(0, 0, 1)); + entity.add(new UIIndependentTranslate(0, 0, modeSet.mode.translation + 1)); SignalState state = greenSignals.getOrDefault(modeSet, SignalState.RED); if (modeSet.mode.equals(EnumGuiMode.RS)) { @@ -97,11 +99,11 @@ private void localAdd(final ModeSet modeSet) { if (setToEntity.containsKey(hpMode)) { if (hpState.equals(SignalState.RED)) { switch (state) { - case SUBSIDIARY_RED: - case GREEN: { + case SUBSIDIARY_RED: { hpState = SignalState.SUBSIDIARY_RED; break; } + case GREEN: case SUBSIDIARY_OFF: { hpState = SignalState.SUBSIDIARY_OFF; break; @@ -119,6 +121,18 @@ private void localAdd(final ModeSet modeSet) { } } + if (modeSet.mode.equals(EnumGuiMode.TRAIN_NUMBER)) { + final TrainNumber number = node.getOption(modeSet).get() + .getEntry(PathEntryType.TRAINNUMBER).orElse(TrainNumber.DEFAULT); + if (!number.equals(TrainNumber.DEFAULT)) { + final UIEntity label = GuiElements.createLabel(number.trainNumber, + ConfigHandler.CLIENT.signalboxTrainNumberColor.get(), 0.5f); + label.setX(6); + label.setY(3); + entity.add(label); + } + } + entity.add((UIComponent) modeSet.mode.consumer.get(state)); this.entity.add(entity); setToEntity.put(modeSet, entity); @@ -189,13 +203,4 @@ public void setColor(final ModeSet mode, final int color) { entity.findRecursive(UILines.class).forEach(lines -> lines.setColor(color)); } } - - public void updateTrainNumber() { - this.getParent().remove(uiTrainNumber); - final TrainNumber number = this.node.getTrainNumber(); - uiTrainNumber.setTrainNumber(number); - if (!number.trainNumber.isEmpty()) { - this.getParent().add(uiTrainNumber); - } - } } \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/guis/UITrainNumber.java b/src/main/java/com/troblecodings/signals/guis/UITrainNumber.java deleted file mode 100644 index 51464d92a..000000000 --- a/src/main/java/com/troblecodings/signals/guis/UITrainNumber.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.troblecodings.signals.guis; - -import com.troblecodings.guilib.ecs.entitys.DrawInfo; -import com.troblecodings.guilib.ecs.entitys.UIComponent; -import com.troblecodings.guilib.ecs.entitys.UIEntity; -import com.troblecodings.guilib.ecs.entitys.render.UILabel; -import com.troblecodings.guilib.ecs.entitys.transform.UIScale; -import com.troblecodings.signals.core.TrainNumber; - -public class UITrainNumber extends UIComponent { - - private TrainNumber number; - - public void setTrainNumber(final TrainNumber number) { - this.number = number; - } - - @Override - public void draw(final DrawInfo info) { - } - - @Override - public void update() { - } - - @Override - public void postDraw(final DrawInfo info) { - if (this.isVisible() && !number.trainNumber.isEmpty()) { - info.stack.pushPose(); - info.stack.translate(0, 0, 5); - final UIEntity trainNumberEntity = new UIEntity(); - trainNumberEntity.setX(parent.getWorldX()); - trainNumberEntity.setY(parent.getWorldY() + 1); - trainNumberEntity.setHeight(20); - trainNumberEntity.add(new UIScale(0.45f, 0.45f, 0.45f)); - final UILabel label = new UILabel(number.trainNumber); - label.setTextColor(0xFFFFFFFF); - trainNumberEntity.add(label); - trainNumberEntity.updateEvent(parent.getLastUpdateEvent()); - trainNumberEntity.draw(info); - info.stack.popPose(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/handler/NameHandler.java b/src/main/java/com/troblecodings/signals/handler/NameHandler.java index f83a28cf1..61cdb2eba 100644 --- a/src/main/java/com/troblecodings/signals/handler/NameHandler.java +++ b/src/main/java/com/troblecodings/signals/handler/NameHandler.java @@ -23,9 +23,11 @@ import com.troblecodings.signals.blocks.RedstoneIO; import com.troblecodings.signals.blocks.Signal; import com.troblecodings.signals.core.LoadHolder; +import com.troblecodings.signals.core.NameStateListener; import com.troblecodings.signals.core.PathGetter; import com.troblecodings.signals.core.StateInfo; import com.troblecodings.signals.core.StateLoadHolder; +import com.troblecodings.signals.enums.ChangedState; import io.netty.buffer.Unpooled; import net.minecraft.client.Minecraft; @@ -53,8 +55,10 @@ public final class NameHandler implements INetworkSync { private static final Map ALL_NAMES = new HashMap<>(); private static final Map ALL_LEVEL_FILES = new HashMap<>(); + private static final Map> TASKS_WHEN_LOAD = new HashMap<>(); private static final Map>> LOAD_COUNTER = new HashMap<>(); private static ExecutorService writeService = Executors.newFixedThreadPool(5); + private static final ExecutorService THREAD_SERVICE = Executors.newCachedThreadPool(); private static EventNetworkChannel channel; private static ResourceLocation channelName; @@ -89,7 +93,7 @@ public static void registerToNetworkChannel(final Object obj) { public static void createName(final StateInfo info, final String name, final Player creator) { if (info.world.isClientSide || name == null) return; - new Thread(() -> { + THREAD_SERVICE.execute(() -> { setNameForNonSignal(info, name); final List> list = new ArrayList<>(); list.add(new LoadHolder<>(creator)); @@ -97,7 +101,7 @@ public static void createName(final StateInfo info, final String name, final Pla LOAD_COUNTER.put(info, list); } createToFile(info, name); - }, "OSNameHandler:createName").start(); + }); } public static void setNameForSignal(final StateInfo info, final String name) { @@ -114,12 +118,12 @@ public static void setNameForSignal(final StateInfo info, final String name) { public static void setNameForNonSignal(final StateInfo info, final String name) { if (info.world.isClientSide || name == null) return; - new Thread(() -> { + THREAD_SERVICE.execute(() -> { synchronized (ALL_NAMES) { ALL_NAMES.put(info, name); } sendToAll(info, name); - }, "OSNameHandler:setName").start(); + }); } public static String getName(final StateInfo info) { @@ -146,6 +150,31 @@ private static ByteBuffer packToBuffer(final BlockPos pos, final String name) { return buffer.build(); } + public static boolean isNameLoaded(final StateInfo info) { + synchronized (ALL_NAMES) { + return ALL_NAMES.containsKey(info); + } + } + + public static void runTaskWhenNameLoaded(final StateInfo info, + final NameStateListener listener) { + if (!info.isValid() || info.isWorldNullOrClientSide()) + return; + if (isNameLoaded(info)) { + synchronized (ALL_NAMES) { + listener.update(info, ALL_NAMES.get(info), ChangedState.UPDATED); + } + } else { + synchronized (TASKS_WHEN_LOAD) { + final List list = TASKS_WHEN_LOAD.computeIfAbsent(info, + _u -> new ArrayList<>()); + if (!list.contains(listener)) { + list.add(listener); + } + } + } + } + public static void setRemoved(final StateInfo info) { synchronized (ALL_NAMES) { ALL_NAMES.remove(info); @@ -317,7 +346,7 @@ public static void loadName(final StateLoadHolder holder, final @Nullable Player public static void loadNames(final List infos, final @Nullable Player player) { if (infos == null || infos.isEmpty()) return; - new Thread(() -> { + THREAD_SERVICE.execute(() -> { infos.forEach(info -> { boolean isLoaded = false; synchronized (LOAD_COUNTER) { @@ -355,8 +384,15 @@ public static void loadNames(final List infos, final @Nullable ALL_NAMES.put(info.info, name); } sendToAll(info.info, name); + synchronized (TASKS_WHEN_LOAD) { + final List tasks = TASKS_WHEN_LOAD.remove(info.info); + if (tasks != null) { + tasks.forEach(listener -> listener.update(info.info, name, + ChangedState.ADDED_TO_CACHE)); + } + } }); - }, "OSNameHandler:loadNames").start(); + }); } public static void unloadName(final StateLoadHolder holder) { diff --git a/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java b/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java index 3f115fcf3..719c410e0 100644 --- a/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java +++ b/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java @@ -28,6 +28,7 @@ import com.troblecodings.signals.core.PathGetter; import com.troblecodings.signals.core.SignalStateListener; import com.troblecodings.signals.core.SignalStateLoadHoler; +import com.troblecodings.signals.core.StateInfo; import com.troblecodings.signals.enums.ChangedState; import io.netty.buffer.Unpooled; @@ -54,6 +55,7 @@ public final class SignalStateHandler implements INetworkSync { private static ExecutorService writeService = Executors.newFixedThreadPool(5); + private static final ExecutorService THREAD_SERVICE = Executors.newCachedThreadPool(); private static final Map> CURRENTLY_LOADED_STATES = new HashMap<>(); private static final Map ALL_LEVEL_FILES = new HashMap<>(); private static final Map>> SIGNAL_COUNTER = new HashMap<>(); @@ -102,7 +104,7 @@ public static void createStates(final SignalStateInfo info, CURRENTLY_LOADED_STATES.put(info, ImmutableMap.copyOf(states)); } updateListeners(info, states, ChangedState.ADDED_TO_FILE); - new Thread(() -> { + THREAD_SERVICE.execute(() -> { final List> list = new ArrayList<>(); list.add(new LoadHolder<>(creator)); synchronized (SIGNAL_COUNTER) { @@ -110,7 +112,7 @@ public static void createStates(final SignalStateInfo info, } sendToAll(info, states); createToFile(info, states); - }, "OSSignalStateHandler:createStates").start(); + }); } public static boolean isSignalLoaded(final SignalStateInfo info) { @@ -185,6 +187,8 @@ private static void updateListeners(final SignalStateInfo info, private static void statesToBuffer(final Signal signal, final Map states, final byte[] readData) { states.forEach((property, string) -> { + if (property.equals(Signal.CUSTOMNAME)) + return; readData[signal.getIDFromProperty( property)] = (byte) (property.getParent().getIDFromValue(string) + 1); }); @@ -233,12 +237,12 @@ public static void setStates(final SignalStateInfo info, final Map { + THREAD_SERVICE.execute(() -> { sendToAll(info, changedProperties); info.signal.getUpdate(info.world, info.pos); if (!contains.get()) createToFile(info, changedProperties); - }, "OSSignalStateHandler:setStates").start(); + }); info.world.getServer().execute(() -> info.world.updateNeighborsAt(info.pos, info.signal)); } @@ -342,12 +346,36 @@ private static Map readAndSerialize(final SignalStateInfo st final byte[] byteArray = buffer.array(); for (int i = 0; i < properties.size(); i++) { final SEProperty property = properties.get(i); + if (property.equals(Signal.CUSTOMNAME)) { + continue; + } final int typeID = Byte.toUnsignedInt(byteArray[i]); if (typeID <= 0) continue; final String value = property.getObjFromID(typeID - 1); map.put(property, value); } + if (NameHandler.isNameLoaded(stateInfo)) { + final String customName = NameHandler.getName(stateInfo); + if (customName == null || customName.isEmpty() + || customName.equals(stateInfo.signal.getSignalTypeName())) { + map.put(Signal.CUSTOMNAME, "false"); + } else { + map.put(Signal.CUSTOMNAME, "true"); + } + } else { + NameHandler.runTaskWhenNameLoaded(new StateInfo(stateInfo.world, stateInfo.pos), + (info, name, changed) -> { + if (name == null || name.isEmpty() + || name.equals(stateInfo.signal.getSignalTypeName())) { + runTaskWhenSignalLoaded(stateInfo, (_u1, _u2, + _u3) -> setState(stateInfo, Signal.CUSTOMNAME, "false")); + } else { + runTaskWhenSignalLoaded(stateInfo, (_u1, _u2, + _u3) -> setState(stateInfo, Signal.CUSTOMNAME, "true")); + } + }); + } return map; } @@ -514,7 +542,7 @@ public static void loadSignals(final List signals, final @Nullable Player player) { if (signals == null || signals.isEmpty()) return; - new Thread(() -> { + THREAD_SERVICE.execute(() -> { signals.forEach(info -> { boolean isLoaded = false; synchronized (SIGNAL_COUNTER) { @@ -548,7 +576,7 @@ public static void loadSignals(final List signals, } } }); - }, "OSSignalStateHandler:loadSignals").start(); + }); } diff --git a/src/main/java/com/troblecodings/signals/signalbox/DelayableInterSignalBoxPathway.java b/src/main/java/com/troblecodings/signals/signalbox/DelayableInterSignalBoxPathway.java index 4f9ac21d2..392321ed2 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/DelayableInterSignalBoxPathway.java +++ b/src/main/java/com/troblecodings/signals/signalbox/DelayableInterSignalBoxPathway.java @@ -4,10 +4,9 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import com.troblecodings.signals.core.BlockPosSignalHolder; import com.troblecodings.signals.enums.EnumPathUsage; -import net.minecraft.core.BlockPos; - public class DelayableInterSignalBoxPathway extends InterSignalBoxPathway { private final ExecutorService service = Executors.newFixedThreadPool(1); @@ -16,6 +15,11 @@ public DelayableInterSignalBoxPathway(final PathwayData data) { super(data); } + @Override + public void setUpPathwayStatus() { + setPathStatus(EnumPathUsage.PREPARED); + } + @Override public void updatePathwaySignals() { setPathStatus(EnumPathUsage.PREPARED); @@ -37,7 +41,7 @@ public void updatePathwaySignals() { if (isEmptyOrBroken()) { return; } - final Map distantSignalPositions = data + final Map distantSignalPositions = data .getOtherSignals(); this.isExecutingSignalSet = false; pathwayToBlock.isExecutingSignalSet = false; diff --git a/src/main/java/com/troblecodings/signals/signalbox/DelayableShuntingPathway.java b/src/main/java/com/troblecodings/signals/signalbox/DelayableShuntingPathway.java new file mode 100644 index 000000000..1572bf6fe --- /dev/null +++ b/src/main/java/com/troblecodings/signals/signalbox/DelayableShuntingPathway.java @@ -0,0 +1,59 @@ +package com.troblecodings.signals.signalbox; + +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.troblecodings.signals.core.BlockPosSignalHolder; +import com.troblecodings.signals.enums.EnumPathUsage; + +public class DelayableShuntingPathway extends ShuntingPathway { + + private final ExecutorService service = Executors.newFixedThreadPool(1); + + public DelayableShuntingPathway(final PathwayData data) { + super(data); + } + + @Override + public void setUpPathwayStatus() { + setPathStatus(EnumPathUsage.PREPARED); + } + + @Override + public void updatePathwaySignals() { + if (isExecutingSignalSet) + return; + this.isExecutingSignalSet = true; + service.execute(() -> { + try { + Thread.sleep(data.getDelay() * 1000); + } catch (final InterruptedException e) { + } + if (isEmptyOrBroken()) { + return; + } + final Map distantSignalPositions = data + .getOtherSignals(); + this.isExecutingSignalSet = false; + synchronized (distantSignalPositions) { + setSignals(getLastSignalInfo()); + } + tile.getLevel().getServer().execute(() -> { + loadTileAndExecute(thisTile -> { + final SignalBoxPathway pw = thisTile.getSignalBoxGrid() + .getPathwayByLastPoint(getLastPoint()); + pw.setPathStatus(EnumPathUsage.SHUNTING); + pw.updatePathwayOnGrid(); + }); + }); + }); + } + + @Override + public String toString() { + return "DelayableShuntingPathway [start=" + getFirstPoint() + ", end=" + getLastPoint() + + ", delay=" + data.getDelay() + "]"; + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/signalbox/DelayableSignalBoxPathway.java b/src/main/java/com/troblecodings/signals/signalbox/DelayableSignalBoxPathway.java index 5962aafd8..5f333e730 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/DelayableSignalBoxPathway.java +++ b/src/main/java/com/troblecodings/signals/signalbox/DelayableSignalBoxPathway.java @@ -4,10 +4,9 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import com.troblecodings.signals.core.BlockPosSignalHolder; import com.troblecodings.signals.enums.EnumPathUsage; -import net.minecraft.core.BlockPos; - public class DelayableSignalBoxPathway extends SignalBoxPathway { private final ExecutorService service = Executors.newFixedThreadPool(1); @@ -16,6 +15,11 @@ public DelayableSignalBoxPathway(final PathwayData data) { super(data); } + @Override + public void setUpPathwayStatus() { + setPathStatus(EnumPathUsage.PREPARED); + } + @Override public void updatePathwaySignals() { setPathStatus(EnumPathUsage.PREPARED); @@ -30,7 +34,7 @@ public void updatePathwaySignals() { if (isEmptyOrBroken()) { return; } - final Map distantSignalPositions = data + final Map distantSignalPositions = data .getOtherSignals(); this.isExecutingSignalSet = false; synchronized (distantSignalPositions) { diff --git a/src/main/java/com/troblecodings/signals/signalbox/InterSignalBoxPathway.java b/src/main/java/com/troblecodings/signals/signalbox/InterSignalBoxPathway.java index 68961b9d3..583c59f85 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/InterSignalBoxPathway.java +++ b/src/main/java/com/troblecodings/signals/signalbox/InterSignalBoxPathway.java @@ -8,6 +8,7 @@ import com.google.common.collect.Maps; import com.troblecodings.core.NBTWrapper; import com.troblecodings.signals.blocks.Signal; +import com.troblecodings.signals.core.BlockPosSignalHolder; import com.troblecodings.signals.core.StateInfo; import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.enums.EnumPathUsage; @@ -151,6 +152,8 @@ protected SignalStateInfo getLastSignalInfo() { @Override protected void setSignals(final SignalStateInfo lastSignal) { + if (tile == null || isExecutingSignalSet) + return; final StateInfo identifier = new StateInfo(tile.getLevel(), tile.getBlockPos()); if (lastSignal != null && pathwayToReset != null) { final Signal signal = SignalBoxHandler.getSignal(identifier, lastSignal.pos); @@ -197,8 +200,14 @@ protected void updateSignalStates() { if (!lastSignal.state.equals(previous)) greenSignals.add(lastSignal); } - final Map distantSignalPositions = data.getOtherSignals(); - distantSignalPositions.values().forEach(position -> { + final Map distantSignalPositions = data + .getOtherSignals(); + distantSignalPositions.forEach((holder, position) -> { + if (holder.shouldTurnSignalOff()) { + position.state = SignalState.OFF; + greenSignals.add(position); + return; + } final SignalBoxPathway next = getNextPathway(); final SignalState previous = position.state; if (lastSignal != null && next != null && !next.isEmptyOrBroken()) { diff --git a/src/main/java/com/troblecodings/signals/signalbox/PathwayData.java b/src/main/java/com/troblecodings/signals/signalbox/PathwayData.java index b0a569066..d57bee159 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/PathwayData.java +++ b/src/main/java/com/troblecodings/signals/signalbox/PathwayData.java @@ -3,10 +3,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; @@ -19,7 +21,9 @@ import com.google.common.collect.ImmutableMap; import com.troblecodings.core.NBTWrapper; import com.troblecodings.signals.OpenSignalsMain; +import com.troblecodings.signals.core.BlockPosSignalHolder; import com.troblecodings.signals.core.JsonEnumHolder; +import com.troblecodings.signals.core.ModeIdentifier; import com.troblecodings.signals.core.PosIdentifier; import com.troblecodings.signals.core.StateInfo; import com.troblecodings.signals.enums.EnumGuiMode; @@ -43,7 +47,6 @@ public class PathwayData { private static final String LIST_OF_NODES = "listOfNodes"; private static final String PATH_TYPE = "pathType"; - private static final String LIST_OF_PROTECTION_NODES = "listOfProtectionNodes"; protected SignalBoxGrid grid = null; private final Map mapOfResetPositions = new HashMap<>(); @@ -57,12 +60,13 @@ public class PathwayData { private int delay = 0; private Optional startSignal = Optional.empty(); private Optional endSignal = Optional.empty(); - private Map otherSignals = ImmutableMap.of(); + private Map otherSignals = ImmutableMap.of(); private List preSignals = ImmutableList.of(); private boolean emptyOrBroken = false; private List protectionWayNodes = ImmutableList.of(); private BlockPos protectionWayReset = null; private int protectionWayResetDelay = 0; + private List trainNumberDisplays = ImmutableList.of(); private SignalBoxPathway pathway; @@ -98,17 +102,25 @@ public static PathwayData of(final SignalBoxGrid grid, final NBTWrapper tag) { public SignalBoxPathway createPathway() { if (pathway == null) { - final boolean isInterSignalBoxPathway = isInterSignalBoxPathway(); - if (delay > 0) { - if (isInterSignalBoxPathway) { - pathway = new DelayableInterSignalBoxPathway(this); + if (type.equals(PathType.SHUNTING)) { + if (delay > 0) { + pathway = new DelayableShuntingPathway(this); } else { - pathway = new DelayableSignalBoxPathway(this); + pathway = new ShuntingPathway(this); } - } else if (isInterSignalBoxPathway) { - pathway = new InterSignalBoxPathway(this); } else { - pathway = new SignalBoxPathway(this); + final boolean isInterSignalBoxPathway = isInterSignalBoxPathway(); + if (delay > 0) { + if (isInterSignalBoxPathway) { + pathway = new DelayableInterSignalBoxPathway(this); + } else { + pathway = new DelayableSignalBoxPathway(this); + } + } else if (isInterSignalBoxPathway) { + pathway = new InterSignalBoxPathway(this); + } else { + pathway = new SignalBoxPathway(this); + } } } return pathway; @@ -142,7 +154,7 @@ private boolean checkForShuntingPath() { this.initalize(); break; } - if (current.isUsed()) { + if (current.isUsedInDirection(newPos)) { return false; } } @@ -229,7 +241,7 @@ protected boolean directResetOfProtectionWay() { return; option.getEntry(PathEntryType.OUTPUT).ifPresent(pos -> SignalBoxHandler .updateRedstoneOutput(new StateInfo(pathway.tile.getLevel(), pos), false)); - option.setEntry(PathEntryType.PATHUSAGE, EnumPathUsage.FREE); + option.removeEntry(PathEntryType.PATHUSAGE); }); return true; } @@ -254,7 +266,8 @@ private void initalize() { final AtomicInteger atomic = new AtomicInteger(Integer.MAX_VALUE); final AtomicReference zs2Value = new AtomicReference<>((byte) -1); final AtomicInteger delayAtomic = new AtomicInteger(0); - final Map otherBuilder = new HashMap<>(); + final Map otherBuilder = new HashMap<>(); + final Set trainNumberDisplays = new HashSet<>(); mapOfBlockingPositions.clear(); mapOfResetPositions.clear(); foreachPath((path, node) -> { @@ -266,6 +279,8 @@ private void initalize() { optionEntry.getEntry(PathEntryType.RESETING) .ifPresent(position -> mapOfResetPositions.put(position, node)); optionEntry.getEntry(PathEntryType.ZS2).ifPresent(value -> zs2Value.set(value)); + optionEntry.getEntry(PathEntryType.CONNECTED_TRAINNUMBER) + .ifPresent(ident -> trainNumberDisplays.add(ident)); }); final Rotation rotation = SignalBoxUtil .getRotationFromDelta(node.getPoint().delta(path.point1)); @@ -279,7 +294,20 @@ private void initalize() { final OtherSignalIdentifier ident = new OtherSignalIdentifier( node.getPoint(), modeSet, position, repeaterOption.isPresent() && repeaterOption.get(), mode); - otherBuilder.put(position, ident); + final BlockPosSignalHolder holder = new BlockPosSignalHolder(position); + if (otherBuilder.containsKey(holder)) { + final OtherSignalIdentifier otherIdent = otherBuilder.get(holder); + if (ident.guiMode.ordinal() < otherIdent.guiMode.ordinal()) { + otherBuilder.put(holder, ident); + otherBuilder.put(new BlockPosSignalHolder(position, true), + otherIdent); + } else { + otherBuilder.put(new BlockPosSignalHolder(position, true), + ident); + } + } else { + otherBuilder.put(holder, ident); + } })); } node.getModes().forEach((mode, entry) -> { @@ -288,6 +316,7 @@ private void initalize() { value -> delayAtomic.updateAndGet(in -> Math.max(in, value))); }); }, null); + this.trainNumberDisplays = ImmutableList.copyOf(trainNumberDisplays); this.otherSignals = ImmutableMap.copyOf(otherBuilder); final SignalBoxNode firstNode = this.listOfNodes.get(this.listOfNodes.size() - 1); this.firstPoint = firstNode.getPoint(); @@ -311,6 +340,7 @@ private void initalize() { .getOption(firstPos.getModeSet()).orElse(null); final List posIdents = entry.getEntry(PathEntryType.PRESIGNALS) .orElse(new ArrayList<>()); + posIdents.removeIf(ident -> !grid.getNode(ident.getPoint()).has(ident.getModeSet())); this.preSignals = ImmutableList.copyOf(posIdents.stream().map(ident -> { final PathOptionEntry vpEntry = grid.getNode(ident.getPoint()) .getOption(ident.getModeSet()).orElse(new PathOptionEntry()); @@ -382,33 +412,23 @@ public void write(final NBTWrapper tag) { node.getPoint().write(entry); return entry; })::iterator); - tag.putList(LIST_OF_PROTECTION_NODES, protectionWayNodes.stream().map(node -> { - final NBTWrapper entry = new NBTWrapper(); - node.getPoint().write(entry); - return entry; - })::iterator); tag.putString(PATH_TYPE, this.type.name()); } public void read(final NBTWrapper tag) { final com.google.common.collect.ImmutableList.Builder nodeBuilder = ImmutableList .builder(); - final com.google.common.collect.ImmutableList.Builder protectionNodeBuilder = ImmutableList - .builder(); tag.getList(LIST_OF_NODES).forEach(nodeNBT -> { final SignalBoxNode node = getNodeFromNBT(nodeNBT); if (node == null) return; nodeBuilder.add(node); }); - tag.getList(LIST_OF_PROTECTION_NODES).forEach(nodeNBT -> { - final SignalBoxNode node = getNodeFromNBT(nodeNBT); - if (node == null) - return; - protectionNodeBuilder.add(node); - }); this.listOfNodes = nodeBuilder.build(); - this.protectionWayNodes = protectionNodeBuilder.build(); + if (!checkForProtectionWay()) { + this.emptyOrBroken = true; + return; + } this.type = PathType.valueOf(tag.getString(PATH_TYPE)); this.initalize(); } @@ -454,7 +474,7 @@ public void compact(final Point point) { this.initalize(); } - public Map getOtherSignals() { + public Map getOtherSignals() { return otherSignals; } @@ -545,7 +565,7 @@ private PathwayData requestInterSignalBoxPathway(final SignalBoxGrid grid) { return; } final PathwayRequestResult endRequeset = SignalBoxUtil.requestPathway(endGrid, - otherStartPoint.get(), otherEndPoint.get()); + otherStartPoint.get(), otherEndPoint.get(), PathType.NORMAL); if (endRequeset.isPass()) { returnResult.set(endRequeset.getPathwayData()); } @@ -607,6 +627,10 @@ public SignalBoxGrid getGrid() { return grid; } + public List getTrainNumberDisplays() { + return trainNumberDisplays; + } + @Override public int hashCode() { return Objects.hash(firstPoint, lastPoint, listOfNodes); @@ -631,4 +655,4 @@ public String toString() { return "PathwayData [firstPoint=" + firstPoint + ",lastPoint=" + lastPoint + ",listOfNodes=" + listOfNodes + "]"; } -} \ No newline at end of file +} diff --git a/src/main/java/com/troblecodings/signals/signalbox/ShuntingPathway.java b/src/main/java/com/troblecodings/signals/signalbox/ShuntingPathway.java new file mode 100644 index 000000000..09ac80931 --- /dev/null +++ b/src/main/java/com/troblecodings/signals/signalbox/ShuntingPathway.java @@ -0,0 +1,34 @@ +package com.troblecodings.signals.signalbox; + +import com.troblecodings.signals.core.StateInfo; +import com.troblecodings.signals.enums.EnumPathUsage; +import com.troblecodings.signals.handler.SignalBoxHandler; +import com.troblecodings.signals.signalbox.entrys.PathEntryType; + +public class ShuntingPathway extends SignalBoxPathway { + + public ShuntingPathway(final PathwayData data) { + super(data); + } + + @Override + public void setPathStatus(final EnumPathUsage status, final Point point) { + data.foreachEntry(option -> { + option.getEntry(PathEntryType.OUTPUT) + .ifPresent(pos -> SignalBoxHandler.updateRedstoneOutput( + new StateInfo(tile.getLevel(), pos), + !status.equals(EnumPathUsage.FREE))); + if (!status.equals(EnumPathUsage.FREE)) { + option.setEntry(PathEntryType.PATHUSAGE, status); + } else { + option.removeEntry(PathEntryType.PATHUSAGE); + } + }, point); + } + + @Override + public void setUpPathwayStatus() { + setPathStatus(EnumPathUsage.SHUNTING); + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxGrid.java b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxGrid.java index d6730036c..b22ab277c 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxGrid.java +++ b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxGrid.java @@ -25,6 +25,7 @@ import com.troblecodings.signals.core.SubsidiaryState; import com.troblecodings.signals.core.TrainNumber; import com.troblecodings.signals.enums.EnumPathUsage; +import com.troblecodings.signals.enums.PathType; import com.troblecodings.signals.enums.PathwayRequestResult; import com.troblecodings.signals.enums.SignalBoxNetwork; import com.troblecodings.signals.handler.SignalBoxHandler; @@ -49,10 +50,11 @@ public class SignalBoxGrid implements INetworkSavable { private static final String NEXT_PATHWAYS = "nextPathways"; private static final String START_POINT = "startPoint"; private static final String END_POINT = "endPoint"; + private static final String PATH_TYPE = "pathType"; protected final Map startsToPath = new HashMap<>(); protected final Map endsToPath = new HashMap<>(); - protected final List> nextPathways = new ArrayList<>(); + protected final Map, PathType> nextPathways = new HashMap<>(); protected final Map modeGrid = new HashMap<>(); protected final SignalBoxFactory factory; protected SignalBoxTileEntity tile; @@ -109,7 +111,6 @@ public boolean resetPathway(final Point p1) { resetPathway(pathway); updateToNet(pathway); tryNextPathways(); - tile.setChanged(); return true; } @@ -142,17 +143,17 @@ protected void updateToNet(final SignalBoxPathway pathway) { buffer.putInt(nodes.size() + protectionWayNodes.size()); nodes.forEach(node -> { node.getPoint().writeNetwork(buffer); - node.writeUpdateNetwork(buffer); + node.writeNetwork(buffer); }); protectionWayNodes.forEach(node -> { node.getPoint().writeNetwork(buffer); - node.writeUpdateNetwork(buffer); + node.writeNetwork(buffer); }); OpenSignalsMain.network.sendTo(tile.get(0).getPlayer(), buffer); } - public PathwayRequestResult requestWay(final Point p1, final Point p2) { - final PathwayRequestResult result = SignalBoxUtil.requestPathway(this, p1, p2); + public PathwayRequestResult requestWay(final Point p1, final Point p2, final PathType type) { + final PathwayRequestResult result = SignalBoxUtil.requestPathway(this, p1, p2, type); if (!result.isPass()) return result; final PathwayData data = result.getPathwayData(); @@ -175,26 +176,16 @@ protected void addPathway(final PathwayData data) { way.setTile(tile); way.deactivateAllOutputsOnPathway(); way.setSignalBoxGrid(this); - way.setPathStatus(EnumPathUsage.SELECTED); + way.setUpPathwayStatus(); way.updatePathwaySignals(); onWayAdd(way); updateToNet(way); } protected void updatePrevious(final SignalBoxPathway pathway) { - SignalBoxPathway previousPath = pathway; - int count = 0; - while ((previousPath = endsToPath.get(previousPath.getFirstPoint())) != null) { - if (count > endsToPath.size()) { - break; - } + SignalBoxPathway previousPath = endsToPath.get(pathway.getFirstPoint()); + if (previousPath != null) { previousPath.setSignals(); - count++; - } - if (count == 0) { - if (OpenSignalsMain.isDebug()) { - OpenSignalsMain.getLogger().debug("Could not find previous! " + pathway); - } } } @@ -222,12 +213,12 @@ private void clearPaths() { public List getAllInConnections() { return modeGrid.values().stream().filter(SignalBoxNode::containsInConnection) - .map(SignalBoxNode::getPoint).collect(Collectors.toUnmodifiableList()); + .map(SignalBoxNode::getPoint).collect(Collectors.toList()); } public List getValidEnds() { return modeGrid.values().stream().filter(SignalBoxNode::isValidEnd) - .map(SignalBoxNode::getPoint).collect(Collectors.toUnmodifiableList()); + .map(SignalBoxNode::getPoint).collect(Collectors.toList()); } public void updateInput(final RedstoneUpdatePacket update) { @@ -278,47 +269,52 @@ private void tryReset(final List pathways, final BlockPos pos) tryNextPathways(); } - private final List> toAdd = new ArrayList<>(); + private final Map, PathType> toAdd = new HashMap<>(); private boolean executingForEach = false; private void tryNextPathways() { executingForEach = true; - nextPathways.removeIf(entry -> { - final PathwayRequestResult request = requestWay(entry.getKey(), entry.getValue()); + final Map, PathType> toRemove = new HashMap<>(); + nextPathways.forEach((entry, type) -> { + final PathwayRequestResult request = requestWay(entry.getKey(), entry.getValue(), type); if (request == PathwayRequestResult.PASS) { - if (tile == null || !tile.isBlocked()) - return true; + if (tile == null || !tile.isBlocked()) { + toRemove.put(entry, type); + return; + } final WriteBuffer buffer = new WriteBuffer(); buffer.putEnumValue(SignalBoxNetwork.REMOVE_SAVEDPW); entry.getKey().writeNetwork(buffer); entry.getValue().writeNetwork(buffer); OpenSignalsMain.network.sendTo(tile.get(0).getPlayer(), buffer); - return true; + toRemove.put(entry, type); + return; } - return false; }); executingForEach = false; - toAdd.forEach(nextPathways::add); + toRemove.keySet().forEach(nextPathways::remove); + toRemove.clear(); + toAdd.forEach(nextPathways::put); toAdd.clear(); if (startsToPath.isEmpty()) nextPathways.clear(); } - public List> getNextPathways() { - return ImmutableList.copyOf(nextPathways); + public Map, PathType> getNextPathways() { + return ImmutableMap.copyOf(nextPathways); } - public boolean addNextPathway(final Point start, final Point end) { + public boolean addNextPathway(final Point start, final Point end, final PathType type) { final Map.Entry entry = Maps.immutableEntry(start, end); - if (!nextPathways.contains(entry)) { + if (!nextPathways.containsKey(entry)) { final SignalBoxPathway pw = startsToPath.get(start); if (pw != null && pw.isInterSignalBoxPathway()) { return false; } if (executingForEach) { - toAdd.add(entry); + toAdd.put(entry, type); } else { - nextPathways.add(entry); + nextPathways.put(entry, type); } return true; } @@ -365,22 +361,25 @@ public void write(final NBTWrapper tag) { } public void writePathways(final NBTWrapper tag) { - tag.putList(PATHWAY_LIST, - startsToPath.values().stream().filter(pw -> !pw.isEmptyOrBroken()).map(pathway -> { - final NBTWrapper path = new NBTWrapper(); - pathway.write(path); - return path; - })::iterator); - tag.putList(NEXT_PATHWAYS, nextPathways.stream().map(entry -> { - final NBTWrapper wrapper = new NBTWrapper(); - final NBTWrapper start = new NBTWrapper(); - entry.getKey().write(start); - final NBTWrapper end = new NBTWrapper(); - entry.getValue().write(end); - wrapper.putWrapper(START_POINT, start); - wrapper.putWrapper(END_POINT, end); - return wrapper; - })::iterator); + if (!startsToPath.isEmpty()) + tag.putList(PATHWAY_LIST, startsToPath.values().stream() + .filter(pw -> !pw.isEmptyOrBroken()).map(pathway -> { + final NBTWrapper path = new NBTWrapper(); + pathway.write(path); + return path; + })::iterator); + if (!nextPathways.isEmpty()) + tag.putList(NEXT_PATHWAYS, nextPathways.entrySet().stream().map(entry -> { + final NBTWrapper wrapper = new NBTWrapper(); + final NBTWrapper start = new NBTWrapper(); + entry.getKey().getKey().write(start); + final NBTWrapper end = new NBTWrapper(); + entry.getKey().getValue().write(end); + wrapper.putWrapper(START_POINT, start); + wrapper.putWrapper(END_POINT, end); + wrapper.putString(PATH_TYPE, entry.getValue().name()); + return wrapper; + })::iterator); } @Override @@ -406,30 +405,37 @@ public void read(final NBTWrapper tag) { } public void readPathways(final NBTWrapper tag) { - if (!tag.contains(PATHWAY_LIST)) - return; - clearPaths(); - tag.getList(PATHWAY_LIST).forEach(comp -> { - final PathwayData data = PathwayData.of(this, comp); - final SignalBoxPathway pathway = data.createPathway(); - pathway.setSignalBoxGrid(this); - pathway.setTile(tile); - pathway.read(comp); - if (pathway.isEmptyOrBroken()) { - OpenSignalsMain.getLogger() - .error("Remove empty or broken pathway, try to recover!"); - return; - } - onWayAdd(pathway); - pathway.postRead(comp); - }); - tag.getList(NEXT_PATHWAYS).forEach(comp -> { - final Point start = new Point(); - start.read(comp.getWrapper(START_POINT)); - final Point end = new Point(); - end.read(comp.getWrapper(END_POINT)); - nextPathways.add(Maps.immutableEntry(start, end)); - }); + if (tag.contains(PATHWAY_LIST)) { + clearPaths(); + tag.getList(PATHWAY_LIST).forEach(comp -> { + final PathwayData data = PathwayData.of(this, comp); + final SignalBoxPathway pathway = data.createPathway(); + pathway.setSignalBoxGrid(this); + pathway.setTile(tile); + pathway.read(comp); + if (pathway.isEmptyOrBroken()) { + OpenSignalsMain.getLogger() + .error("Remove empty or broken pathway, try to recover!"); + return; + } + onWayAdd(pathway); + pathway.postRead(comp); + }); + } + if (tag.contains(NEXT_PATHWAYS)) + tag.getList(NEXT_PATHWAYS).forEach(comp -> { + final Point start = new Point(); + start.read(comp.getWrapper(START_POINT)); + final Point end = new Point(); + end.read(comp.getWrapper(END_POINT)); + if (comp.contains(PATH_TYPE)) { + nextPathways.put(Maps.immutableEntry(start, end), + PathType.valueOf(comp.getString(PATH_TYPE))); + } else { + nextPathways.put(Maps.immutableEntry(start, end), + SignalBoxUtil.getPathTypeFrom(modeGrid.get(start), modeGrid.get(end))); + } + }); } @Override @@ -564,8 +570,9 @@ public BlockPos updateManuellRSOutput(final Point point, final ModeSet mode, return null; final PathOptionEntry entry = node.getOption(mode).get(); final Optional outputPos = entry.getEntry(PathEntryType.OUTPUT); - final Optional usage = entry.getEntry(PathEntryType.PATHUSAGE); - if (outputPos.isEmpty() || (usage.isPresent() && !usage.get().equals(EnumPathUsage.FREE))) + final EnumPathUsage usage = entry.getEntry(PathEntryType.PATHUSAGE) + .orElse(EnumPathUsage.FREE); + if (!outputPos.isPresent() || !usage.equals(EnumPathUsage.FREE)) return null; if (state) { node.addManuellOutput(mode); @@ -581,7 +588,7 @@ public void updateSubsidiarySignal(final Point point, final ModeSet mode, if (node == null) return; final Optional pos = node.getOption(mode).get().getEntry(PathEntryType.SIGNAL); - if (pos.isEmpty()) + if (!pos.isPresent()) return; final Signal signal = SignalBoxHandler .getSignal(new StateInfo(tile.getLevel(), tile.getBlockPos()), pos.get()); @@ -608,9 +615,10 @@ public void updateSubsidiarySignal(final Point point, final ModeSet mode, return; final SignalStateInfo info = new SignalStateInfo(tile.getLevel(), pos.get(), signal); SignalStateHandler.runTaskWhenSignalLoaded(info, (stateInfo, oldProperties, _u) -> { - SignalStateHandler.setStates(info, properties.state.entrySet().stream() - .filter(propertyEntry -> oldProperties.containsKey(propertyEntry.getKey())) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue))); + SignalStateHandler.setStates(info, + properties.state.entrySet().stream().filter( + propertyEntry -> oldProperties.containsKey(propertyEntry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); }); states.put(mode, entry); enabledSubsidiaryTypes.put(point, states); diff --git a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxNode.java b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxNode.java index 2cf83c7c6..f68bf9e38 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxNode.java +++ b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxNode.java @@ -16,7 +16,6 @@ import com.troblecodings.core.NBTWrapper; import com.troblecodings.core.ReadBuffer; import com.troblecodings.core.WriteBuffer; -import com.troblecodings.signals.core.TrainNumber; import com.troblecodings.signals.enums.EnumGuiMode; import com.troblecodings.signals.enums.EnumPathUsage; import com.troblecodings.signals.enums.PathType; @@ -38,7 +37,6 @@ public class SignalBoxNode implements INetworkSavable, Iterable { private final Point point; private boolean isAutoPoint = false; private String customText = ""; - private TrainNumber trainNumber = TrainNumber.DEFAULT; public SignalBoxNode() { this(new Point()); @@ -95,18 +93,6 @@ public boolean isAutoPoint() { return isAutoPoint; } - public void setTrainNumber(final TrainNumber number) { - this.trainNumber = number; - } - - public void removeTrainNumber() { - this.trainNumber = TrainNumber.DEFAULT; - } - - public TrainNumber getTrainNumber() { - return trainNumber == null ? TrainNumber.DEFAULT : trainNumber; - } - public void post() { possibleConnections.clear(); for (final Map.Entry entry : possibleModes.entrySet()) { @@ -184,39 +170,46 @@ public void write(final NBTWrapper compound) { final NBTWrapper wrapper = new NBTWrapper(); entry.getKey().write(wrapper); entry.getValue().write(wrapper); + if (manuellEnabledOutputs.contains(entry.getKey())) { + wrapper.putBoolean(ENABLED_OUTPUTS, true); + } else { + wrapper.putBoolean(ENABLED_OUTPUTS, false); + } return wrapper; })::iterator); - final List enabledOutputs = new ArrayList<>(); - manuellEnabledOutputs.forEach(mode -> { - final NBTWrapper wrapper = new NBTWrapper(); - mode.write(wrapper); - enabledOutputs.add(wrapper); - }); - compound.putList(ENABLED_OUTPUTS, enabledOutputs); this.point.write(compound); - compound.putBoolean(IS_AUTO_POINT, isAutoPoint); - compound.putString(CUSTOM_NAME, customText); - if (this.trainNumber != null) - trainNumber.writeTag(compound); + if (isAutoPoint) + compound.putBoolean(IS_AUTO_POINT, isAutoPoint); + if (!customText.isEmpty()) + compound.putString(CUSTOM_NAME, customText); } @Override public void read(final NBTWrapper compound) { final SignalBoxFactory factory = SignalBoxFactory.getFactory(); + final boolean oldOutputSystem = compound.contains(ENABLED_OUTPUTS); compound.getList(POINT_LIST).forEach(tag -> { final PathOptionEntry entry = factory.getEntry(); entry.read(tag); - possibleModes.put(new ModeSet(tag), entry); - }); - compound.getList(ENABLED_OUTPUTS).forEach(tag -> { - final ModeSet modeSet = new ModeSet(tag); - if (!manuellEnabledOutputs.contains(modeSet)) - manuellEnabledOutputs.add(modeSet); + final ModeSet mode = new ModeSet(tag); + possibleModes.put(mode, entry); + if (!oldOutputSystem) + if (tag.getBoolean(ENABLED_OUTPUTS)) { + if (!manuellEnabledOutputs.contains(mode)) + manuellEnabledOutputs.add(mode); + } }); + if (oldOutputSystem) + compound.getList(ENABLED_OUTPUTS).forEach(tag -> { + final ModeSet modeSet = new ModeSet(tag); + if (!manuellEnabledOutputs.contains(modeSet)) + manuellEnabledOutputs.add(modeSet); + }); this.point.read(compound); - this.isAutoPoint = compound.getBoolean(IS_AUTO_POINT); - this.customText = compound.getString(CUSTOM_NAME); - this.trainNumber = TrainNumber.of(compound); + if (compound.contains(IS_AUTO_POINT)) + this.isAutoPoint = compound.getBoolean(IS_AUTO_POINT); + if (compound.contains(CUSTOM_NAME)) + this.customText = compound.getString(CUSTOM_NAME); post(); } @@ -236,9 +229,10 @@ public Optional getOption(final Optional mode) { return mode.flatMap(this::getOption); } - public PathType getPathType(final SignalBoxNode other) { + public List getPossibleTypes(final SignalBoxNode other) { + final List possibleTypes = new ArrayList<>(); if (other == null || other.getPoint().equals(this.getPoint())) - return PathType.NONE; + return possibleTypes; final Set thisMode = this.possibleModes.keySet().stream() .map(mode -> mode.mode).collect(Collectors.toSet()); @@ -250,9 +244,9 @@ public PathType getPathType(final SignalBoxNode other) { final boolean otherContains = Arrays.stream(type.getModes()) .anyMatch(otherMode::contains); if (thisContains && otherContains) - return type; + possibleTypes.add(type); } - return PathType.NONE; + return possibleTypes; } public PathwayRequestResult canMakePath(final Path path, final PathType type) { @@ -275,9 +269,27 @@ public PathwayRequestResult canMakePath(final Path path, final PathType type) { } public boolean isUsed() { - for (final PathOptionEntry entry : possibleModes.values()) { - if (!entry.getEntry(PathEntryType.PATHUSAGE).orElse(EnumPathUsage.FREE) - .equals(EnumPathUsage.FREE)) { + for (final Point point : Arrays.asList(this.point.delta(new Point(1, 0)), + this.point.delta(new Point(-1, 0)), this.point.delta(new Point(0, 1)), + this.point.delta(new Point(0, -1)))) { + if (isUsedInDirection(point)) { + return true; + } + } + return false; + } + + public boolean isUsedInDirection(final Point point) { + for (final Path path : possibleConnections.keySet()) { + if (!(path.point1.equals(point) || path.point2.equals(point))) { + continue; + } + final ModeSet mode = getMode(path); + if (mode == null) { + continue; + } + if (!getOption(mode).orElse(new PathOptionEntry()).getEntry(PathEntryType.PATHUSAGE) + .orElse(EnumPathUsage.FREE).equals(EnumPathUsage.FREE)) { return true; } } @@ -365,7 +377,6 @@ public void readNetwork(final ReadBuffer buffer) { } this.isAutoPoint = buffer.getBoolean(); this.customText = buffer.getString(); - this.trainNumber = TrainNumber.of(buffer); post(); } @@ -388,7 +399,6 @@ public void readUpdateNetwork(final ReadBuffer buffer) { } this.isAutoPoint = buffer.getBoolean(); this.customText = buffer.getString(); - this.trainNumber = TrainNumber.of(buffer); post(); } @@ -403,22 +413,19 @@ public void writeNetwork(final WriteBuffer buffer) { manuellEnabledOutputs.forEach(mode -> mode.writeNetwork(buffer)); buffer.putBoolean(isAutoPoint); buffer.putString(customText); - if (trainNumber != null) { - trainNumber.writeNetwork(buffer); - } else { - TrainNumber.DEFAULT.writeNetwork(buffer); - } } public void writeUpdateNetwork(final WriteBuffer buffer) { int size = 0; for (final PathOptionEntry entry : possibleModes.values()) { - if (entry.containsEntry(PathEntryType.PATHUSAGE)) + if (entry.containsEntry(PathEntryType.PATHUSAGE) + || entry.containsEntry(PathEntryType.TRAINNUMBER)) size++; } buffer.putByte((byte) size); possibleModes.forEach((mode, entry) -> { - if (entry.containsEntry(PathEntryType.PATHUSAGE)) { + if (entry.containsEntry(PathEntryType.PATHUSAGE) + || entry.containsEntry(PathEntryType.TRAINNUMBER)) { mode.writeNetwork(buffer); entry.writeUpdateNetwork(buffer); } @@ -426,11 +433,6 @@ public void writeUpdateNetwork(final WriteBuffer buffer) { buffer.putByte((byte) 0); buffer.putBoolean(isAutoPoint); buffer.putString(customText); - if (trainNumber != null) { - trainNumber.writeNetwork(buffer); - } else { - TrainNumber.DEFAULT.writeNetwork(buffer); - } } public String getCustomText() { diff --git a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxPathway.java b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxPathway.java index 4238521ac..1c1de1770 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxPathway.java +++ b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxPathway.java @@ -16,6 +16,8 @@ import com.troblecodings.signals.OpenSignalsMain; import com.troblecodings.signals.blocks.RedstoneIO; import com.troblecodings.signals.blocks.Signal; +import com.troblecodings.signals.core.BlockPosSignalHolder; +import com.troblecodings.signals.core.ModeIdentifier; import com.troblecodings.signals.core.StateInfo; import com.troblecodings.signals.core.SubsidiaryEntry; import com.troblecodings.signals.core.TrainNumber; @@ -30,6 +32,7 @@ import com.troblecodings.signals.signalbox.config.ResetInfo; import com.troblecodings.signals.signalbox.config.SignalConfig; import com.troblecodings.signals.signalbox.entrys.PathEntryType; +import com.troblecodings.signals.signalbox.entrys.PathOptionEntry; import com.troblecodings.signals.tileentitys.IChunkLoadable; import net.minecraft.core.BlockPos; @@ -41,6 +44,7 @@ public class SignalBoxPathway implements IChunkLoadable { protected final PathwayData data; + protected final SignalConfig config; protected boolean isBlocked; protected boolean isAutoPathway = false; @@ -55,6 +59,7 @@ public void setTile(final SignalBoxTileEntity tile) { } public SignalBoxPathway(final PathwayData data) { + this.config = new SignalConfig(this); this.data = data; this.originalFirstPoint = new Point(data.getFirstPoint()); updatePathwayToAutomatic(); @@ -104,7 +109,11 @@ public void setPathStatus(final EnumPathUsage status, final @Nullable Point poin .ifPresent(pos -> SignalBoxHandler.updateRedstoneOutput( new StateInfo(tile.getLevel(), pos), !status.equals(EnumPathUsage.FREE))); - option.setEntry(PathEntryType.PATHUSAGE, status); + if (!status.equals(EnumPathUsage.FREE)) { + option.setEntry(PathEntryType.PATHUSAGE, status); + } else { + option.removeEntry(PathEntryType.PATHUSAGE); + } }, point); if (status.equals(EnumPathUsage.SELECTED) || status.equals(EnumPathUsage.PREPARED)) { setProtectionWay(); @@ -137,10 +146,20 @@ public void removeProtectionWay() { data.removeProtectionWay(); } + public void setUpPathwayStatus() { + setPathStatus(EnumPathUsage.SELECTED); + } + public void setPathStatus(final EnumPathUsage status) { setPathStatus(status, null); } + public void updatePrevious() { + if (grid == null) + return; + grid.updatePrevious(this); + } + protected SignalStateInfo lastSignalInfo = null; protected SignalStateInfo getLastSignalInfo() { @@ -187,11 +206,19 @@ protected void setSignals(final SignalStateInfo lastSignal) { if (first == null) return; final SignalStateInfo firstInfo = new SignalStateInfo(world, startSignal.pos, first); - SignalConfig.change(new ConfigInfo(firstInfo, lastSignal, data)); + config.change(new ConfigInfo(firstInfo, lastSignal, data)); updatePreSignals(); } - final Map distantSignalPositions = data.getOtherSignals(); - distantSignalPositions.values().forEach(position -> { + final SignalBoxPathway next = getNextPathway(); + if (next != null && (next.isEmptyOrBroken() || next.isBlocked)) { + updateSignalStates(); + return; + } + final Map distantSignalPositions = data + .getOtherSignals(); + distantSignalPositions.forEach((holder, position) -> { + if (holder.shouldTurnSignalOff()) + return; final Signal current = SignalBoxHandler.getSignal(identifier, position.pos); if (current == null) return; @@ -199,9 +226,9 @@ protected void setSignals(final SignalStateInfo lastSignal) { new SignalStateInfo(world, position.pos, current), lastSignal, data, position.isRepeater); if (position.guiMode.equals(EnumGuiMode.HP)) { - SignalConfig.loadDisable(info); + config.loadDisable(info); } else { - SignalConfig.change(info); + config.change(info); } }); updateSignalStates(); @@ -211,6 +238,10 @@ private void updatePreSignals() { final MainSignalIdentifier startSignal = data.getStartSignal(); if (startSignal == null) return; + final SignalBoxPathway next = getNextPathway(); + if (next != null && (next.isEmptyOrBroken() || next.isBlocked)) { + return; + } final StateInfo identifier = new StateInfo(tile.getLevel(), tile.getBlockPos()); final Signal first = SignalBoxHandler.getSignal(identifier, startSignal.pos); if (first == null) @@ -221,7 +252,7 @@ private void updatePreSignals() { final Signal current = SignalBoxHandler.getSignal(identifier, posIdent.pos); if (current == null) return; - SignalConfig.change( + config.change( new ConfigInfo(new SignalStateInfo(tile.getLevel(), posIdent.pos, current), firstInfo, data, posIdent.isRepeater)); }); @@ -233,24 +264,34 @@ protected void updateSignalStates() { final MainSignalIdentifier startSignal = data.getStartSignal(); final MainSignalIdentifier endSignal = data.getEndSignal(); if (startSignal != null) { - if (isBlocked) - return; - final SignalState previous = startSignal.state; - startSignal.state = SignalState.GREEN; - if (!startSignal.state.equals(previous)) - greenSignals.add(startSignal); - data.getPreSignals().forEach(signalIdent -> { - signalIdent.state = SignalState.GREEN; - greenSignals.add(signalIdent); - }); + if (!isBlocked) { + final SignalState previous = startSignal.state; + startSignal.state = SignalState.GREEN; + if (!startSignal.state.equals(previous)) + greenSignals.add(startSignal); + data.getPreSignals().forEach(signalIdent -> { + signalIdent.state = SignalState.GREEN; + greenSignals.add(signalIdent); + }); + } } - final Map distantSignalPositions = data.getOtherSignals(); - distantSignalPositions.values().forEach(position -> { + final Map distantSignalPositions = data + .getOtherSignals(); + distantSignalPositions.forEach((holder, position) -> { + if (holder.shouldTurnSignalOff()) { + position.state = SignalState.OFF; + greenSignals.add(position); + return; + } final SignalBoxPathway next = getNextPathway(); final SignalState previous = position.state; if (endSignal != null && next != null && !next.isEmptyOrBroken()) { - if (!next.isExecutingSignalSet) + if (!next.isExecutingSignalSet) { position.state = SignalState.GREEN; + } + if (next.isBlocked) { + position.state = SignalState.RED; + } } else { position.state = SignalState.RED; } @@ -280,7 +321,8 @@ public List getGreenSignals() { if (startSignal.state.equals(SignalState.GREEN)) returnList.add(startSignal); } - final Map distantSignalPositions = data.getOtherSignals(); + final Map distantSignalPositions = data + .getOtherSignals(); distantSignalPositions.values().forEach(signal -> { if (signal.state.equals(SignalState.GREEN) || signal.state.equals(SignalState.OFF)) returnList.add(signal); @@ -373,8 +415,13 @@ private void resetFirstSignal() { private void resetOther() { final List redSignals = new ArrayList<>(); - final Map distantSignalPositions = data.getOtherSignals(); - distantSignalPositions.values().forEach(position -> { + final Map distantSignalPositions = data + .getOtherSignals(); + distantSignalPositions.forEach((holder, position) -> { + if (holder.shouldTurnSignalOff()) { + position.state = SignalState.RED; + redSignals.add(position); + } final Signal current = SignalBoxHandler .getSignal(new StateInfo(tile.getLevel(), tile.getBlockPos()), position.pos); if (current == null) @@ -395,7 +442,6 @@ public void resetPathway(final @Nullable Point point) { this.setPathStatus(EnumPathUsage.FREE, point); resetFirstSignal(); if (data.totalPathwayReset(point)) { - this.isBlocked = false; resetOther(); resetAllTrainNumbers(); sendTrainNumberUpdates(); @@ -421,11 +467,13 @@ public void compact(final Point point) { new StateInfo(tile.getLevel(), tile.getBlockPos()), position); if (current == null) return; - final Map distantSignalPositions = data + final Map distantSignalPositions = data .getOtherSignals(); final OtherSignalIdentifier identifier = distantSignalPositions - .getOrDefault(position, new OtherSignalIdentifier(point, - new ModeSet(mode, rotation), position, false, mode)); + .getOrDefault(new BlockPosSignalHolder(position), + new OtherSignalIdentifier(point, + new ModeSet(mode, rotation), position, false, + mode)); SignalConfig.reset(new ResetInfo( new SignalStateInfo(tile.getLevel(), position, current), identifier.isRepeater)); @@ -434,9 +482,17 @@ public void compact(final Point point) { if (!identifier.state.equals(previous)) { redSignals.add(identifier); } + final OtherSignalIdentifier otherIdent = distantSignalPositions + .get(new BlockPosSignalHolder(position, true)); + if (otherIdent != null) { + otherIdent.state = SignalState.RED; + redSignals.add(otherIdent); + } })); } }, point); + resetAllTrainNumbers(data.getTrainNumberDisplays()); + sendTrainNumberUpdates(); data.compact(point); updateSignalsOnClient(redSignals); updateTrainNumber(trainNumber); @@ -539,9 +595,9 @@ public void checkTrainNumberUpdate(final TrainNumber number, final SignalBoxNode protected void updateTrainNumber(final TrainNumber number) { resetAllTrainNumbers(); - final List listOfNodes = data.getListOfNodes(); - final SignalBoxNode setNode = listOfNodes.get((listOfNodes.size() - 1) / 2); - setNode.setTrainNumber(number); + final List trainNumberDisplays = data.getTrainNumberDisplays(); + trainNumberDisplays.forEach(ident -> grid.getNode(ident.point).getOption(ident.mode) + .orElse(new PathOptionEntry()).setEntry(PathEntryType.TRAINNUMBER, number)); this.trainNumber = number; sendTrainNumberUpdates(); } @@ -549,20 +605,26 @@ protected void updateTrainNumber(final TrainNumber number) { private void sendTrainNumberUpdates() { if (!this.tile.isBlocked()) return; - final List listOfNodes = data.getListOfNodes(); + final List trainNumberDisplays = data.getTrainNumberDisplays(); final WriteBuffer buffer = new WriteBuffer(); buffer.putEnumValue(SignalBoxNetwork.SEND_TRAIN_NUMBER); - buffer.putInt(listOfNodes.size()); - listOfNodes.forEach(node -> { + buffer.putInt(trainNumberDisplays.size()); + trainNumberDisplays.forEach(ident -> { + final SignalBoxNode node = grid.getNode(ident.point); node.getPoint().writeNetwork(buffer); - node.getTrainNumber().writeNetwork(buffer); + node.writeNetwork(buffer); }); OpenSignalsMain.network.sendTo(tile.get(0).getPlayer(), buffer); } private void resetAllTrainNumbers() { - final List listOfNodes = data.getListOfNodes(); - listOfNodes.forEach(node -> node.removeTrainNumber()); + resetAllTrainNumbers(data.getTrainNumberDisplays()); + } + + private void resetAllTrainNumbers(final List trainNumberDisplays) { + if (grid != null && trainNumberDisplays != null) + trainNumberDisplays.forEach(ident -> grid.getNode(ident.point).getOption(ident.mode) + .orElse(new PathOptionEntry()).removeEntry(PathEntryType.TRAINNUMBER)); } public void deactivateAllOutputsOnPathway() { @@ -599,7 +661,7 @@ protected boolean loadTileAndExecute(final BlockPos tilePos, public void checkReRequest() { if (isAutoPathway) { - grid.requestWay(originalFirstPoint, getLastPoint()); + grid.requestWay(originalFirstPoint, getLastPoint(), getPathType()); } } @@ -668,4 +730,8 @@ public PathType getPathType() { public boolean isInterSignalBoxPathway() { return this instanceof InterSignalBoxPathway; } -} \ No newline at end of file + + public SignalBoxGrid getGrid() { + return grid; + } +} diff --git a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxUtil.java b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxUtil.java index 9c5190fec..f5f846410 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxUtil.java +++ b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxUtil.java @@ -23,6 +23,7 @@ public final class SignalBoxUtil { public static final int SELECTED_COLOR = ConfigHandler.CLIENT.signalboxSelectColor.get(); public static final int USED_COLOR = ConfigHandler.CLIENT.signalboxUsedColor.get(); public static final int PREPARED_COLOR = ConfigHandler.CLIENT.signalboxPreparedColor.get(); + public static final int SHUNTING_COLOR = ConfigHandler.CLIENT.signalboxShuntingColor.get(); private SignalBoxUtil() { } @@ -66,13 +67,11 @@ public Point getPoint() { } public static PathwayRequestResult requestPathway(final SignalBoxGrid grid, final Point p1, - final Point p2) { + final Point p2, final PathType pathType) { final Map modeGrid = grid.modeGrid; if (!modeGrid.containsKey(p1) || !modeGrid.containsKey(p2)) return PathwayRequestResult.NOT_IN_GRID; - final SignalBoxNode lastNode = modeGrid.get(p2); final SignalBoxNode firstNode = modeGrid.get(p1); - final PathType pathType = firstNode.getPathType(lastNode); if (pathType.equals(PathType.NONE)) return PathwayRequestResult.NO_EQUAL_PATH_TYPE; @@ -195,6 +194,7 @@ public static int getDefaultCosts(final ModeSet mode) { case STRAIGHT: case END: case IN_CONNECTION: + case ARROW: case OUT_CONNECTION: { return 0; } @@ -207,4 +207,12 @@ public static int getDefaultCosts(final ModeSet mode) { } } -} \ No newline at end of file + public static PathType getPathTypeFrom(final SignalBoxNode start, final SignalBoxNode end) { + final List possilbeTypes = start.getPossibleTypes(end); + if (!possilbeTypes.isEmpty()) { + return possilbeTypes.get(0); + } else { + return PathType.NONE; + } + } +} diff --git a/src/main/java/com/troblecodings/signals/signalbox/config/SignalConfig.java b/src/main/java/com/troblecodings/signals/signalbox/config/SignalConfig.java index 9ac6b27bf..813073426 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/config/SignalConfig.java +++ b/src/main/java/com/troblecodings/signals/signalbox/config/SignalConfig.java @@ -11,20 +11,30 @@ import com.troblecodings.signals.contentpacks.ChangeConfigParser; import com.troblecodings.signals.contentpacks.OneSignalNonPredicateConfigParser; import com.troblecodings.signals.contentpacks.OneSignalPredicateConfigParser; +import com.troblecodings.signals.core.LoadHolder; +import com.troblecodings.signals.core.SignalStateListener; +import com.troblecodings.signals.core.SignalStateLoadHoler; import com.troblecodings.signals.enums.PathType; import com.troblecodings.signals.handler.SignalStateHandler; import com.troblecodings.signals.handler.SignalStateInfo; import com.troblecodings.signals.properties.PredicatedPropertyBase.ConfigProperty; +import com.troblecodings.signals.signalbox.SignalBoxPathway; public final class SignalConfig { - private SignalConfig() { + private static final LoadHolder> LOAD_HOLDER = new LoadHolder<>( + SignalConfig.class); + + private final SignalBoxPathway pathway; + + public SignalConfig(final SignalBoxPathway pathway) { + this.pathway = pathway; } - public static void change(final ConfigInfo info) { + public void change(final ConfigInfo info) { final Signal currentSignal = info.currentinfo.signal; if (info.type.equals(PathType.NORMAL)) { - if (info.nextinfo != null) { + if (info.nextinfo != null && info.nextinfo.isValid()) { final Signal nextSignal = info.nextinfo.signal; final List values = ChangeConfigParser.CHANGECONFIGS .get(Maps.immutableEntry(currentSignal, nextSignal)); @@ -39,13 +49,15 @@ public static void change(final ConfigInfo info) { } else if (info.type.equals(PathType.SHUNTING)) { final List shuntingValues = OneSignalNonPredicateConfigParser.SHUNTINGCONFIGS .get(currentSignal); - if (shuntingValues != null) { + if (shuntingValues != null && info.currentinfo.isValid()) { loadWithoutPredicate(shuntingValues, info.currentinfo); } } } - private static void loadDefault(final ConfigInfo info) { + private void loadDefault(final ConfigInfo info) { + if (!info.currentinfo.isValid()) + return; final List defaultValues = OneSignalPredicateConfigParser.DEFAULTCONFIGS .get(info.currentinfo.signal); if (defaultValues != null) { @@ -58,7 +70,7 @@ public static void reset(final ResetInfo info) { .get(info.current.signal); if (resetValues == null) return; - SignalStateHandler.runTaskWhenSignalLoaded(info.current, (stateInfo, oldProperties, _u) -> { + loadSignalAndRunTask(info.current, (stateInfo, oldProperties, _u) -> { final Map, Object> object = new HashMap<>(); object.put(Boolean.class, info.isRepeater); object.put(Map.class, oldProperties); @@ -68,8 +80,7 @@ public static void reset(final ResetInfo info) { if (property.test(object)) { propertiesToSet.putAll(property.state.entrySet().stream() .filter(entry -> oldProperties.containsKey(entry.getKey())) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); } }); if (!propertiesToSet.isEmpty()) @@ -77,7 +88,7 @@ public static void reset(final ResetInfo info) { }); } - public static void loadDisable(final ConfigInfo info) { + public void loadDisable(final ConfigInfo info) { final List disableValues = OneSignalPredicateConfigParser.DISABLECONFIGS .get(info.currentinfo.signal); if (disableValues != null) { @@ -85,27 +96,24 @@ public static void loadDisable(final ConfigInfo info) { } } - private static void changeIfPresent(final List values, final ConfigInfo info) { - SignalStateHandler.runTaskWhenSignalLoaded(info.currentinfo, - (stateInfo, oldProperties, _u) -> { - if (info.nextinfo != null) { - SignalStateHandler.runTaskWhenSignalLoaded(info.nextinfo, - (nextInfo, nextProperties, _u2) -> changeSignals(values, info, - oldProperties, nextProperties)); - } else { - changeSignals(values, info, oldProperties, null); - } + private void changeIfPresent(final List values, final ConfigInfo info) { + loadSignalAndRunTask(info.currentinfo, (stateInfo, oldProperties, _u) -> { + if (info.nextinfo != null) { + loadSignalAndRunTask(info.nextinfo, (nextInfo, nextProperties, _u2) -> { + changeSignals(values, info, oldProperties, nextProperties); }); + } else { + changeSignals(values, info, oldProperties, null); + } + }); } - private static void changeSignals(final List values, final ConfigInfo info, + private void changeSignals(final List values, final ConfigInfo info, final Map oldProperties, final Map nextProperties) { final Map, Object> object = new HashMap<>(); - if (info.nextinfo != null) { - object.put(Map.class, nextProperties); - } + object.put(Map.class, nextProperties != null ? nextProperties : new HashMap<>()); object.put(Integer.class, info.speed); object.put(String.class, info.zs2Value); object.put(Boolean.class, info.isSignalRepeater); @@ -114,28 +122,40 @@ private static void changeSignals(final List values, final Confi if (property.test(object)) { propertiesToSet.putAll(property.state.entrySet().stream() .filter(entry -> oldProperties.containsKey(entry.getKey())) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); } }); - if (!propertiesToSet.isEmpty()) + if (!propertiesToSet.isEmpty()) { SignalStateHandler.setStates(info.currentinfo, propertiesToSet); + pathway.updatePrevious(); + } } - private static void loadWithoutPredicate(final List values, + private void loadWithoutPredicate(final List values, final SignalStateInfo current) { if (values != null) { - SignalStateHandler.runTaskWhenSignalLoaded(current, (info, oldProperties, _u) -> { + loadSignalAndRunTask(current, (info, oldProperties, _u) -> { final Map propertiesToSet = new HashMap<>(); values.forEach(property -> { propertiesToSet.putAll(property.state.entrySet().stream() .filter(entry -> oldProperties.containsKey(entry.getKey())) - .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, - Map.Entry::getValue))); + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); }); if (!propertiesToSet.isEmpty()) SignalStateHandler.setStates(current, propertiesToSet); + pathway.updatePrevious(); }); } } + + private static void loadSignalAndRunTask(final SignalStateInfo info, + final SignalStateListener task) { + final boolean isSignalLoaded = SignalStateHandler.isSignalLoaded(info); + if (!isSignalLoaded) { + SignalStateHandler.loadSignal(new SignalStateLoadHoler(info, LOAD_HOLDER)); + task.andThen((_u1, _u2, _u3) -> SignalStateHandler + .unloadSignal(new SignalStateLoadHoler(info, LOAD_HOLDER))); + } + SignalStateHandler.runTaskWhenSignalLoaded(info, task); + } } \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/signalbox/entrys/ModeIdentifierEntry.java b/src/main/java/com/troblecodings/signals/signalbox/entrys/ModeIdentifierEntry.java new file mode 100644 index 000000000..1bbd80ea4 --- /dev/null +++ b/src/main/java/com/troblecodings/signals/signalbox/entrys/ModeIdentifierEntry.java @@ -0,0 +1,42 @@ +package com.troblecodings.signals.signalbox.entrys; + +import com.troblecodings.core.NBTWrapper; +import com.troblecodings.core.ReadBuffer; +import com.troblecodings.core.WriteBuffer; +import com.troblecodings.signals.core.ModeIdentifier; + +public class ModeIdentifierEntry extends IPathEntry { + + private ModeIdentifier identifier; + + @Override + public void readNetwork(final ReadBuffer buffer) { + identifier = ModeIdentifier.of(buffer); + } + + @Override + public void writeNetwork(final WriteBuffer buffer) { + identifier.writeNetwork(buffer); + } + + @Override + public void write(final NBTWrapper tag) { + identifier.write(tag); + } + + @Override + public void read(final NBTWrapper tag) { + identifier = ModeIdentifier.of(tag); + } + + @Override + public ModeIdentifier getValue() { + return identifier; + } + + @Override + public void setValue(final ModeIdentifier value) { + identifier = value; + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/signalbox/entrys/PathEntryType.java b/src/main/java/com/troblecodings/signals/signalbox/entrys/PathEntryType.java index 2e01f17e5..b55570f4b 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/entrys/PathEntryType.java +++ b/src/main/java/com/troblecodings/signals/signalbox/entrys/PathEntryType.java @@ -7,7 +7,9 @@ import java.util.Objects; import com.google.common.collect.ImmutableList; +import com.troblecodings.signals.core.ModeIdentifier; import com.troblecodings.signals.core.PosIdentifier; +import com.troblecodings.signals.core.TrainNumber; import com.troblecodings.signals.enums.EnumPathUsage; import com.troblecodings.signals.signalbox.Point; @@ -70,6 +72,12 @@ private PathEntryType(final Class> entryClass, final Str public static final PathEntryType PROTECTIONWAY_RESET = new PathEntryType<>( BlockposEntry.class, "protectionway_reset"); + public static final PathEntryType CONNECTED_TRAINNUMBER = new PathEntryType<>( + ModeIdentifierEntry.class, "connected_point"); + + public static final PathEntryType TRAINNUMBER = new PathEntryType<>( + TrainNumberEntry.class, "trainnumber"); + private static final class EnumPathUsageEntry extends EnumEntry { public EnumPathUsageEntry() { diff --git a/src/main/java/com/troblecodings/signals/signalbox/entrys/PathOptionEntry.java b/src/main/java/com/troblecodings/signals/signalbox/entrys/PathOptionEntry.java index 773cb9c19..4fb97c571 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/entrys/PathOptionEntry.java +++ b/src/main/java/com/troblecodings/signals/signalbox/entrys/PathOptionEntry.java @@ -109,8 +109,17 @@ public void writeNetwork(final WriteBuffer buffer) { } public void writeUpdateNetwork(final WriteBuffer builder) { - builder.putByte((byte) 1); - builder.putByte((byte) PathEntryType.PATHUSAGE.getID()); - pathEntrys.get(PathEntryType.PATHUSAGE).writeNetwork(builder); + int size = 0; + for (final PathEntryType entry : pathEntrys.keySet()) { + if (entry.equals(PathEntryType.PATHUSAGE) || entry.equals(PathEntryType.TRAINNUMBER)) + size++; + } + builder.putByte((byte) size); + pathEntrys.forEach((mode, entry) -> { + if (mode.equals(PathEntryType.PATHUSAGE) || mode.equals(PathEntryType.TRAINNUMBER)) { + builder.putByte((byte) mode.getID()); + entry.writeNetwork(builder); + } + }); } } \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/signalbox/entrys/TrainNumberEntry.java b/src/main/java/com/troblecodings/signals/signalbox/entrys/TrainNumberEntry.java new file mode 100644 index 000000000..c439f438b --- /dev/null +++ b/src/main/java/com/troblecodings/signals/signalbox/entrys/TrainNumberEntry.java @@ -0,0 +1,42 @@ +package com.troblecodings.signals.signalbox.entrys; + +import com.troblecodings.core.NBTWrapper; +import com.troblecodings.core.ReadBuffer; +import com.troblecodings.core.WriteBuffer; +import com.troblecodings.signals.core.TrainNumber; + +public class TrainNumberEntry extends IPathEntry { + + private TrainNumber number = TrainNumber.DEFAULT; + + @Override + public void readNetwork(final ReadBuffer buffer) { + number = TrainNumber.of(buffer); + } + + @Override + public void writeNetwork(final WriteBuffer buffer) { + number.writeNetwork(buffer); + } + + @Override + public void write(final NBTWrapper tag) { + number.writeTag(tag); + } + + @Override + public void read(final NBTWrapper tag) { + number = TrainNumber.of(tag); + } + + @Override + public TrainNumber getValue() { + return number; + } + + @Override + public void setValue(final TrainNumber value) { + number = value; + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/signalbridge/SignalBridgeBuilder.java b/src/main/java/com/troblecodings/signals/signalbridge/SignalBridgeBuilder.java index f1dc68159..fd6478930 100644 --- a/src/main/java/com/troblecodings/signals/signalbridge/SignalBridgeBuilder.java +++ b/src/main/java/com/troblecodings/signals/signalbridge/SignalBridgeBuilder.java @@ -94,7 +94,7 @@ public VectorWrapper getVecForSignal(final Entry entry) { public boolean hasBlockOn(final VectorWrapper vec, final Entry entry) { final boolean isCollidingWithBlock = vec.getZ() == 0 - ? pointForBlocks.containsKey(new Point(vec.getX(), vec.getY())) + ? pointForBlocks.containsKey(new Point((int) vec.getX(), (int) vec.getY())) : false; final VectorWrapper signalVec = vecForSignal.get(entry); return isCollidingWithBlock || (!vec.equals(signalVec) && vecForSignal.containsValue(vec)); diff --git a/src/main/java/com/troblecodings/signals/tileentitys/PathwayRequesterTileEntity.java b/src/main/java/com/troblecodings/signals/tileentitys/PathwayRequesterTileEntity.java index c41a9392d..9c020a690 100644 --- a/src/main/java/com/troblecodings/signals/tileentitys/PathwayRequesterTileEntity.java +++ b/src/main/java/com/troblecodings/signals/tileentitys/PathwayRequesterTileEntity.java @@ -8,10 +8,12 @@ import com.troblecodings.signals.OpenSignalsMain; import com.troblecodings.signals.blocks.SignalBox; import com.troblecodings.signals.core.TileEntityInfo; +import com.troblecodings.signals.enums.PathType; import com.troblecodings.signals.enums.PathwayRequestResult; import com.troblecodings.signals.signalbox.Point; import com.troblecodings.signals.signalbox.SignalBoxGrid; import com.troblecodings.signals.signalbox.SignalBoxTileEntity; +import com.troblecodings.signals.signalbox.SignalBoxUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; @@ -68,10 +70,14 @@ public void requestPathway() { loadChunkAndGetTile(SignalBoxTileEntity.class, (ServerLevel) level, linkedSignalBox, (tile, _u) -> { final SignalBoxGrid grid = tile.getSignalBoxGrid(); - final PathwayRequestResult result = grid.requestWay(pathway.getKey(), - pathway.getValue()); - if (!result.isPass() && result.canBeAddedToSaver() && addPWToSaver) { - grid.addNextPathway(pathway.getKey(), pathway.getValue()); + final PathType type = SignalBoxUtil.getPathTypeFrom( + grid.getNode(pathway.getKey()), grid.getNode(pathway.getValue())); + if (!type.equals(PathType.NONE)) { + final PathwayRequestResult result = grid.requestWay(pathway.getKey(), + pathway.getValue(), type); + if (!result.isPass() && result.canBeAddedToSaver() && addPWToSaver) { + grid.addNextPathway(pathway.getKey(), pathway.getValue(), type); + } } }); diff --git a/src/main/resources/assets/opensignals/enumdefinition/enums.json b/src/main/resources/assets/opensignals/enumdefinition/enums.json index f518f7c6d..f379c71cd 100644 --- a/src/main/resources/assets/opensignals/enumdefinition/enums.json +++ b/src/main/resources/assets/opensignals/enumdefinition/enums.json @@ -457,7 +457,8 @@ "SO19_1", "SO19_2", "SO19_3", - "SO106" + "SO106", + "TRAIN_LENGTH" ], "NEAddition": [ "OFF", @@ -474,7 +475,8 @@ "M200", "M250", "KURZ", - "LANG" + "LANG", + "FREE" ], "WNMech": [ "WN1", diff --git a/src/main/resources/assets/opensignals/lang/de_de.json b/src/main/resources/assets/opensignals/lang/de_de.json index 9ccc6fb4e..40855e71b 100644 --- a/src/main/resources/assets/opensignals/lang/de_de.json +++ b/src/main/resources/assets/opensignals/lang/de_de.json @@ -666,5 +666,13 @@ "property.value.DISTANT_LEFT": "Vorsignal links", "property.value.DISTANT_RIGHT": "Vorsignal rechts", "block.opensignals.postconnectable": "Verbindungsfähiger Mast", - "property.value.GSMR": "GSMR Tafel" + "property.value.GSMR": "GSMR Tafel", + "info.key.removeother": "Andere entfernen?", + "info.train_number": "Zugnummernfeld", + "property.TRAIN_NUMBER": "Zugnummernfeld", + "btn.connect.trainnumber": "Zugnummernfeld verbinden", + "gui.tile.notvalid": "Nicht erlaubt", + "property.SHUNTING": "Rangieren", + "gui.signalbox.choosetypes": "Wähle Fahrstraßentyp", + "property.mode_select.name": "Wähle Streckenelement" } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/lang/en_us.json b/src/main/resources/assets/opensignals/lang/en_us.json index 1cff45a12..51fbf6381 100644 --- a/src/main/resources/assets/opensignals/lang/en_us.json +++ b/src/main/resources/assets/opensignals/lang/en_us.json @@ -637,7 +637,7 @@ "property.pathway_costs.desc": "This option can be used to increase the 'costs' for certain path elements so that the path algorithm avoids this path if possible. This is particularly helpful if you want to influence the pathway manually.", "info.node.text": "Labeling", "property.can_be_overstepped.name": "Can be skipped", - "property.can_be_overstepped.desc": "The signal can be skipped. This means that the pathway can be set to the next signal and this signal shows identifier light (turned off).", + "property.can_be_overstepped.desc": "The signal can be skipped. This means that the pathway can be set to the next signal and this signal shows identifier light (turned off).", "property.presignals.name": "Define Presignals", "property.presignals.desc": "Here you can define corresponding distant signals that also activate when the main signal is in the driving position, even without an active pathway.", "info.usage.trainnumber": "Train number", @@ -646,15 +646,15 @@ "info.usage.changetrainnumber": "Set train number", "info.arrow": "Dead signal", "info.ne1": "Ne1 - Trapezoid sign", - "info.ne5": "Ne5 - Holding sign", - "info.zs3": "Zs3 - Speed indicator signal", + "info.ne5": "Ne5 - Holding sign", + "info.zs3": "Zs3 - Speed indicator signal", "block.opensignals.zs32": "Zs3/Zs2", - "tile.zs32.name": "Zs3/Zs2", - "property.ZS3": "Zs3/Zs2", - "property.protectionway.name": "Overlap", - "property.protectionway.desc": "Select a section of path behind the destination signal. The overlap is set up to this point. The overlap (pass-through path) is a protective section behind the destination signal that must be secured and kept clear if trains do not come to a stop in front of the signal as planned and path-through past the signal.", + "tile.zs32.name": "Zs3/Zs2", + "property.ZS3": "Zs3/Zs2", + "property.protectionway.name": "Overlap", + "property.protectionway.desc": "Select a section of path behind the destination signal. The overlap is set up to this point. The overlap (pass-through path) is a protective section behind the destination signal that must be secured and kept clear if trains do not come to a stop in front of the signal as planned and path-through past the signal.", "property.reset_protectionway_delay.name": "Delay-Overlap-reset", - "property.reset_protectionway_delay.desc": "", + "property.reset_protectionway_delay.desc": "", "info.usage.savedpathways.desc": "All saved pathways are listed here. You can display or delete the pathways.", "property.prop.INPUT.protectionway_reset.name": "Overlap reset", "property.prop.INPUT.protectionway_reset.desc": "Select a redstone input which will trigger the overlap reset.", @@ -666,5 +666,13 @@ "property.value.DISTANT_LEFT": "Distant signal left", "property.value.DISTANT_RIGHT": "Distant signal right", "block.opensignals.postconnectable": "Connectable Pole", - "property.value.GSMR": "GSMR Plate" + "property.value.GSMR": "GSMR Plate", + "info.key.removeother": "Remove other?", + "info.train_number": "Train number field", + "property.TRAIN_NUMBER": "Train number field", + "btn.connect.trainnumber": "Connect trainnumber", + "gui.tile.notvalid": "Not valid", + "property.SHUNTING": "Shunting", + "gui.signalbox.choosetypes": "Choose pathway type", + "property.mode_select.name": "Select track element" } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/modeldefinitions/ne5_addition.extention.json b/src/main/resources/assets/opensignals/modeldefinitions/ne5_addition.extention.json index 8ed982811..2ce7e1201 100644 --- a/src/main/resources/assets/opensignals/modeldefinitions/ne5_addition.extention.json +++ b/src/main/resources/assets/opensignals/modeldefinitions/ne5_addition.extention.json @@ -8,6 +8,7 @@ "M200": "opensignals:blocks/ne/ne5_add_200", "M250": "opensignals:blocks/ne/ne5_add_250", "KURZ": "opensignals:blocks/ne/ne5_add_kurzzug", - "LANG": "opensignals:blocks/ne/ne5_add_langzug" + "LANG": "opensignals:blocks/ne/ne5_add_langzug", + "FREE": "opensignals:blocks/default/white" } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/modeldefinitions/nesignal.json b/src/main/resources/assets/opensignals/modeldefinitions/nesignal.json index 6ef4d619c..c1b1e911e 100644 --- a/src/main/resources/assets/opensignals/modeldefinitions/nesignal.json +++ b/src/main/resources/assets/opensignals/modeldefinitions/nesignal.json @@ -336,6 +336,15 @@ } }, "y": 2.0 + }, + { + "blockstate": "with(NETYPE.TRAIN_LENGTH)", + "extentions": { + "arrow.json": { + "ARROW": "1" + } + }, + "y": 1.0 } ], "y": 0 @@ -349,6 +358,14 @@ "NE5_ADDITION": "2" } } + }, + { + "blockstate": "with(NETYPE.TRAIN_LENGTH)", + "extentions": { + "ne5_addition.json": { + "NE5_ADDITION": "2" + } + } } ], "y": 0 diff --git a/src/main/resources/assets/opensignals/modeldefinitions/shlight.json b/src/main/resources/assets/opensignals/modeldefinitions/shlight.json index b4685302e..835bf878f 100644 --- a/src/main/resources/assets/opensignals/modeldefinitions/shlight.json +++ b/src/main/resources/assets/opensignals/modeldefinitions/shlight.json @@ -25,7 +25,7 @@ { "blockstate": "with(sh_light_bottom.STATUS_LIGHT) && hasandisnot(sh_high)", "retexture": { - "lamp_whitenorth": "lamp_white" + "lamp_white2north": "lamp_white" } }, { @@ -50,7 +50,7 @@ { "blockstate": "with(sh_light_bottom.STATUS_LIGHT) && hasandis(sh_high)", "retexture": { - "lamp_whitenorth": "lamp_white" + "lamp_white2north": "lamp_white" }, "y": 2 } diff --git a/src/main/resources/assets/opensignals/modeldefinitions/wnsignal.json b/src/main/resources/assets/opensignals/modeldefinitions/wnsignal.json index c0fd325e3..658f6e7b5 100644 --- a/src/main/resources/assets/opensignals/modeldefinitions/wnsignal.json +++ b/src/main/resources/assets/opensignals/modeldefinitions/wnsignal.json @@ -39,33 +39,45 @@ { "blockstate":"hasandis(WNTYPE) && with(WNCROSS.WN3)", "retexture":{ - "lamp_1": "lamp_white", - "lamp_3": "lamp_white", - "lamp_5": "lamp_white" + "lamp_1_north": "lamp_white", + "lamp_3_north": "lamp_white", + "lamp_5_north": "lamp_white", + "lamp_1_south": "lamp_white", + "lamp_2_south": "lamp_white", + "lamp_4_south": "lamp_white" } }, { "blockstate":"hasandis(WNTYPE) && with(WNCROSS.WN4)", "retexture":{ - "lamp_1": "lamp_white", - "lamp_2": "lamp_white", - "lamp_4": "lamp_white" + "lamp_1_north": "lamp_white", + "lamp_2_north": "lamp_white", + "lamp_4_north": "lamp_white", + "lamp_1_south": "lamp_white", + "lamp_3_south": "lamp_white", + "lamp_5_south": "lamp_white" } }, { "blockstate":"hasandis(WNTYPE) && with(WNCROSS.WN5)", "retexture":{ - "lamp_1": "lamp_white", - "lamp_3": "lamp_white", - "lamp_4": "lamp_white" + "lamp_1_north": "lamp_white", + "lamp_3_north": "lamp_white", + "lamp_4_north": "lamp_white", + "lamp_1_south": "lamp_white", + "lamp_3_south": "lamp_white", + "lamp_4_south": "lamp_white" } }, { "blockstate":"hasandis(WNTYPE) && with(WNCROSS.WN6)", "retexture":{ - "lamp_1": "lamp_white", - "lamp_2": "lamp_white", - "lamp_5": "lamp_white" + "lamp_1_north": "lamp_white", + "lamp_2_north": "lamp_white", + "lamp_5_north": "lamp_white", + "lamp_1_south": "lamp_white", + "lamp_2_south": "lamp_white", + "lamp_5_south": "lamp_white" } }, { diff --git a/src/main/resources/assets/opensignals/models/block/wn/wn3_6.json b/src/main/resources/assets/opensignals/models/block/wn/wn3_6.json index 09256cb05..2b76f74e4 100644 --- a/src/main/resources/assets/opensignals/models/block/wn/wn3_6.json +++ b/src/main/resources/assets/opensignals/models/block/wn/wn3_6.json @@ -1 +1,539 @@ -{"credit": "Made with Blockbench by Mc_Jeronimo", "texture_size": [32, 32], "textures": {"0": "opensignals:blocks/default/shield_gray", "1": "opensignals:blocks/default/shield_black", "particle": "opensignals:blocks/default/shield_black", "lamp_1": "opensignals:blocks/lamps/lamp_dark", "lamp_2": "opensignals:blocks/lamps/lamp_dark", "lamp_3": "opensignals:blocks/lamps/lamp_dark", "lamp_4": "opensignals:blocks/lamps/lamp_dark", "lamp_5": "opensignals:blocks/lamps/lamp_dark"}, "elements": [{"from": [4, 4, 6], "to": [12, 12, 10], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 4, 4], "texture": "#1"}, "east": {"uv": [0, 0, 2, 4], "texture": "#1"}, "south": {"uv": [0, 0, 4, 4], "texture": "#1"}, "west": {"uv": [0, 0, 2, 4], "texture": "#1"}, "up": {"uv": [0, 0, 4, 2], "texture": "#1"}, "down": {"uv": [0, 0, 4, 2], "texture": "#1"}}}, {"from": [7, 0, 7], "to": [9, 4, 9], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 1, 1], "texture": "#0"}, "east": {"uv": [0, 0, 1, 1], "texture": "#0"}, "south": {"uv": [0, 0, 1, 1], "texture": "#0"}, "west": {"uv": [0, 0, 1, 1], "texture": "#0"}}}, {"from": [6.5, 8, 5], "to": [7, 9, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [9, 8, 5], "to": [9.5, 9, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [7, 9, 5], "to": [9, 9.5, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [6.5, 8, 10], "to": [7, 9, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [9, 8, 10], "to": [9.5, 9, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [7, 9, 10], "to": [9, 9.5, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [4.5, 6, 5], "to": [5, 7, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [7, 6, 5], "to": [7.5, 7, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [5, 7, 5], "to": [7, 7.5, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [4.5, 6, 10], "to": [5, 7, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [7, 6, 10], "to": [7.5, 7, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [5, 7, 10], "to": [7, 7.5, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [9, 7, 5], "to": [11, 7.5, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [11, 6, 5], "to": [11.5, 7, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [8.5, 6, 5], "to": [9, 7, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [9, 7, 10], "to": [11, 7.5, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [11, 6, 10], "to": [11.5, 7, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [8.5, 6, 10], "to": [9, 7, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"name": "lamp_1", "from": [7, 7, 5.9], "to": [9, 9, 5.9], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [1, 1, 3, 3], "texture": "#lamp_1"}}}, {"name": "lamp_2", "from": [9, 5, 5.9], "to": [11, 7, 5.9], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [1, 1, 3, 3], "texture": "#lamp_2"}}}, {"name": "lamp_3", "from": [5, 5, 5.9], "to": [7, 7, 5.9], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [1, 1, 3, 3], "texture": "#lamp_3"}}}, {"name": "lamp_1", "from": [7, 7, 10.1], "to": [9, 9, 10.1], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"south": {"uv": [1, 1, 3, 3], "texture": "#lamp_1"}}}, {"name": "lamp_2", "from": [9, 5, 10.1], "to": [11, 7, 10.1], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"south": {"uv": [1, 1, 3, 3], "texture": "#lamp_2"}}}, {"name": "lamp_3", "from": [5, 5, 10.1], "to": [7, 7, 10.1], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"south": {"uv": [1, 1, 3, 3], "texture": "#lamp_3"}}}, {"name": "lamp_4", "from": [5, 9, 10.1], "to": [7, 11, 10.1], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"south": {"uv": [1, 1, 3, 3], "texture": "#lamp_4"}}}, {"name": "lamp_4", "from": [5, 9, 5.9], "to": [7, 11, 5.9], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [1, 1, 3, 3], "texture": "#lamp_4"}}}, {"name": "lamp_5", "from": [9, 9, 10.1], "to": [11, 11, 10.1], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"south": {"uv": [1, 1, 3, 3], "texture": "#lamp_5"}}}, {"name": "lamp_5", "from": [9, 9, 5.9], "to": [11, 11, 5.9], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [1, 1, 3, 3], "texture": "#lamp_5"}}}, {"from": [9, 11, 5], "to": [11, 11.5, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [11, 10, 5], "to": [11.5, 11, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [8.5, 10, 5], "to": [9, 11, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [9, 11, 10], "to": [11, 11.5, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [11, 10, 10], "to": [11.5, 11, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [8.5, 10, 10], "to": [9, 11, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [5, 11, 5], "to": [7, 11.5, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [7, 10, 5], "to": [7.5, 11, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [4.5, 10, 5], "to": [5, 11, 6], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [5, 11, 10], "to": [7, 11.5, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"}}}, {"from": [7, 10, 10], "to": [7.5, 11, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}, {"from": [4.5, 10, 10], "to": [5, 11, 11], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": {"east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}}}], "groups": [{"name": "body", "origin": [11, 16, 13], "color": 0, "children": [0, 1]}, {"name": "hoods1", "origin": [8, 8, 8], "color": 0, "children": [2, 3, 4, 5, 6, 7]}, {"name": "hoods2", "origin": [8, 8, 8], "color": 0, "children": [8, 9, 10, 11, 12, 13]}, {"name": "hoods3", "origin": [8, 8, 8], "color": 0, "children": [14, 15, 16, 17, 18, 19]}, {"name": "lamps", "origin": [11, 16, 13], "color": 0, "children": [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]}, {"name": "hoods3", "origin": [8, 8, 8], "color": 0, "children": [30, 31, 32, 33, 34, 35]}, {"name": "hoods3", "origin": [8, 8, 8], "color": 0, "children": [36, 37, 38, 39, 40, 41]}]} \ No newline at end of file +{ + "credit": "Made with Blockbench by Mc_Jeronimo", + "texture_size": [32, 32], + "textures": { + "0": "opensignals:blocks/default/shield_gray", + "1": "opensignals:blocks/default/shield_black", + "particle": "opensignals:blocks/default/shield_black", + "lamp_1_north": "opensignals:blocks/lamps/lamp_dark", + "lamp_2_north": "opensignals:blocks/lamps/lamp_dark", + "lamp_3_north": "opensignals:blocks/lamps/lamp_dark", + "lamp_4_north": "opensignals:blocks/lamps/lamp_dark", + "lamp_5_north": "opensignals:blocks/lamps/lamp_dark", + "lamp_1_south": "opensignals:blocks/lamps/lamp_dark", + "lamp_2_south": "opensignals:blocks/lamps/lamp_dark", + "lamp_3_south": "opensignals:blocks/lamps/lamp_dark", + "lamp_4_south": "opensignals:blocks/lamps/lamp_dark", + "lamp_5_south": "opensignals:blocks/lamps/lamp_dark" + }, + "elements": [ + { + "from": [4, 4, 6], + "to": [12, 12, 10], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 4], "texture": "#1"}, + "east": {"uv": [0, 0, 2, 4], "texture": "#1"}, + "south": {"uv": [0, 0, 4, 4], "texture": "#1"}, + "west": {"uv": [0, 0, 2, 4], "texture": "#1"}, + "up": {"uv": [0, 0, 4, 2], "texture": "#1"}, + "down": {"uv": [0, 0, 4, 2], "texture": "#1"} + } + }, + { + "from": [7, 0, 7], + "to": [9, 4, 9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "texture": "#0"} + } + }, + { + "from": [6.5, 8, 5], + "to": [7, 9, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [9, 8, 5], + "to": [9.5, 9, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [7, 9, 5], + "to": [9, 9.5, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [6.5, 8, 10], + "to": [7, 9, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [9, 8, 10], + "to": [9.5, 9, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [7, 9, 10], + "to": [9, 9.5, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [4.5, 6, 5], + "to": [5, 7, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [7, 6, 5], + "to": [7.5, 7, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [5, 7, 5], + "to": [7, 7.5, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [4.5, 6, 10], + "to": [5, 7, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [7, 6, 10], + "to": [7.5, 7, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [5, 7, 10], + "to": [7, 7.5, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [9, 7, 5], + "to": [11, 7.5, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [11, 6, 5], + "to": [11.5, 7, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [8.5, 6, 5], + "to": [9, 7, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [9, 7, 10], + "to": [11, 7.5, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [11, 6, 10], + "to": [11.5, 7, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [8.5, 6, 10], + "to": [9, 7, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "name": "lamp_1", + "from": [7, 7, 5.9], + "to": [9, 9, 5.9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 3, 3], "texture": "#lamp_1_north"} + } + }, + { + "name": "lamp_3", + "from": [9, 5, 5.9], + "to": [11, 7, 5.9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 3, 3], "texture": "#lamp_3_north"} + } + }, + { + "name": "lamp_2", + "from": [5, 5, 5.9], + "to": [7, 7, 5.9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 3, 3], "texture": "#lamp_2_north"} + } + }, + { + "name": "lamp_1", + "from": [7, 7, 10.1], + "to": [9, 9, 10.1], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "south": {"uv": [1, 1, 3, 3], "texture": "#lamp_1_south"} + } + }, + { + "name": "lamp_3", + "from": [9, 5, 10.1], + "to": [11, 7, 10.1], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "south": {"uv": [1, 1, 3, 3], "texture": "#lamp_3_south"} + } + }, + { + "name": "lamp_2", + "from": [5, 5, 10.1], + "to": [7, 7, 10.1], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "south": {"uv": [1, 1, 3, 3], "texture": "#lamp_2_south"} + } + }, + { + "name": "lamp_5", + "from": [5, 9, 10.1], + "to": [7, 11, 10.1], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "south": {"uv": [1, 1, 3, 3], "texture": "#lamp_5_south"} + } + }, + { + "name": "lamp_5", + "from": [5, 9, 5.9], + "to": [7, 11, 5.9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 3, 3], "texture": "#lamp_5_north"} + } + }, + { + "name": "lamp_4", + "from": [9, 9, 10.1], + "to": [11, 11, 10.1], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "south": {"uv": [1, 1, 3, 3], "texture": "#lamp_4_south"} + } + }, + { + "name": "lamp_4", + "from": [9, 9, 5.9], + "to": [11, 11, 5.9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 3, 3], "texture": "#lamp_4_north"} + } + }, + { + "from": [9, 11, 5], + "to": [11, 11.5, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [11, 10, 5], + "to": [11.5, 11, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [8.5, 10, 5], + "to": [9, 11, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [9, 11, 10], + "to": [11, 11.5, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [11, 10, 10], + "to": [11.5, 11, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [8.5, 10, 10], + "to": [9, 11, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [5, 11, 5], + "to": [7, 11.5, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [7, 10, 5], + "to": [7.5, 11, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [4.5, 10, 5], + "to": [5, 11, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [5, 11, 10], + "to": [7, 11.5, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "south": {"uv": [0, 0, 1, 0.25], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.25], "texture": "#1"}, + "up": {"uv": [0, 0, 1, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 1, 0.5], "texture": "#1"} + } + }, + { + "from": [7, 10, 10], + "to": [7.5, 11, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + }, + { + "from": [4.5, 10, 10], + "to": [5, 11, 11], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "east": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "south": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "west": {"uv": [0, 0, 0.5, 0.5], "texture": "#1"}, + "up": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"}, + "down": {"uv": [0, 0, 0.25, 0.5], "texture": "#1"} + } + } + ], + "groups": [ + { + "name": "body", + "origin": [11, 16, 13], + "color": 0, + "children": [0, 1] + }, + { + "name": "hoods1", + "origin": [8, 8, 8], + "color": 0, + "children": [2, 3, 4, 5, 6, 7] + }, + { + "name": "hoods2", + "origin": [8, 8, 8], + "color": 0, + "children": [8, 9, 10, 11, 12, 13] + }, + { + "name": "hoods3", + "origin": [8, 8, 8], + "color": 0, + "children": [14, 15, 16, 17, 18, 19] + }, + { + "name": "lamps", + "origin": [11, 16, 13], + "color": 0, + "children": [20, 21, 22, 23, 24, 25, 26, 27, 28, 29] + }, + { + "name": "hoods3", + "origin": [8, 8, 8], + "color": 0, + "children": [30, 31, 32, 33, 34, 35] + }, + { + "name": "hoods3", + "origin": [8, 8, 8], + "color": 0, + "children": [36, 37, 38, 39, 40, 41] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalconfigs/change/hv_hv_config.json b/src/main/resources/assets/opensignals/signalconfigs/change/hv_hv_config.json index 4cea6543d..59a4dc4e4 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/change/hv_hv_config.json +++ b/src/main/resources/assets/opensignals/signalconfigs/change/hv_hv_config.json @@ -7,6 +7,9 @@ "slow": "config(stopsignal.HP2) || config(hphome.HP2)" }, "values": { + + "map(drive)": ["distantsignal.VR1"], + "(config(zs3.Z1) || config(zs3plate.Z1))": ["zs3v.Z1"], "(config(zs3.Z2) || config(zs3plate.Z2))": ["zs3v.Z2"], "(config(zs3.Z3) || config(zs3plate.Z3))": ["zs3v.Z3"], @@ -24,7 +27,6 @@ "(config(zs3.Z15) || config(zs3plate.Z15))": ["zs3v.Z15"], "map(stop)": ["distantsignal.VR0", "zs3v.OFF"], - "map(drive)": ["distantsignal.VR1"], "map(slow)": ["distantsignal.VR2"], "signalRepeater(true)": ["vrlight.true"], diff --git a/src/main/resources/assets/opensignals/signalconfigs/change/hv_ks_config.json b/src/main/resources/assets/opensignals/signalconfigs/change/hv_ks_config.json index 36e38b66b..27d53e4ba 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/change/hv_ks_config.json +++ b/src/main/resources/assets/opensignals/signalconfigs/change/hv_ks_config.json @@ -7,6 +7,8 @@ }, "values": { + "map(drive)": ["distantsignal.VR1"], + "(config(zs3.Z1) || config(zs3plate.Z1))": ["zs3v.Z1", "distantsignal.VR2"], "(config(zs3.Z2) || config(zs3plate.Z2))": ["zs3v.Z2", "distantsignal.VR2"], "(config(zs3.Z3) || config(zs3plate.Z3))": ["zs3v.Z3", "distantsignal.VR2"], @@ -24,7 +26,6 @@ "(config(zs3.Z15) || config(zs3plate.Z15))": ["zs3v.Z15", "distantsignal.VR1"], "map(stop)": ["distantsignal.VR0", "zs3v.OFF"], - "map(drive)": ["distantsignal.VR1"], "signalRepeater(true)": ["vrlight.true"], "speed(<.1) || speed(>.15)": ["stopsignal.HP1", "hphome.HP1", "hpblock.HP1"], diff --git a/src/main/resources/assets/opensignals/signalconfigs/change/hv_sema.json b/src/main/resources/assets/opensignals/signalconfigs/change/hv_sema.json index 6c0d12655..6b392a7a3 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/change/hv_sema.json +++ b/src/main/resources/assets/opensignals/signalconfigs/change/hv_sema.json @@ -8,6 +8,8 @@ }, "values": { + "map(drive)": ["distantsignal.VR1"], + "(config(zs3.Z1) || config(zs3plate.Z1))": ["zs3v.Z1"], "(config(zs3.Z2) || config(zs3plate.Z2))": ["zs3v.Z2"], "(config(zs3.Z3) || config(zs3plate.Z3))": ["zs3v.Z3"], @@ -25,7 +27,6 @@ "(config(zs3.Z15) || config(zs3plate.Z15))": ["zs3v.Z15"], "map(stop)": ["distantsignal.VR0", "zs3v.OFF"], - "map(drive)": ["distantsignal.VR1"], "map(slow)": ["distantsignal.VR2"], "signalRepeater(true)": ["vrlight.true"], diff --git a/src/main/resources/assets/opensignals/signalconfigs/change/ks_hv_config.json b/src/main/resources/assets/opensignals/signalconfigs/change/ks_hv_config.json index bb6927d8e..248616a44 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/change/ks_hv_config.json +++ b/src/main/resources/assets/opensignals/signalconfigs/change/ks_hv_config.json @@ -26,6 +26,7 @@ "map(stop)": ["kombisignal.KS2", "kombisignal_main.KS1", "kombisignal_distant.KS2", "zs3v.OFF", "zs2v.OFF"], "map(stop) && signalRepeater(true)": ["kombisignal_distant.KS2_REPEAT"], "map(drive)": ["kombisignal.KS1", "kombisignal_main.KS1", "kombisignal_distant.KS1"], + "config(stopsignal.HP2) || config(hphome.HP2)" : ["kombisignal.KS1_BLINK", "kombisignal_main.KS1", "kombisignal_distant.KS1_BLINK", "zs3v.Z4"], "map(drive) && map(zs3)": ["kombisignal.KS1_BLINK", "kombisignal_main.KS1", "kombisignal_distant.KS1_BLINK"], "map(drive) && map(zs3) && signalRepeater(true)": ["kombisignal_distant.KS1_BLINK_REPEAT"], diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hl.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hl.json index d18721252..77fcf364d 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hl.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hl.json @@ -5,10 +5,16 @@ "mainlightsignal.HL_ZS1", "exitsignal.HL_ZS1", "blocksignal.HL_ZS1", - "blockexitsignal.HL_ZS1" + "blockexitsignal.HL_ZS1", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ], "ZS8": [ - "zs2.ZS8" + "zs2.ZS8", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ], "ZP9": [ "zs2.ZP9" @@ -16,14 +22,20 @@ "SH1": [ "mainlightsignal.HL_SHUNTING", "exitsignal.HL_SHUNTING", - "blockexitsignal.HL_SHUNTING" + "blockexitsignal.HL_SHUNTING", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ], "STATUSLIGHT": [ "mainlightsignal.HL_STATUS_LIGHT", "mainlightsignal_distant.HL_STATUS_LIGHT", "exitsignal.HL_STATUS_LIGHT", "blocksignal.HL_STATUS_LIGHT", - "blockexitsignal.HL_STATUS_LIGHT" + "blockexitsignal.HL_STATUS_LIGHT", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ] } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hlbridge.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hlbridge.json index aacd9b8e0..5f3b41996 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hlbridge.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hlbridge.json @@ -5,10 +5,16 @@ "mainlightsignal.HL_ZS1", "exitsignal.HL_ZS1", "blocksignal.HL_ZS1", - "blockexitsignal.HL_ZS1" + "blockexitsignal.HL_ZS1", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ], "ZS8": [ - "zs2.ZS8" + "zs2.ZS8", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ], "ZP9": [ "zs2.ZP9" @@ -16,14 +22,20 @@ "SH1": [ "mainlightsignal.HL_SHUNTING", "exitsignal.HL_SHUNTING", - "blockexitsignal.HL_SHUNTING" + "blockexitsignal.HL_SHUNTING", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ], "STATUSLIGHT": [ "mainlightsignal.HL_STATUS_LIGHT", "mainlightsignal_distant.HL_STATUS_LIGHT", "exitsignal.HL_STATUS_LIGHT", "blocksignal.HL_STATUS_LIGHT", - "blockexitsignal.HL_STATUS_LIGHT" + "blockexitsignal.HL_STATUS_LIGHT", + "mainlightsignallightbar.OFF", + "zs2.OFF", + "zs2v.OFF" ] } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hv.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hv.json index cac4a1783..9479fd0fd 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hv.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hv.json @@ -2,21 +2,55 @@ "currentSignal": "hvsignal", "allStates": { "ZS1": [ - "zs1.TRUE" + "stopsignal.HP0", + "hphome.HP0", + "hpblock.HP0", + "zs1.TRUE", + "zs7.FALSE", + "identifier.FALSE", + "zs3.OFF", + "zs3v.OFF", + "distantsignal.VR0" ], "ZS7": [ - "zs7.TRUE" + "stopsignal.HP0", + "hphome.HP0", + "hpblock.HP0", + "zs1.FALSE", + "zs7.TRUE", + "identifier.FALSE", + "zs3.OFF", + "zs3v.OFF", + "distantsignal.OFF" ], "ZS8": [ - "zs3.ZS8" + "stopsignal.HP0", + "hphome.HP0", + "hpblock.HP0", + "zs1.FALSE", + "zs7.FALSE", + "identifier.FALSE", + "zs3.ZS8", + "zs3v.OFF", + "distantsignal.VR0" ], "ZP9": [ "zs3.ZP9" ], "SH1": [ - "stopsignal.SHUNTING" + "stopsignal.SHUNTING", + "zs1.FALSE", + "zs7.FALSE", + "identifier.FALSE", + "zs3.OFF", + "zs3v.OFF", + "distantsignal.OFF" ], "STATUSLIGHT": [ + "zs1.FALSE", + "zs7.FALSE", + "zs3.OFF", + "zs3v.OFF", "stopsignal.OFF", "hphome.OFF", "hpblock.OFF", diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hvbridge.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hvbridge.json index 14446ad3a..ee79e0143 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hvbridge.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/hvbridge.json @@ -2,21 +2,55 @@ "currentSignal": "hvsignalbridge", "allStates": { "ZS1": [ - "zs1.TRUE" + "stopsignal.HP0", + "hphome.HP0", + "hpblock.HP0", + "zs1.TRUE", + "zs7.FALSE", + "identifier.FALSE", + "zs3.OFF", + "zs3v.OFF", + "distantsignal.VR0" ], "ZS7": [ - "zs7.TRUE" + "stopsignal.HP0", + "hphome.HP0", + "hpblock.HP0", + "zs1.FALSE", + "zs7.TRUE", + "identifier.FALSE", + "zs3.OFF", + "zs3v.OFF", + "distantsignal.OFF" ], "ZS8": [ - "zs3.ZS8" + "stopsignal.HP0", + "hphome.HP0", + "hpblock.HP0", + "zs1.FALSE", + "zs7.FALSE", + "identifier.FALSE", + "zs3.ZS8", + "zs3v.OFF", + "distantsignal.VR0" ], "ZP9": [ "zs3.ZP9" ], "SH1": [ - "stopsignal.SHUNTING" + "stopsignal.SHUNTING", + "zs1.FALSE", + "zs7.FALSE", + "identifier.FALSE", + "zs3.OFF", + "zs3v.OFF", + "distantsignal.OFF" ], "STATUSLIGHT": [ + "zs1.FALSE", + "zs7.FALSE", + "zs3.OFF", + "zs3v.OFF", "stopsignal.OFF", "hphome.OFF", "hpblock.OFF", diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ks.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ks.json index 74437e10f..8db396273 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ks.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ks.json @@ -3,26 +3,48 @@ "allStates": { "ZS1": [ "kombisignal.KS_ZS1", - "kombisignal_main.KS_ZS1" + "kombisignal_main.KS_ZS1", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "ZS7": [ "kombisignal.KS_ZS7", - "kombisignal_main.KS_ZS7" + "kombisignal_main.KS_ZS7", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "ZS8": [ - "zs2.ZS8" + "kombisignal.HP0", + "kombisignal_main.HP0", + "zs2.ZS8", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "ZP9": [ "zs2.ZP9" ], "SH1": [ "kombisignal.KS_SHUNTING", - "kombisignal_main.KS_SHUNTING" + "kombisignal_main.KS_SHUNTING", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "STATUSLIGHT": [ "kombisignal.KS_STATUS_LIGHT", "kombisignal_main.KS_STATUS_LIGHT", - "kombisignal_distant.KS_STATUS_LIGHT" + "kombisignal_distant.KS_STATUS_LIGHT", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ] } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ksbridge.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ksbridge.json index 85d5664c0..5a693d36f 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ksbridge.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/ksbridge.json @@ -3,26 +3,48 @@ "allStates": { "ZS1": [ "kombisignal.KS_ZS1", - "kombisignal_main.KS_ZS1" + "kombisignal_main.KS_ZS1", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "ZS7": [ "kombisignal.KS_ZS7", - "kombisignal_main.KS_ZS7" + "kombisignal_main.KS_ZS7", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "ZS8": [ - "zs2.ZS8" + "kombisignal.HP0", + "kombisignal_main.HP0", + "zs2.ZS8", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "ZP9": [ "zs2.ZP9" ], "SH1": [ "kombisignal.KS_SHUNTING", - "kombisignal_main.KS_SHUNTING" + "kombisignal_main.KS_SHUNTING", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ], "STATUSLIGHT": [ "kombisignal.KS_STATUS_LIGHT", "kombisignal_main.KS_STATUS_LIGHT", - "kombisignal_distant.KS_STATUS_LIGHT" + "kombisignal_distant.KS_STATUS_LIGHT", + "zs3.OFF", + "zs2.OFF", + "zs3v.OFF", + "zs2v.OFF" ] } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphore.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphore.json index 6be81dda2..a02885b8c 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphore.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphore.json @@ -2,19 +2,39 @@ "currentSignal": "semaphoresignal", "allStates": { "ZS1": [ + "wing1.FALSE", + "wing2.FALSE", + "zs3.OFF", + "ra12.FALSE", + "zs7.FALSE", "zs1.TRUE" ], "ZS7": [ - "zs7.TRUE" + "wing1.FALSE", + "wing2.FALSE", + "zs3.OFF", + "ra12.FALSE", + "zs7.TRUE", + "zs1.FALSE" ], "ZS8": [ - "zs3.ZS8" + "wing1.FALSE", + "wing2.FALSE", + "zs3.ZS8", + "ra12.FALSE", + "zs7.FALSE", + "zs1.FALSE" ], "ZP9": [ "zs3.ZP9" ], "SH1": [ - "ra12.TRUE" + "wing1.FALSE", + "wing2.FALSE", + "zs3.OFF", + "ra12.TRUE", + "zs7.FALSE", + "zs1.FALSE" ] } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphorebridge.json b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphorebridge.json index a57a988b1..f6d9d3231 100644 --- a/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphorebridge.json +++ b/src/main/resources/assets/opensignals/signalconfigs/subsidiary/semaphorebridge.json @@ -2,19 +2,39 @@ "currentSignal": "semaphoresignalbridge", "allStates": { "ZS1": [ + "wing1.FALSE", + "wing2.FALSE", + "zs3.OFF", + "ra12.FALSE", + "zs7.FALSE", "zs1.TRUE" ], "ZS7": [ - "zs7.TRUE" + "wing1.FALSE", + "wing2.FALSE", + "zs3.OFF", + "ra12.FALSE", + "zs7.TRUE", + "zs1.FALSE" ], "ZS8": [ - "zs3.ZS8" + "wing1.FALSE", + "wing2.FALSE", + "zs3.ZS8", + "ra12.FALSE", + "zs7.FALSE", + "zs1.FALSE" ], "ZP9": [ "zs3.ZP9" ], "SH1": [ - "ra12.TRUE" + "wing1.FALSE", + "wing2.FALSE", + "zs3.OFF", + "ra12.TRUE", + "zs7.FALSE", + "zs1.FALSE" ] } } \ No newline at end of file diff --git a/src/main/resources/assets/opensignals/signalsystems/buesignal.json b/src/main/resources/assets/opensignals/signalsystems/buesignal.json index 26eb58d7b..c195a7bec 100644 --- a/src/main/resources/assets/opensignals/signalsystems/buesignal.json +++ b/src/main/resources/assets/opensignals/signalsystems/buesignal.json @@ -6,7 +6,7 @@ "signalHeights": { "config(BUETYPE.BUE4) || config(BUETYPE.BUE5) || config(BUETYPE.HET) || config(BUETYPE.AUTO_HET) || config(BUETYPE.ET) || config(BUETYPE.AUTO_ET) || config(BUETYPE.BUE_DISTANT) || config(BUETYPE.BUE_IDENTIFICATION)": 1 }, - "customNameRenderHeight": 1.5, + "customNameRenderHeight": 1.55, "offsetY": -5, "renderHeights": { "!(config(BUETYPE.BUE_IDENTIFICATION) || config(BUETYPE.BUE_DISTANT)) ": -1 diff --git a/src/main/resources/assets/opensignals/signalsystems/nesignal.json b/src/main/resources/assets/opensignals/signalsystems/nesignal.json index 1f4734095..d0ab495ea 100644 --- a/src/main/resources/assets/opensignals/signalsystems/nesignal.json +++ b/src/main/resources/assets/opensignals/signalsystems/nesignal.json @@ -13,14 +13,16 @@ "config(NETYPE.NE1)": 1, "config(NETYPE.NE5)": 1, "config(NETYPE.NE6)": 1, - "config(NETYPE.SO106)": 1 + "config(NETYPE.SO106)": 1, + "config(NETYPE.TRAIN_LENGTH)": 0 }, "customNameRenderHeight": 1.52, "offsetY": -7, "offsetX": -15, "signWidth": 50, "renderHeights": { - "!config(NETYPE.NE1)": -1 + "!config(NETYPE.NE1)": -1, + "config(NETYPE.TRAIN_LENGTH)": 0.9 } }, "seProperties": [