Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid generating a new material list every time #682

Open
wants to merge 2 commits into
base: 1.20.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public abstract class AbstractMaterial implements IMaterial {
protected int tier = -1;
protected Tier harvestTier = Tiers.IRON;
protected Ingredient ingredient = Ingredient.EMPTY;
protected final Map<PartType, Ingredient> partSubstitutes = new HashMap<>();
protected Map<PartType, Ingredient> partSubstitutes = Map.of();

protected final Map<PartType, StatModifierMap> stats = new LinkedHashMap<>();
protected final Map<PartType, List<TraitInstance>> traits = new LinkedHashMap<>();
Expand Down Expand Up @@ -256,8 +256,7 @@ public boolean isVisible(PartType partType) {
public void updateIngredient(SyncMaterialCraftingItemsPacket msg) {
if (msg.isValid()) {
msg.getIngredient(this.materialId).ifPresent(ing -> this.ingredient = ing);
this.partSubstitutes.clear();
msg.getPartSubstitutes(this.materialId).forEach(this.partSubstitutes::put);
this.partSubstitutes = Map.copyOf(msg.getPartSubstitutes(this.materialId));
}
}

Expand Down Expand Up @@ -499,7 +498,7 @@ private void deserializeCraftingItems(JsonObject json, T ret) {
Ingredient ingredient = Ingredient.fromJson(entry.getValue());
map.put(partType, ingredient);
});
ret.partSubstitutes.putAll(map);
ret.partSubstitutes = Map.copyOf(map);
}
} else {
throw new JsonSyntaxException("Expected 'crafting_items' to be an object");
Expand Down Expand Up @@ -594,11 +593,13 @@ private void readCraftingItems(FriendlyByteBuf buffer, T material) {

// Part subs
int subCount = buffer.readByte();
Map.Entry<PartType, Ingredient>[] subs = new Map.Entry[subCount];
for (int i = 0; i < subCount; ++i) {
PartType partType = PartType.get(buffer.readResourceLocation());
Ingredient ingredient = tempReadIngredientFix(buffer);
material.partSubstitutes.put(partType, ingredient);
subs[i] = Map.entry(partType, ingredient);
}
material.partSubstitutes = Map.ofEntries(subs);
}

private void readDisplayProperties(FriendlyByteBuf buf, T material) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.network.NetworkEvent;
import net.silentchaos512.gear.SilentGear;
import net.silentchaos512.gear.api.material.IMaterial;
import net.silentchaos512.gear.gear.GearJsonException;
import net.silentchaos512.gear.gear.MaterialJsonException;
import net.silentchaos512.gear.network.SyncMaterialsPacket;
import net.silentchaos512.gear.util.TextUtil;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.io.IOException;
Expand All @@ -42,6 +42,8 @@ public class MaterialManager implements ResourceManagerReloadListener {

private static final String DATA_PATH = "silentgear_materials";
private static final Map<ResourceLocation, IMaterial> MATERIALS = Collections.synchronizedMap(new LinkedHashMap<>());
private static final List<IMaterial> ROOT_MATERIAL_LIST = new ArrayList<>();
private static final Map<Item, IMaterial> MATERIAL_LOOKUP_MAP = Collections.synchronizedMap(new IdentityHashMap<>());
private static final Collection<String> ERROR_LIST = new ArrayList<>();
private static final Collection<String> INGREDIENT_CONFLICT_LIST = new ArrayList<>();

Expand Down Expand Up @@ -86,6 +88,7 @@ public void onResourceManagerReload(ResourceManager resourceManager) {
}
}
}
recreateMaterialCache();
}

checkForIngredientConflicts(ingredientConflicts);
Expand Down Expand Up @@ -131,20 +134,17 @@ private static void logSkippedMaterials(Collection<ResourceLocation> list) {
}
}

public static List<IMaterial> getValues() {
return getValues(true);
public static Collection<IMaterial> getValues() {
synchronized (MATERIALS) {
return MATERIALS.values();
}
}

public static List<IMaterial> getValues(boolean includeChildren) {
synchronized (MATERIALS) {
List<IMaterial> list = new ArrayList<>();
for (IMaterial m : MATERIALS.values()) {
if (includeChildren || m.getParent() == null) {
list.add(m);
}
}
return list;
public static Collection<IMaterial> getValues(boolean includeChildren) {
if (includeChildren) {
return getValues();
}
return Collections.unmodifiableList(ROOT_MATERIAL_LIST);
}

public static List<IMaterial> getChildren(IMaterial material) {
Expand Down Expand Up @@ -172,10 +172,9 @@ public static IMaterial get(@Nullable ResourceLocation id) {
public static IMaterial from(ItemStack stack) {
if (stack.isEmpty()) return null;

for (IMaterial material : getValues()) {
if (material.getIngredient().test(stack)) {
return material;
}
IMaterial lookup = MATERIAL_LOOKUP_MAP.get(stack.getItem());
if (lookup != null && lookup.getIngredient().test(stack)) {
return lookup;
}

return null;
Expand All @@ -189,6 +188,7 @@ public static void handleSyncPacket(SyncMaterialsPacket msg, Supplier<NetworkEve
mat.retainData(oldMaterials.get(mat.getId()));
MATERIALS.put(mat.getId(), mat);
}
recreateMaterialCache();
SilentGear.LOGGER.info("Read {} materials from server", MATERIALS.size());
}
ctx.get().setPacketHandled(true);
Expand All @@ -208,4 +208,30 @@ public static Collection<Component> getErrorMessages(ServerPlayer player) {
});
return ret;
}

private static void recreateMaterialCache() {
synchronized (MATERIALS) {
ROOT_MATERIAL_LIST.clear();
MATERIAL_LOOKUP_MAP.clear();
for (IMaterial mat : MATERIALS.values()) {
if (mat.getParent() == null) {
ROOT_MATERIAL_LIST.add(mat);
}
for (ItemStack itemStack : mat.getIngredient().getItems()) {
Item item = itemStack.getItem();
if (Blocks.BARRIER.asItem().equals(item)) {
// When a material has no valid ingredients for it (e.g. no items with the tag
// `forge:ingots/bismuth_brass` exist for bismuth_brass material), Ingredient.getItems() returns
// a single Barrier item. Just ignore it because it means the material isn't obtainable anyway.
continue;
}

IMaterial prevMat = MATERIAL_LOOKUP_MAP.put(item, mat);
if (prevMat != null) {
SilentGear.LOGGER.error("Registered more than one material ({}, {}) for the same item ({})!", mat, prevMat, item);
}
}
}
}
}
}
27 changes: 21 additions & 6 deletions src/main/java/net/silentchaos512/gear/gear/part/PartManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.network.NetworkEvent;
import net.silentchaos512.gear.SilentGear;
import net.silentchaos512.gear.api.part.IGearPart;
Expand All @@ -33,14 +35,14 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

@SuppressWarnings("deprecation")
public final class PartManager implements ResourceManagerReloadListener {
public static final PartManager INSTANCE = new PartManager();

public static final Marker MARKER = MarkerManager.getMarker("PartManager");

private static final String DATA_PATH = "silentgear_parts";
private static final Map<ResourceLocation, IGearPart> MAP = Collections.synchronizedMap(new LinkedHashMap<>());
private static final Map<Item, IGearPart> LOOKUP_MAP = Collections.synchronizedMap(new IdentityHashMap<>());
private static int highestMainPartTier = 0;
private static final Collection<String> ERROR_LIST = new ArrayList<>();

Expand All @@ -58,6 +60,7 @@ public void onResourceManagerReload(ResourceManager resourceManager) {

synchronized (MAP) {
MAP.clear();
LOOKUP_MAP.clear();
ERROR_LIST.clear();
SilentGear.LOGGER.info(MARKER, "Reloading part files");

Expand Down Expand Up @@ -114,6 +117,20 @@ private static void addPart(IGearPart part) {
throw new IllegalStateException("Duplicate gear part " + part.getId());
} else {
MAP.put(part.getId(), part);
for (ItemStack itemStack : part.getIngredient().getItems()) {
Item item = itemStack.getItem();
if (Blocks.BARRIER.asItem().equals(item)) {
// When a material has no valid ingredients for it (e.g. no items with the tag
// `forge:ingots/bismuth_brass` exist for bismuth_brass material), Ingredient.getItems() returns
// a single Barrier item. Just ignore it because it means the material isn't obtainable anyway.
continue;
}

IGearPart prevPart = LOOKUP_MAP.put(item, part);
if (prevPart != null) {
SilentGear.LOGGER.error("Registered more than one part ({}, {}) for the same item ({})!", part, prevPart, item);
}
}
}
}

Expand Down Expand Up @@ -156,11 +173,9 @@ public static IGearPart get(String id) {
public static IGearPart from(ItemStack stack) {
if (stack.isEmpty()) return null;

// We can't reliable keep an IItemProvider -> IGearPart map anymore
for (IGearPart part : getValues()) {
if (part.getIngredient().test(stack)) {
return part;
}
IGearPart lookup = LOOKUP_MAP.get(stack.getItem());
if (lookup != null && lookup.getIngredient().test(stack)) {
return lookup;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public Optional<Ingredient> getIngredient(ResourceLocation materialId) {
}

public Map<PartType, Ingredient> getPartSubstitutes(ResourceLocation materialId) {
return partSubs.getOrDefault(materialId, Collections.emptyMap());
return partSubs.getOrDefault(materialId, Map.of());
}

public static SyncMaterialCraftingItemsPacket decode(FriendlyByteBuf buffer) {
Expand Down