Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
e327f32
Refactor items
Creeperface01 Sep 10, 2020
eac549c
Commit current progress just to be able to continue at school
Creeperface01 Sep 13, 2020
e04850b
Finish base api
Creeperface01 Sep 18, 2020
d36b869
Merge branch 'bleeding' into item-refactor
Creeperface01 Sep 25, 2020
53bab3b
Rewrite more classes
Creeperface01 Sep 26, 2020
b24af7b
Add more serializers for wood types
Creeperface01 Sep 28, 2020
a4303d9
Update block hardness values
Creeperface01 Sep 30, 2020
79249e6
Update block attributes
Creeperface01 Oct 1, 2020
213fe2e
Update block attributes
Creeperface01 Oct 5, 2020
7903d9a
Update block tool tiers
Creeperface01 Oct 5, 2020
a0c0ca4
Update block attributes
Creeperface01 Oct 8, 2020
344e2bc
Initial work on API split
SupremeMortal Oct 10, 2020
a55709a
Implement all states correctly
Creeperface01 Oct 16, 2020
db66d77
Fix block states in generator configuration
Creeperface01 Oct 19, 2020
972e041
Merge remote-tracking branch 'origin/bleeding' into item-refactor
Creeperface01 Oct 19, 2020
0ff172a
Various bug fixes
Creeperface01 Oct 20, 2020
9aa3315
Add item constants
Creeperface01 Oct 21, 2020
3dcd015
Fix missing item meta serializer and id to type mappings
Creeperface01 Oct 25, 2020
fbdf4b4
Fix liquids a bit
Creeperface01 Oct 25, 2020
38a59b2
Fix creative items
Creeperface01 Oct 27, 2020
957a450
Send recipes
Creeperface01 Oct 28, 2020
64c2725
Merge remote-tracking branch 'origin/bleeding' into item-refactor
Creeperface01 Oct 28, 2020
7e7f1db
Merge remote-tracking branch 'origin/bleeding' into item-refactor
Creeperface01 Oct 29, 2020
9f7eb00
Fix incorrect instanceof checks
Creeperface01 Oct 30, 2020
0a7ea6c
Fix liquid behavior
Creeperface01 Oct 30, 2020
0136ebb
Merge remote-tracking branch 'origin/bleeding' into item-refactor
Creeperface01 Oct 30, 2020
1b175d9
Add default bounding boxes
Creeperface01 Nov 1, 2020
e587ac2
Merge remote-tracking branch 'origin/feature/api' into item-refactor
Creeperface01 Nov 6, 2020
3d708b3
Fix conflicts
Creeperface01 Nov 6, 2020
937afd2
Merge pull request #50 from CloudburstMC/item-refactor
SupremeMortal Nov 6, 2020
a5e17d9
Update protocol lib
Sleepybear Jan 3, 2021
d4fef57
Update ItemData arrays to lists
Sleepybear Jan 3, 2021
9e5dadb
Update palette dynamic generation
Sleepybear Jan 3, 2021
034ba36
remove debug
Sleepybear Jan 3, 2021
dbc65d2
Update BlockPaletteTest with new palette.
Sleepybear Jan 5, 2021
fdb7819
AIR is no longer runtime ID 0
Sleepybear Jan 6, 2021
a890e74
Refactor of BlockStorage and fix flower pot deserialisation
SupremeMortal Jan 10, 2021
63f2a4e
API Updates
Sleepybear Feb 1, 2021
4e8bad7
move EnchantmentTypes to API
Sleepybear Feb 4, 2021
728d86e
move EntityEvent to API and other updates
Sleepybear Feb 4, 2021
7856d1f
move AABB to API
Sleepybear Feb 4, 2021
e3c93f4
Move entity interfaces to API
Sleepybear Feb 4, 2021
edb829e
Move `impl` package to base `entity` package in Server repo
Sleepybear Feb 4, 2021
0ed53c5
Move Chunk and BlockEntity interfaces to API
Sleepybear Feb 4, 2021
b7f3e1d
Move BlockEntity to API
Sleepybear Feb 4, 2021
50988c1
Rename Player to CloudPlayer
Sleepybear Feb 5, 2021
7ad0afd
BaseEntity error fixes
Sleepybear Feb 5, 2021
0793ae3
Event fixes
Sleepybear Feb 5, 2021
0829056
Move firework data to API
Sleepybear Feb 5, 2021
817446c
migrate ResourcePack info
Sleepybear Feb 5, 2021
0cf3f6c
Player event fixes
Sleepybear Feb 6, 2021
8b8306a
implement Potions to API
Sleepybear Feb 8, 2021
e4094ca
Finsih Event API
Sleepybear Feb 10, 2021
5e84a4f
Inventory Interfaces
Sleepybear Feb 11, 2021
f675ba8
update protocol lib
Sleepybear Mar 10, 2021
7faafe8
update to use property for easier updating
Sleepybear Mar 10, 2021
7012e87
revert to com.nukkitx.math library
Sleepybear Mar 10, 2021
f1007d9
fixes
Sleepybear Mar 11, 2021
c95babd
Block Behavior fixes
Sleepybear Mar 12, 2021
bcff194
fixes and move ChunkManager to API
Sleepybear Mar 12, 2021
69c1909
Level and Chunk fixes
Sleepybear Mar 13, 2021
351ccbe
CloudPlayer fixes
Sleepybear Mar 16, 2021
a7be150
CloudLevel fixes
Sleepybear Mar 16, 2021
f105c75
CloudServer fixes
Sleepybear Mar 16, 2021
66bbd3c
Fixes
Sleepybear Mar 16, 2021
e6189b4
move data classes and fixes
Sleepybear Mar 17, 2021
799d7da
block entity and inventory fixes
Sleepybear Mar 17, 2021
889d479
remove duplicatated files
Sleepybear Mar 17, 2021
44c8df2
remove more duplicatated files
Sleepybear Mar 17, 2021
74281c3
more error fixes
Sleepybear Mar 18, 2021
21d40c7
Update block palette to 1.16.210
SupremeMortal Mar 18, 2021
082784c
Send message when level conversion is complete
SupremeMortal Mar 18, 2021
d42109a
Don't create dependency reduced pom
SupremeMortal Mar 18, 2021
1e48b9b
Server is now joinable with 1.16.210
SupremeMortal Mar 18, 2021
4540ac6
Finish error fixes
Sleepybear Mar 19, 2021
6bba574
re-add deprecated block trait and update BlockStateUpdaters lib
Sleepybear Mar 19, 2021
77fbb96
API Updates
Sleepybear Feb 1, 2021
8b5bb7b
move EnchantmentTypes to API
Sleepybear Feb 4, 2021
b1fb0d0
move EntityEvent to API and other updates
Sleepybear Feb 4, 2021
75e4781
move AABB to API
Sleepybear Feb 4, 2021
d0e30e9
Move entity interfaces to API
Sleepybear Feb 4, 2021
e3e66dd
Move `impl` package to base `entity` package in Server repo
Sleepybear Feb 4, 2021
5f667f0
Move Chunk and BlockEntity interfaces to API
Sleepybear Feb 4, 2021
6410dfe
Move BlockEntity to API
Sleepybear Feb 4, 2021
367761c
Rename Player to CloudPlayer
Sleepybear Feb 5, 2021
1759826
BaseEntity error fixes
Sleepybear Feb 5, 2021
54803e2
Event fixes
Sleepybear Feb 5, 2021
f42cc4f
Move firework data to API
Sleepybear Feb 5, 2021
38d49c4
migrate ResourcePack info
Sleepybear Feb 5, 2021
2aab5ed
Player event fixes
Sleepybear Feb 6, 2021
18a81d4
implement Potions to API
Sleepybear Feb 8, 2021
a267686
Finsih Event API
Sleepybear Feb 10, 2021
ef1e811
Inventory Interfaces
Sleepybear Feb 11, 2021
0c57392
update protocol lib
Sleepybear Mar 10, 2021
c8f0d5f
revert to com.nukkitx.math library
Sleepybear Mar 10, 2021
e5818bf
fixes
Sleepybear Mar 11, 2021
6a9dfd2
Block Behavior fixes
Sleepybear Mar 12, 2021
f68e78f
fixes and move ChunkManager to API
Sleepybear Mar 12, 2021
6723a2b
Level and Chunk fixes
Sleepybear Mar 13, 2021
b222220
CloudPlayer fixes
Sleepybear Mar 16, 2021
bbc8234
CloudLevel fixes
Sleepybear Mar 16, 2021
44ea3f0
CloudServer fixes
Sleepybear Mar 16, 2021
35d1c8a
Fixes
Sleepybear Mar 16, 2021
e2e40c0
move data classes and fixes
Sleepybear Mar 17, 2021
172ecf7
block entity and inventory fixes
Sleepybear Mar 17, 2021
2f5c0fc
remove duplicatated files
Sleepybear Mar 17, 2021
001a7d0
remove more duplicatated files
Sleepybear Mar 17, 2021
c76f77c
more error fixes
Sleepybear Mar 18, 2021
0ee7723
Finish error fixes
Sleepybear Mar 19, 2021
1bdb133
re-add deprecated block trait and update BlockStateUpdaters lib
Sleepybear Mar 19, 2021
ce002a1
rebase protocol-update branch
Sleepybear Mar 19, 2021
8aaf344
Merge remote-tracking branch 'Sleepy/api-changes' into api-changes
Sleepybear Mar 19, 2021
7fd9b6a
update block type with correct blocktraits
Sleepybear Mar 20, 2021
3013b1a
move Item data classes
Sleepybear Mar 20, 2021
6a84c09
convert to using recipes.json with string IDs
Sleepybear Mar 22, 2021
11b8dac
update submodules
Sleepybear Mar 22, 2021
9d669ec
Update item IDs
Sleepybear Mar 22, 2021
8d0c648
Update item IDs
Sleepybear Mar 22, 2021
2766454
Update Dye types
Sleepybear Mar 22, 2021
82b10aa
update boat IDs
Sleepybear Mar 22, 2021
d5f883b
load legacy ids from file
Sleepybear Mar 22, 2021
1e0e4c6
add spawn eggs
Sleepybear Mar 22, 2021
01ec256
implement unknown items
Sleepybear Mar 23, 2021
3b2ad19
add unregister methods to RecipeRegistry
Sleepybear Mar 23, 2021
bb00810
create player inventory interface
Sleepybear Mar 23, 2021
e14bdac
Update Skin data to expose to API
Sleepybear Mar 24, 2021
5633787
refactor block registry implementation
Sleepybear Mar 25, 2021
b5dd087
refactor skin processing
Sleepybear Mar 25, 2021
bd0f996
bugfix
Sleepybear Mar 25, 2021
34ad2be
Refactor Potion/Effect types to remove network data from API
Sleepybear Mar 26, 2021
1bd44f6
Start on Inventory refactor
Sleepybear Mar 26, 2021
c8eb8f1
Create inventory interfaces
Sleepybear Mar 26, 2021
64f642b
More inventory refactoring
Sleepybear Apr 12, 2021
ee541ff
Import updates
Sleepybear Apr 12, 2021
0f49dae
Build error fixes
Sleepybear Apr 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix block states in generator configuration
  • Loading branch information
Creeperface01 committed Oct 19, 2020
commit db66d77e261d6d736f1b4cf9530e6fbd3f9b8077
42 changes: 34 additions & 8 deletions src/main/java/org/cloudburstmc/server/block/BlockPalette.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ public boolean equals(NbtMap a, NbtMap b) {
});
private final Reference2ObjectMap<BlockState, NbtMap> stateSerializedMap = new Reference2ObjectLinkedOpenHashMap<>();
private final AtomicInteger runtimeIdAllocator = new AtomicInteger();
private final Reference2ReferenceMap<Identifier, BlockState> defaultStateMap = new Reference2ReferenceOpenHashMap<>();
private final Reference2ReferenceMap<BlockType, BlockState> defaultStateMap = new Reference2ReferenceOpenHashMap<>();
private final Reference2ReferenceMap<Identifier, BlockState> stateMap = new Reference2ReferenceOpenHashMap<>();
private final Reference2ReferenceMap<Identifier, Object2ReferenceMap<NbtMap, BlockState>> stateTraitMap = new Reference2ReferenceOpenHashMap<>();
private final Map<String, Set<Object>> vanillaTraitMap = new HashMap<>();

public void addBlock(BlockType type, BlockSerializer serializer, BlockTrait<?>[] traits) {
if (this.defaultStateMap.containsKey(type.getId())) {
if (this.defaultStateMap.containsKey(type)) {
log.warn("Duplicate block type: {}", type);
}

Expand All @@ -57,8 +60,8 @@ public void addBlock(BlockType type, BlockSerializer serializer, BlockTrait<?>[]
map.put(state.getTraits(), state);
}

BlockState defaultState = map.get(Arrays.stream(traits).collect(Collectors.toMap(t -> t, BlockTrait::getDefaultValue)));
this.defaultStateMap.put(type.getId(), defaultState);
BlockState defaultState = map.get(Arrays.stream(traits).filter(t -> !t.isOnlySerialize()).collect(Collectors.toMap(t -> t, BlockTrait::getDefaultValue)));
this.defaultStateMap.put(type, defaultState);

states.forEach((nbt, state) -> {
if (!state.isInitialized()) {
Expand All @@ -67,19 +70,42 @@ public void addBlock(BlockType type, BlockSerializer serializer, BlockTrait<?>[]
int runtimeId = this.runtimeIdAllocator.getAndIncrement();
this.stateRuntimeMap.put(state, runtimeId);
this.runtimeStateMap.put(runtimeId, state);
this.stateMap.putIfAbsent(state.getId(), state.defaultState());
}

val stateMap = nbt.getCompound("states");

val traitMap = stateTraitMap.computeIfAbsent(state.getId(), (v) -> new Object2ReferenceOpenHashMap<>());
traitMap.put(stateMap, state);

stateMap.forEach((traitName, traitValue) -> {
val traitValues = vanillaTraitMap.computeIfAbsent(traitName, (k) -> new LinkedHashSet<>());
traitValues.add(traitValue);
});

this.stateSerializedMap.put(state, nbt);
this.serializedStateMap.put(nbt, state);
});
}

public BlockState getDefaultState(Identifier id) {
return this.defaultStateMap.get(id);
public Map<String, Set<Object>> getVanillaTraitMap() {
return vanillaTraitMap;
}

public BlockState getState(Identifier id) {
return this.stateMap.get(id);
}

public BlockState getState(Identifier id, Map<String, Object> traits) {
return Optional.ofNullable(this.stateTraitMap.get(id)).map(s -> s.get(traits)).orElse(null);
}

public Set<String> getTraits(Identifier blockId) {
return Optional.ofNullable(this.stateTraitMap.get(blockId)).map(m -> Iterables.getLast(m.keySet()).keySet()).orElse(null);
}

public BlockState getDefaultState(BlockType blockType) {
return this.defaultStateMap.get(blockType.getId());
return this.defaultStateMap.get(blockType);
}

public BlockState getBlockState(int runtimeId) {
Expand Down Expand Up @@ -152,7 +178,7 @@ private static Map<NbtMap, CloudBlockState> getBlockPermutations(BlockType type,
}

Map<Map<BlockTrait<?>, Comparable<?>>, CloudBlockState> duplicated = new Object2ReferenceOpenHashMap<>();
Map<NbtMap, CloudBlockState> permutations = new Object2ReferenceOpenHashMap<>();
Map<NbtMap, CloudBlockState> permutations = new Object2ReferenceLinkedOpenHashMap<>();
int n = traits.length;

// To keep track of next element in each of the n arrays
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.cloudburstmc.server.level.generator.standard.StandardGeneratorUtils;
import org.cloudburstmc.server.block.util.BlockUtils;

import java.io.IOException;

Expand All @@ -14,6 +14,6 @@
final class BlockStateDeserializer extends JsonDeserializer<BlockState> {
@Override
public BlockState deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return StandardGeneratorUtils.parseState(p.getText());
return BlockUtils.parseState(p.getText());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ public BlockState getStateFromMeta(Identifier type, int meta) {
Int2ReferenceMap<BlockState> states = meta2state.get(type);

if (states == null) {
return BlockPalette.INSTANCE.getDefaultState(type);
return BlockPalette.INSTANCE.getState(type);
}

BlockState state = states.get(meta);
if (state == null) {
state = BlockPalette.INSTANCE.getDefaultState(type);
state = BlockPalette.INSTANCE.getState(type);
}

return state;
Expand Down
200 changes: 200 additions & 0 deletions src/main/java/org/cloudburstmc/server/block/util/BlockUtils.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
package org.cloudburstmc.server.block.util;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.nukkitx.math.vector.Vector3i;
import lombok.NonNull;
import lombok.experimental.UtilityClass;
import lombok.val;
import net.daporkchop.lib.common.misc.Tuple;
import net.daporkchop.lib.common.misc.string.PStrings;
import net.daporkchop.lib.common.ref.Ref;
import net.daporkchop.lib.common.ref.ThreadRef;
import net.daporkchop.lib.common.util.PorkUtil;
import org.cloudburstmc.server.block.BlockPalette;
import org.cloudburstmc.server.block.BlockState;
import org.cloudburstmc.server.block.BlockTraits;
import org.cloudburstmc.server.block.trait.BlockTrait;
import org.cloudburstmc.server.registry.BlockRegistry;
import org.cloudburstmc.server.utils.Identifier;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkArgument;
import static net.daporkchop.lib.common.util.PorkUtil.uncheckedCast;

@UtilityClass
public class BlockUtils {

private final Ref<Matcher> SINGLE_STATE_PATTERN = ThreadRef.regex(Pattern.compile(
"^((?:[a-z0-9_]+:)?[a-z0-9_]+)(\\{(?:[a-z_]+=[a-z0-9_]+(?:,\\s*)?)+\\})?$", Pattern.CASE_INSENSITIVE));
private final Ref<Matcher> SINGLE_TRAIT_PATTERN = ThreadRef.regex(Pattern.compile(
"(?<=^\\{|,|\\s)([a-z_]+)=([a-z0-9_]+),?(?=\\}$|,)", Pattern.CASE_INSENSITIVE));

private final Ref<Matcher> WILDCARD_STATE_PATTERN = ThreadRef.regex(Pattern.compile(
"^((?:[a-z0-9_]+:)?[a-z0-9_]+)(\\{(?:[a-z_]+=(?:[a-z0-9_]+|\\*)(?:,\\s*)?)+\\})?$", Pattern.CASE_INSENSITIVE));
private final Ref<Matcher> WILDCARD_TRAIT_PATTERN = ThreadRef.regex(Pattern.compile(
"(?<=^\\{|,|\\s)([a-z_]+)=([a-z0-9_]+|\\*),?(?=\\}$|,)", Pattern.CASE_INSENSITIVE));

private final Ref<Matcher> INT_PATTERN = ThreadRef.regex(Pattern.compile(
"\\d+", Pattern.CASE_INSENSITIVE));


public long key(Vector3i position) {
return key(position.getX(), position.getY(), position.getZ());
}
Expand All @@ -23,4 +61,166 @@ public Vector3i fromKey(long key) {
int z = (int) (key & 0xFFFFFFF);
return Vector3i.from(x, y, z);
}

public <T extends Comparable<T>> BlockTrait<T> findTrait(@NonNull BlockState state, @NonNull String traitName) {
BlockTrait<?> trait = BlockTraits.from(traitName);
if (trait == null) {
//fall back to vanilla name
trait = BlockTraits.fromVanilla(traitName);
}
checkArgument(trait != null, "unknown trait: \"%s\"", traitName);
checkArgument(state.getTrait(trait) != null, "block %s doesn't contain trait \"%s\"!", state.getType(), traitName);
return uncheckedCast(trait);
}

public <T extends Comparable<T>> T parseTrait(@NonNull BlockTrait<T> trait, @NonNull String valueText) {
for (T value : trait.getPossibleValues()) {
if (valueText.equalsIgnoreCase(value.toString())) {
return value;
}
}
throw new IllegalArgumentException(PStrings.fastFormat("trait %s (vanilla: %s) doesn't contain value \"%s\"", trait.getName(), PorkUtil.fallbackIfNull(trait.getVanillaName(), trait.getName()), valueText));
}

public BlockState applyTrait(@NonNull BlockState state, @NonNull String traitName, @NonNull String valueText) {
BlockTrait<?> trait = findTrait(state, traitName);
return state.withTrait(trait, uncheckedCast(parseTrait(trait, valueText)));
}

private void applyDefaultValues(Identifier id, Map<String, Object> traits) {
val vanillaTraits = BlockPalette.INSTANCE.getVanillaTraitMap();

BlockPalette.INSTANCE.getTraits(id).forEach(name -> {
traits.computeIfAbsent(name, k -> Iterables.get(vanillaTraits.get(name), 0));
});
}

public Object convertTraitValue(String value) {
value = value.toLowerCase();

if (value.equals("false")) {
return false;
}

if (value.equals("true")) {
return true;
}

if (INT_PATTERN.get().reset(value).matches()) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException ignore) {

}
}

return value;
}

/**
* Parses a {@link BlockState} formatted as:
* <p>
* {@code [namespace:]<id>[{trait=value[,trait2=value2[,...]]}]}
* <p>
* Examples:
* <p>
* - {@code minecraft:stone}
* - {@code stone{stone_type=granite}}
* - {@code minecraft:golden_rail{is_powered=true,simple_rail_direction=north_south}}
*
* @param input the {@link String} to parse
* @return the parsed {@link BlockState}
* @throws IllegalArgumentException if the input could not be parsed
*/
public static BlockState parseState(@NonNull String input) {
Matcher matcher = SINGLE_STATE_PATTERN.get().reset(input);
checkArgument(matcher.find(), "unable to parse block state: \"%s\"", input);

String idText = matcher.group(1);
Identifier blockId = Identifier.fromString(idText);
checkArgument(BlockRegistry.get().getBlock(blockId) != null, "unknown block: \"%s\"", idText);

Map<String, Object> traits = new HashMap<>();
String traitsTxt = matcher.group(2);
if (traitsTxt != null) {
matcher = SINGLE_TRAIT_PATTERN.get().reset(traitsTxt);
while (matcher.find()) {
traits.put(matcher.group(1), convertTraitValue(matcher.group(2)));
}
}

applyDefaultValues(blockId, traits);

BlockState state = BlockPalette.INSTANCE.getState(blockId, traits);
checkArgument(state != null, "unknown block: \"%s\" with traits: \"%s\" (%s)", idText, traits, traitsTxt);

return state;
}

/**
* Variant of {@link #parseState(String)} which can process trait values with wildcards.
* <p>
* Examples:
* <p>
* - {@code minecraft:stone}
* - {@code stone{stone_type=granite}}
* - {@code minecraft:golden_rail{is_powered=*,simple_rail_direction=north_south}}
*
* @param input the {@link String} to parse
* @return all {@link BlockState}s which matched the input
* @throws IllegalArgumentException if the input could not be parsed
*/
public static Stream<BlockState> parseStateWildcard(@NonNull String input) {
Matcher matcher = WILDCARD_STATE_PATTERN.get().reset(input);
checkArgument(matcher.find(), "unable to parse block state: \"%s\"", input);

String idText = matcher.group(1);
Identifier blockId = Identifier.fromString(idText);
checkArgument(BlockRegistry.get().getBlock(blockId) != null, "unknown block: \"%s\"", idText);

List<Map<String, Object>> variants = new ArrayList<>();

String traitsTxt = matcher.group(2);
Map<String, Object> base = new HashMap<>();
if (traitsTxt != null) {
List<String> wildcart = new LinkedList<>();

matcher = WILDCARD_TRAIT_PATTERN.get().reset(traitsTxt);
while (matcher.find()) {
String traitName = matcher.group(1);
String valueText = matcher.group(2);
if ("*".equals(valueText)) {
wildcart.add(traitName);
} else {
base.put(traitName, convertTraitValue(valueText));
}
}

applyDefaultValues(blockId, base);

if (wildcart.isEmpty()) {
variants.add(base);
} else {
Lists.cartesianProduct(wildcart.stream().flatMap(name ->
BlockPalette.INSTANCE.getVanillaTraitMap().getOrDefault(name, Collections.emptySet())
.stream()
.map(v -> new Tuple<>(name, v))
)
.collect(Collectors.toList()))
.forEach(entries ->
variants.add(entries.stream().collect(Collectors.toMap(Tuple::getA, Tuple::getB)))
);
}
} else {
applyDefaultValues(blockId, base);
variants.add(base);
}

return variants.stream().map(traits -> {
BlockState state = BlockPalette.INSTANCE.getState(blockId, traits);
checkArgument(state != null, "unknown block: \"%s\" with traits: \"%s\" (%s)", idText, traits, traitsTxt);

return state;
});
}
}
Loading