diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java index 8a44638f4..42197a8cc 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -141,8 +141,6 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { protected RotationComponent rotation; protected boolean placeAir = false; - private static final Set VALID_MATERIAL_INSTANCE_NAMES = ImmutableSet.of("*", "up", "down", "north", "south", "west", "east"); - private void validateBox(BoxComponent box) { if (box == null) { return; @@ -189,9 +187,6 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { @Override public Builder materialInstance(@NotNull String name, @NotNull MaterialInstance materialInstance) { - if (!VALID_MATERIAL_INSTANCE_NAMES.contains(name)) { - throw new IllegalArgumentException("Material instance name must be one of " + VALID_MATERIAL_INSTANCE_NAMES); - } this.materialInstances.put(name, materialInstance); return this; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java index de97d38d4..ba0fdf17d 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockData.java @@ -139,7 +139,7 @@ public class GeyserCustomBlockData implements CustomBlockData { @Override public Builder booleanProperty(@NonNull String propertyName) { - this.properties.put(propertyName, new GeyserCustomBlockProperty<>(propertyName, List.of(false, true), PropertyType.BOOLEAN)); + this.properties.put(propertyName, new GeyserCustomBlockProperty<>(propertyName, List.of((byte) 0, (byte) 1), PropertyType.BOOLEAN)); return this; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java index 5e195962a..576bd9743 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockState.java @@ -70,7 +70,7 @@ public class GeyserCustomBlockState implements CustomBlockState { @Override public Builder booleanProperty(@NonNull String propertyName, boolean value) { - properties.put(propertyName, value); + properties.put(propertyName, value ? (byte) 1 : (byte) 0); return this; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index ba661af58..cb5fb1c64 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -42,6 +42,7 @@ import org.geysermc.geyser.level.block.GeyserCustomBlockComponents.CustomBlockCo import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.mappings.util.BlockPropertyTypeMaps; +import org.geysermc.geyser.util.BlockUtils; import java.nio.file.Path; import java.util.ArrayList; @@ -169,7 +170,7 @@ public class MappingsReader_v1 extends MappingsReader { @Override public CustomBlockMapping readBlockMappingEntry(String identifier, JsonNode node) throws InvalidCustomMappingsFileException { if (node == null || !node.isObject()) { - throw new InvalidCustomMappingsFileException("Invalid block mappings entry:" + node.toString()); + throw new InvalidCustomMappingsFileException("Invalid block mappings entry:" + node); } String name = node.get("name").asText(); @@ -177,41 +178,49 @@ public class MappingsReader_v1 extends MappingsReader { throw new InvalidCustomMappingsFileException("A block entry has no name"); } + boolean onlyOverrideStates = node.has("only_override_states") && node.get("only_override_states").asBoolean(); JsonNode stateOverrides = node.get("state_overrides"); + + if (onlyOverrideStates && (stateOverrides == null || !stateOverrides.isObject())) { + throw new InvalidCustomMappingsFileException("A block entry has only_override_states set to true but no state_overrides"); + } + List stateKeys = new ArrayList<>(); - Iterator> fields = stateOverrides.fields(); - while (fields.hasNext()) { - stateKeys.add(identifier + fields.next().getKey()); + + if (stateOverrides != null && stateOverrides.isObject()) { + Iterator> fields = stateOverrides.fields(); + while (fields.hasNext()) { + stateKeys.add(identifier + fields.next().getKey()); + } } List defaultStates = List.copyOf(BlockRegistries.JAVA_IDENTIFIERS.get().keySet()) .stream() .filter(s -> s.startsWith(identifier + "[")) .collect(Collectors.toList()); + if (defaultStates.isEmpty()) defaultStates.add(""); CustomBlockDataBuilder customBlockDataBuilder = new CustomBlockDataBuilder(); - - customBlockDataBuilder - .name(name) - .components(createCustomBlockComponents(node)) - .permutations(createCustomBlockPermutations(stateOverrides)) + customBlockDataBuilder.name(name) + .components(createCustomBlockComponents(node, defaultStates.get(0), identifier)) + .permutations(createCustomBlockPermutations(stateOverrides, identifier)) .booleanProperty("geyser_custom:default"); - BlockPropertyTypeMaps blockPropertyTypeMaps = createBlockPropertyTypeMaps(defaultStates); + BlockPropertyTypeMaps blockPropertyTypeMaps = createBlockPropertyTypeMaps(onlyOverrideStates ? stateKeys : defaultStates); blockPropertyTypeMaps.stringValuesMap().forEach((key, value) -> customBlockDataBuilder.stringProperty(key, new ArrayList(value))); blockPropertyTypeMaps.intValuesMap().forEach((key, value) -> customBlockDataBuilder.intProperty(key, new ArrayList(value))); blockPropertyTypeMaps.booleanValuesSet().forEach((value) -> customBlockDataBuilder.booleanProperty(value)); CustomBlockData customBlockData = customBlockDataBuilder.build(); - Map states = createCustomBlockStatesMap(identifier, stateKeys, defaultStates, customBlockData, + Map states = createCustomBlockStatesMap(identifier, stateKeys, defaultStates, onlyOverrideStates, customBlockData, blockPropertyTypeMaps.stateKeyStrings(), blockPropertyTypeMaps.stateKeyInts(), blockPropertyTypeMaps.stateKeyBools()); return new CustomBlockMapping(customBlockData, states); } - private List createCustomBlockPermutations(JsonNode node) { + private List createCustomBlockPermutations(JsonNode node, String identifier) { List permutations = new ArrayList<>(); if (node != null && node.isObject()) { @@ -220,62 +229,49 @@ public class MappingsReader_v1 extends MappingsReader { JsonNode value = entry.getValue(); if (value.isObject()) { value.forEach(data -> { - permutations.add(new CustomBlockPermutation(createCustomBlockComponents(data), createCustomBlockPropertyQuery(key))); + permutations.add(new CustomBlockPermutation(createCustomBlockComponents(data, key, identifier), createCustomBlockPropertyQuery(key))); }); } }); } - permutations.add(new CustomBlockPermutation( - new GeyserCustomBlockComponents.CustomBlockComponentsBuilder().build(), - "q.block_property('geyser_custom:default') == 1")); + permutations.add(new CustomBlockPermutation(new GeyserCustomBlockComponents.CustomBlockComponentsBuilder().build(), "q.block_property('geyser_custom:default') == 1")); return permutations; } - private Map createCustomBlockStatesMap( - String identifier, - List stateKeys, - List defaultStates, - CustomBlockData customBlockData, - Map> stateKeyStrings, - Map> stateKeyInts, - Map> stateKeyBools) { + private Map createCustomBlockStatesMap(String identifier, List stateKeys,List defaultStates, boolean onlyOverrideStates, CustomBlockData customBlockData, + Map> stateKeyStrings, Map> stateKeyInts, Map> stateKeyBools) { Map states = new HashMap<>(); - defaultStates.removeAll(stateKeys); - - defaultStates.forEach(key -> { - CustomBlockState.Builder builder = customBlockData.blockStateBuilder(); - builder.booleanProperty("geyser_custom:default", true); - - stateKeyStrings.getOrDefault(key, Collections.emptyMap()).forEach((property, stringValue) -> builder.stringProperty(property, stringValue)); - stateKeyInts.getOrDefault(key, Collections.emptyMap()).forEach((property, intValue) -> builder.intProperty(property, intValue)); - stateKeyBools.getOrDefault(key, Collections.emptyMap()).forEach((property, boolValue) -> builder.booleanProperty(property, boolValue)); - - CustomBlockState blockState = builder.build(); - - states.put(key, blockState); - }); - - stateKeys.forEach((key) -> { - CustomBlockState.Builder builder = customBlockData.blockStateBuilder(); - builder.booleanProperty("geyser_custom:default", false); - - stateKeyStrings.getOrDefault(key, Collections.emptyMap()).forEach((property, stringValue) -> builder.stringProperty(property, stringValue)); - stateKeyInts.getOrDefault(key, Collections.emptyMap()).forEach((property, intValue) -> builder.intProperty(property, intValue)); - stateKeyBools.getOrDefault(key, Collections.emptyMap()).forEach((property, boolValue) -> builder.booleanProperty(property, boolValue)); - - CustomBlockState blockState = builder.build(); - - states.put(key, blockState); - }); + if (!onlyOverrideStates) { + defaultStates.removeAll(stateKeys); + createCustomBlockStates(defaultStates, true, customBlockData, stateKeyStrings, stateKeyInts, stateKeyBools, states); + } + createCustomBlockStates(stateKeys, false, customBlockData, stateKeyStrings, stateKeyInts, stateKeyBools, states); return states; } - private BlockPropertyTypeMaps createBlockPropertyTypeMaps(List stateKeys) { + private void createCustomBlockStates(List stateKeys, boolean defaultState, CustomBlockData customBlockData, + Map> stateKeyStrings, Map> stateKeyInts, + Map> stateKeyBools, Map states) { + stateKeys.forEach((key) -> { + CustomBlockState.Builder builder = customBlockData.blockStateBuilder(); + builder.booleanProperty("geyser_custom:default", defaultState); + + stateKeyStrings.getOrDefault(key, Collections.emptyMap()).forEach((property, stringValue) -> builder.stringProperty(property, stringValue)); + stateKeyInts.getOrDefault(key, Collections.emptyMap()).forEach((property, intValue) -> builder.intProperty(property, intValue)); + stateKeyBools.getOrDefault(key, Collections.emptyMap()).forEach((property, boolValue) -> builder.booleanProperty(property, boolValue)); + + CustomBlockState blockState = builder.build(); + + states.put(key, blockState); + }); + } + + private BlockPropertyTypeMaps createBlockPropertyTypeMaps(List usedStateKeys) { Map> stringValuesMap = new HashMap<>(); Map> stateKeyStrings = new HashMap<>(); @@ -285,13 +281,8 @@ public class MappingsReader_v1 extends MappingsReader { Set booleanValuesSet = new HashSet<>(); Map> stateKeyBools = new HashMap<>(); - for (String state : stateKeys) { - int openBracketIndex = state.indexOf("["); - int closeBracketIndex = state.indexOf("]"); - - String cleanStates = state.substring(openBracketIndex + 1, closeBracketIndex); - - String[] pairs = cleanStates.split("\\s*,\\s*"); + for (String state : usedStateKeys) { + String[] pairs = splitStateString(state); for (String pair : pairs) { String[] parts = pair.split("="); @@ -329,7 +320,11 @@ public class MappingsReader_v1 extends MappingsReader { return new BlockPropertyTypeMaps(stringValuesMap, stateKeyStrings, intValuesMap, stateKeyInts, booleanValuesSet, stateKeyBools); } - private CustomBlockComponents createCustomBlockComponents(JsonNode node) { + private CustomBlockComponents createCustomBlockComponents(JsonNode node, String state, String identifier) { + String stateIdentifier = identifier + state; + int test = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(stateIdentifier, -1); + BlockUtils.getCollision(test); + CustomBlockComponentsBuilder builder = new CustomBlockComponentsBuilder(); builder .geometry("geometry.some.geometry"); @@ -354,8 +349,7 @@ public class MappingsReader_v1 extends MappingsReader { } private String createCustomBlockPropertyQuery(String state) { - String list = state.substring(1, state.length() - 1); - String[] conditions = list.split(","); + String[] conditions = splitStateString(state); String[] queries = new String[conditions.length]; for (int i = 0; i < conditions.length; i++) { @@ -376,4 +370,15 @@ public class MappingsReader_v1 extends MappingsReader { return String.format("q.block_property('geyser_custom:default') == 0 && %s", query); } + private String[] splitStateString(String state) { + int openBracketIndex = state.indexOf("["); + int closeBracketIndex = state.indexOf("]"); + + String cleanStates = state.substring(openBracketIndex + 1, closeBracketIndex); + + String[] pairs = cleanStates.split("\\s*,\\s*"); + + return pairs; + } + }