Skip to content

Commit

Permalink
Fix leaking of temporary DimensionOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Patbox committed Apr 30, 2022
1 parent a92e165 commit fd58345
Show file tree
Hide file tree
Showing 15 changed files with 328 additions and 34 deletions.
15 changes: 12 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '0.10-SNAPSHOT'
id 'fabric-loom' version '0.11-SNAPSHOT'
id 'maven-publish'
}

Expand All @@ -10,8 +10,15 @@ archivesBaseName = project.archives_base_name
version = project.mod_version + "+" + project.minecraft_version
group = project.maven_group

minecraft {
accessWidener = file("src/main/resources/fantasy.accesswidener")
loom {
accessWidenerPath = file("src/main/resources/fantasy.accesswidener")
}

sourceSets {
testmod {
compileClasspath += main.compileClasspath
runtimeClasspath += main.runtimeClasspath
}
}

repositories {
Expand All @@ -24,6 +31,8 @@ dependencies {
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"

testmodImplementation sourceSets.main.output
}

processResources {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ yarn_mappings=1.18.2+build.1
loader_version=0.13.3

# Mod Properties
mod_version=0.4.4
mod_version=0.4.5
maven_group=xyz.nucleoid
archives_base_name=fantasy

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/xyz/nucleoid/fantasy/FantasyDimensionOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package xyz.nucleoid.fantasy;

import net.minecraft.world.dimension.DimensionOptions;

import java.util.function.Predicate;

public interface FantasyDimensionOptions {
Predicate<DimensionOptions> SAVE_PREDICATE = (e) -> ((FantasyDimensionOptions) (Object) e).fantasy$getSave();

void fantasy$setSave(boolean value);
boolean fantasy$getSave();
}
3 changes: 3 additions & 0 deletions src/main/java/xyz/nucleoid/fantasy/FantasyWorldAccess.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package xyz.nucleoid.fantasy;

import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public interface FantasyWorldAccess {
void fantasy$setTickWhenEmpty(boolean tickWhenEmpty);

Expand Down
14 changes: 8 additions & 6 deletions src/main/java/xyz/nucleoid/fantasy/RemoveFromRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@

import net.minecraft.util.Identifier;
import net.minecraft.util.registry.SimpleRegistry;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public interface RemoveFromRegistry<T> {
@SuppressWarnings("unchecked")
static <T> boolean remove(SimpleRegistry<T> registry, Identifier key) {
return ((RemoveFromRegistry<T>) registry).remove(key);
return ((RemoveFromRegistry<T>) registry).fantasy$remove(key);
}

@SuppressWarnings("unchecked")
static <T> boolean remove(SimpleRegistry<T> registry, T value) {
return ((RemoveFromRegistry<T>) registry).remove(value);
return ((RemoveFromRegistry<T>) registry).fantasy$remove(value);
}

boolean remove(T value);
boolean fantasy$remove(T value);

boolean remove(Identifier key);
boolean fantasy$remove(Identifier key);

void setFrozen(boolean value);
void fantasy$setFrozen(boolean value);

boolean isFrozen();
boolean fantasy$isFrozen();
}
10 changes: 7 additions & 3 deletions src/main/java/xyz/nucleoid/fantasy/RuntimeWorldManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ final class RuntimeWorldManager {
RuntimeWorld add(RegistryKey<World> worldKey, RuntimeWorldConfig config, RuntimeWorld.Style style) {
DimensionOptions options = config.createDimensionOptions(this.server);

if (style == RuntimeWorld.Style.TEMPORARY) {
((FantasyDimensionOptions) (Object) options).fantasy$setSave(false);
}

SimpleRegistry<DimensionOptions> dimensionsRegistry = getDimensionsRegistry(this.server);
boolean isFrozen = ((RemoveFromRegistry<?>) dimensionsRegistry).isFrozen();
((RemoveFromRegistry<?>) dimensionsRegistry).setFrozen(false);
boolean isFrozen = ((RemoveFromRegistry<?>) dimensionsRegistry).fantasy$isFrozen();
((RemoveFromRegistry<?>) dimensionsRegistry).fantasy$setFrozen(false);
dimensionsRegistry.add(RegistryKey.of(Registry.DIMENSION_KEY, worldKey.getValue()), options, Lifecycle.stable());
((RemoveFromRegistry<?>) dimensionsRegistry).setFrozen(isFrozen);
((RemoveFromRegistry<?>) dimensionsRegistry).fantasy$setFrozen(isFrozen);

RuntimeWorld world = new RuntimeWorld(this.server, worldKey, config, style);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package xyz.nucleoid.fantasy.mixin.registry;

import net.minecraft.world.dimension.DimensionOptions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import xyz.nucleoid.fantasy.FantasyDimensionOptions;

@Mixin(DimensionOptions.class)
public class DimensionOptionsMixin implements FantasyDimensionOptions {
@Unique
private boolean fantasy$save = true;

@Override
public void fantasy$setSave(boolean value) {
this.fantasy$save = value;
}

@Override
public boolean fantasy$getSave() {
return this.fantasy$save;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package xyz.nucleoid.fantasy.mixin.registry;

import net.minecraft.util.registry.Registry;
import net.minecraft.world.dimension.DimensionOptions;
import net.minecraft.world.gen.GeneratorOptions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import xyz.nucleoid.fantasy.FantasyDimensionOptions;
import xyz.nucleoid.fantasy.util.FilteredRegistry;

import java.util.function.Function;

@Mixin(GeneratorOptions.class)
public class GeneratorOptionsMixin {
@ModifyArg(method = "method_28606", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/MapCodec;forGetter(Ljava/util/function/Function;)Lcom/mojang/serialization/codecs/RecordCodecBuilder;", ordinal = 3))
private static Function<GeneratorOptions, Registry<DimensionOptions>> fantasy$wrapRegistry(Function<GeneratorOptions, Registry<DimensionOptions>> getter) {
return (e) -> new FilteredRegistry<>(e.getDimensions(), FantasyDimensionOptions.SAVE_PREDICATE);
}}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package xyz.nucleoid.fantasy.mixin.registry;

import com.google.common.collect.BiMap;
import com.mojang.serialization.Lifecycle;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.ObjectList;
Expand Down Expand Up @@ -42,41 +41,46 @@ public abstract class SimpleRegistryMixin<T> implements RemoveFromRegistry<T> {
@Shadow @Nullable private List<RegistryEntry.Reference<T>> cachedEntries;

@Override
public boolean remove(T entry) {
public boolean fantasy$remove(T entry) {
var registryEntry = this.valueToEntry.get(entry);
int rawId = this.entryToRawId.removeInt(entry);
if (rawId == -1) {
return false;
}

this.rawIdToEntry.set(rawId, null);
this.idToEntry.remove(registryEntry);
this.keyToEntry.remove(registryEntry);
this.entryToLifecycle.remove(entry);
this.valueToEntry.remove(entry);
if (this.cachedEntries != null) {
this.cachedEntries.remove(registryEntry);
}
if (this.unfrozenValueToEntry != null) {
this.unfrozenValueToEntry.remove(entry);
try {
this.rawIdToEntry.set(rawId, null);
this.idToEntry.remove(registryEntry.registryKey().getValue());
this.keyToEntry.remove(registryEntry.registryKey());
this.entryToLifecycle.remove(entry);
this.valueToEntry.remove(entry);
if (this.cachedEntries != null) {
this.cachedEntries.remove(registryEntry);
}
if (this.unfrozenValueToEntry != null) {
this.unfrozenValueToEntry.remove(entry);
}

return true;
} catch (Throwable e) {
e.printStackTrace();
return false;
}

return true;
}

@Override
public boolean remove(Identifier key) {
public boolean fantasy$remove(Identifier key) {
var entry = this.idToEntry.get(key);
return entry != null && entry.hasKeyAndValue() && this.remove(entry.value());
return entry != null && entry.hasKeyAndValue() && this.fantasy$remove(entry.value());
}

@Override
public void setFrozen(boolean value) {
public void fantasy$setFrozen(boolean value) {
this.frozen = value;
}

@Override
public boolean isFrozen() {
public boolean fantasy$isFrozen() {
return this.frozen;
}
}
Loading

0 comments on commit fd58345

Please sign in to comment.