Skip to content

Commit

Permalink
Slightly optimise and improve debugability of state creation code (#2469
Browse files Browse the repository at this point in the history
)

* Slightly optimise and improve debugability of state creation code

* Make 5s rather than 60, and add time taken to the output
  • Loading branch information
me4502 authored Feb 17, 2024
1 parent ed36e74 commit 8c656bd
Showing 1 changed file with 37 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package com.sk89q.worldedit.world.block;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Lists;
Expand Down Expand Up @@ -79,22 +80,30 @@ public void setInternalId(BlockState blockState, int internalId) {
this.emptyBaseBlock = new BaseBlock(this);
}

/**
* Generates a map of all possible states for a block type.
*
* @param blockType The block type
* @return The map of states
*/
static Map<Map<Property<?>, Object>, BlockState> generateStateMap(BlockType blockType) {
ImmutableMap.Builder<Map<Property<?>, Object>, BlockState> stateMapBuilder = ImmutableMap.builder();
List<? extends Property<?>> properties = blockType.getProperties();
ImmutableMap.Builder<Map<Property<?>, Object>, BlockState> stateMapBuilder = null;

if (!properties.isEmpty()) {
List<List<Object>> separatedValues = Lists.newArrayList();
// Create a list of lists of values, with a copy of the underlying lists
List<List<Object>> separatedValues = Lists.newArrayListWithCapacity(properties.size());
for (Property<?> prop : properties) {
List<Object> vals = Lists.newArrayList();
vals.addAll(prop.getValues());
separatedValues.add(vals);
separatedValues.add(ImmutableList.copyOf(prop.getValues()));
}

List<List<Object>> valueLists = Lists.cartesianProduct(separatedValues);
stateMapBuilder = ImmutableMap.builderWithExpectedSize(valueLists.size());
for (List<Object> valueList : valueLists) {
Map<Property<?>, Object> valueMap = Maps.newTreeMap(Comparator.comparing(Property::getName));
BlockState stateMaker = new BlockState(blockType);
for (int i = 0; i < valueList.size(); i++) {
int valueCount = valueList.size();
for (int i = 0; i < valueCount; i++) {
Property<?> property = properties.get(i);
Object value = valueList.get(i);
valueMap.put(property, value);
Expand All @@ -104,27 +113,40 @@ static Map<Map<Property<?>, Object>, BlockState> generateStateMap(BlockType bloc
}
}

ImmutableMap<Map<Property<?>, Object>, BlockState> stateMap = stateMapBuilder.build();
ImmutableMap<Map<Property<?>, Object>, BlockState> stateMap;

if (stateMap.isEmpty()) {
if (stateMapBuilder == null) {
// No properties.
stateMap = ImmutableMap.of(ImmutableMap.of(), new BlockState(blockType));
} else {
stateMap = stateMapBuilder.build();
}

Watchdog watchdog = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getWatchdog();
long startTime = System.currentTimeMillis();

for (BlockState state : stateMap.values()) {
state.populate(stateMap);
}

// Sometimes loading can take a while. This is the perfect spot to let MC know we're working.
Watchdog watchdog = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getWatchdog();
if (watchdog != null) {
watchdog.tick();
// Sometimes loading can take a while. This is the perfect spot to let MC know we're working.
if (watchdog != null) {
watchdog.tick();
}
}
long timeTaken = System.currentTimeMillis() - startTime;
if (timeTaken > 5000) {
WorldEdit.logger.warn("Took more than 5 seconds to generate complete state map for " + blockType.getId() + ". This block is likely improperly using properties. State count: " + stateMap.size() + ". " + timeTaken + "ms elapsed.");
}

return stateMap;
}

/**
* Creates the underlying state table for object lookups.
*
* @param stateMap The state map to generate the table from
*/
private void populate(Map<Map<Property<?>, Object>, BlockState> stateMap) {
final ImmutableTable.Builder<Property<?>, Object, BlockState> states = ImmutableTable.builder();

Expand All @@ -148,7 +170,7 @@ private void populate(Map<Map<Property<?>, Object>, BlockState> stateMap) {
}

private <V> Map<Property<?>, Object> withValue(final Property<V> property, final V value) {
final ImmutableMap.Builder<Property<?>, Object> values = ImmutableMap.builder();
final ImmutableMap.Builder<Property<?>, Object> values = ImmutableMap.builderWithExpectedSize(this.values.size());
for (Map.Entry<Property<?>, Object> entry : this.values.entrySet()) {
if (entry.getKey().equals(property)) {
values.put(entry.getKey(), value);
Expand Down

0 comments on commit 8c656bd

Please sign in to comment.