Skip to content

Commit

Permalink
Prevent infinite log spam from missing chunk components, resolves #156
Browse files Browse the repository at this point in the history
  • Loading branch information
Pyrofab committed May 19, 2024
1 parent 447d679 commit a98d8c8
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
*/
package org.ladysnake.cca.internal.base;

import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Identifier;
Expand Down Expand Up @@ -74,8 +74,8 @@ public void copyFrom(ComponentContainer other, RegistryWrapper.WrapperLookup reg
*/
@Override
public void fromTag(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) {
if(tag.contains(NBT_KEY, NbtType.LIST)) {
NbtList componentList = tag.getList(NBT_KEY, NbtType.COMPOUND);
if(tag.contains(NBT_KEY, NbtElement.LIST_TYPE)) {
NbtList componentList = tag.getList(NBT_KEY, NbtElement.COMPOUND_TYPE);
for (int i = 0; i < componentList.size(); i++) {
NbtCompound nbt = componentList.getCompound(i);
ComponentKey<?> type = ComponentRegistry.get(new Identifier(nbt.getString("componentId")));
Expand All @@ -86,13 +86,13 @@ public void fromTag(NbtCompound tag, RegistryWrapper.WrapperLookup registryLooku
}
}
}
} else if (tag.contains("cardinal_components", NbtType.COMPOUND)) {
} else if (tag.contains(NBT_KEY, NbtElement.COMPOUND_TYPE)) {
NbtCompound componentMap = tag.getCompound(NBT_KEY);

for (ComponentKey<?> key : this.keys()) {
String keyId = key.getId().toString();

if (componentMap.contains(keyId, NbtType.COMPOUND)) {
if (componentMap.contains(keyId, NbtElement.COMPOUND_TYPE)) {
Component component = key.getInternal(this);
assert component != null;
component.readFromNbt(componentMap.getCompound(keyId), registryLookup);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
*/
package org.ladysnake.cca.internal.base;

import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
Expand All @@ -42,27 +44,44 @@

public final class ComponentsInternals {
public static final Logger LOGGER = LogManager.getLogger("Cardinal Components API");
private static boolean logDeserializationWarnings = true;
private static final int DEFAULT_MAX_WARNINGS_PER_COMPONENT = 5;
private static final boolean DEFAULT_LOG_DESERIALIZATION_WARNINGS = true;
private static final int configVersion = 2;
private static boolean logDeserializationWarnings = DEFAULT_LOG_DESERIALIZATION_WARNINGS;
private static int maxWarningsPerComponent = DEFAULT_MAX_WARNINGS_PER_COMPONENT;
private static final Object2IntMap<String> warningCounts = new Object2IntOpenHashMap<>();

public static void init() {
Path path = FabricLoader.getInstance().getConfigDir().resolve("cardinal-components-api.properties");
try(Reader reader = Files.newBufferedReader(path)) {
Properties cfg = new Properties();
cfg.load(reader);
logDeserializationWarnings = Boolean.parseBoolean(cfg.getProperty("log-deserialization-warnings", "true"));
if (Integer.parseInt(cfg.getProperty("config-version")) < configVersion) {
writeConfigFile(path);
cfg.clear();
}
logDeserializationWarnings = Boolean.parseBoolean(cfg.getProperty("log-deserialization-warnings", String.valueOf(DEFAULT_LOG_DESERIALIZATION_WARNINGS)));
maxWarningsPerComponent = Integer.parseInt(cfg.getProperty("max-deserialization-warnings", String.valueOf(DEFAULT_MAX_WARNINGS_PER_COMPONENT)));
} catch (IOException e) {
try {
Files.writeString(path, """
# If set to false, warnings will not get logged when a component fails to be resolved (typically due to mods being removed)
# Default value: true
log-deserialization-warnings = true
writeConfigFile(path);
}
}

# Internal value, do not edit or your changes may be arbitrarily reset
config-version = 1
""");
} catch (IOException ex) {
LOGGER.error("Failed to write config file at {}", path);
}
private static void writeConfigFile(Path path) {
try {
Files.writeString(path, """
# If set to false, warnings will not get logged when a component fails to be resolved (typically due to mods being removed)
# Default value: %1$s
log-deserialization-warnings = %1$s
# If log-deserialization-warnings is enabled, warnings will be printed at most *this number of times* for every component type
# Default value: %2$d
max-deserialization-warnings = %2$d
# Internal value, do not edit or your changes may be arbitrarily reset
config-version = %3$d
""".formatted(DEFAULT_LOG_DESERIALIZATION_WARNINGS, DEFAULT_MAX_WARNINGS_PER_COMPONENT, configVersion));
} catch (IOException ex) {
LOGGER.error("Failed to write config file at {}", path);
}
}

Expand All @@ -78,12 +97,16 @@ public static <R> R createFactory(Class<R> factoryClass) {
public static void logDeserializationWarnings(Collection<String> missedKeyIds) {
if (logDeserializationWarnings) {
for (String missedKeyId : missedKeyIds) {
Identifier id = Identifier.tryParse(missedKeyId);
String cause;
if (id == null) cause = "invalid identifier";
else if (ComponentRegistry.get(id) == null) cause = "unregistered key";
else cause = "provider does not have ";
LOGGER.warn("Failed to deserialize component: {} {}", cause, missedKeyId);
int warningCount = warningCounts.getInt(missedKeyId);
if (warningCount < maxWarningsPerComponent) {
Identifier id = Identifier.tryParse(missedKeyId);
String cause;
if (id == null) cause = "invalid identifier";
else if (ComponentRegistry.get(id) == null) cause = "unregistered key";
else cause = "provider does not have ";
LOGGER.warn("Failed to deserialize component: {} {}{}", cause, missedKeyId, warningCount + 1 >= maxWarningsPerComponent ? " (last warning for this component)" : "");
warningCounts.put(missedKeyId, warningCount + 1);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
package org.ladysnake.cca.mixin.chunk.common;

import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.ChunkSerializer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ProtoChunk;
import net.minecraft.world.chunk.WrapperProtoChunk;
import net.minecraft.world.poi.PointOfInterestStorage;
import org.ladysnake.cca.internal.base.AbstractComponentContainer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
Expand All @@ -42,6 +44,11 @@ private static void deserialize(ServerWorld world, PointOfInterestStorage pointO
ProtoChunk ret = cir.getReturnValue();
Chunk chunk = ret instanceof WrapperProtoChunk ? ((WrapperProtoChunk) ret).getWrappedChunk() : ret;
chunk.asComponentProvider().getComponentContainer().fromTag(tag, world.getRegistryManager());
// If components have been removed, we need to make the chunk save again
if (tag.contains(AbstractComponentContainer.NBT_KEY, NbtElement.COMPOUND_TYPE)) {
int remainingComponentCount = tag.getCompound(AbstractComponentContainer.NBT_KEY).getSize();
chunk.setNeedsSaving(remainingComponentCount > 0);
}
}

@Inject(method = "serialize", at = @At("RETURN"))
Expand Down
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ Updated to 1.20.5/1.20.6

This update introduces multiple breaking changes - a migration guide is available on [the Ladysnake website](https://ladysnake.org/wiki/cardinal-components-api/upgrade-instructions/CCA-6-changes).

### Pre-Release 3
**Fixes**
- Missing components (usually caused by removed mods) will no longer trigger a wall of warnings
- The number of warnings logged for each missing component type is configurable

### Pre-Release 2
**Fixes**
- The library no longer requires Loom 1.7-alpha to be used in dev workspaces
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fabric_api_version=0.98.0+1.20.6
elmendorf_version=0.12.0-SNAPSHOT

#Publishing
mod_version = 6.0.0-pre2
mod_version = 6.0.0-pre3
curseforge_id = 318449
modrinth_id = K01OU20C
curseforge_versions = 1.20.5; 1.20.6
Expand Down

0 comments on commit a98d8c8

Please sign in to comment.