Skip to content

Commit

Permalink
Bump 1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
himekifee committed Feb 13, 2022
1 parent 8736eff commit 08573b6
Show file tree
Hide file tree
Showing 35 changed files with 1,507 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: |
${{ runner.os }}-gradle-
Expand Down
6 changes: 5 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '0.11-SNAPSHOT'
id 'fabric-loom' version '0.10-SNAPSHOT'
id 'maven-publish'
}

Expand Down Expand Up @@ -38,6 +38,10 @@ dependencies {
modApi("me.shedaniel.cloth:cloth-config-fabric:5.0.34") {
exclude(group: "net.fabricmc.fabric-api")
}
modImplementation 'com.electronwill.night-config:toml:3.6.0'

include group: 'com.electronwill.night-config', name: 'toml', version: '3.6.0'
include group: 'com.electronwill.night-config', name: 'core', version: '3.6.0'
}

processResources {
Expand Down
6 changes: 6 additions & 0 deletions etc/docs/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[[filters]]
priority = 10
name = "example"
targets.whitelist = [ "org.jmt.*" ]
targets.blacklist = [ "org.jmt.bad.**" ]
pools.primary.name = "LEGACY"
30 changes: 30 additions & 0 deletions etc/filters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Adding stuff to the filter

The mod should automatically identify troublesome entities and automatically create a new filter config file, but in the event that it doesn't...

Create a new `.toml` file in `config/mcmt-serdes/`. It can be named anything, but keep it simple for sanity's sake.

Paste the contents of this example config:

```toml
[[filters]]
name = "custom"
priority = 10

[filters.pools]

[filters.pools.primary]
name = "LEGACY"
params = {}

[filters.targets]
blacklist = ["com.example.Entity"]
whitelist = []

```

Change/Add the erroring entities in `filters.targets.blacklist`. This uses Java class notation, not Minecraft IDs. You can also change the name of the config to better identify open configs.

*IF AND ONLY IF YOU'RE USING THE NEW SERIALIZATION PATCH:*

You can choose a pool in `filters.pools.primary.name` between `LEGACY` (multithreaded with a chunk look to prevent race conditions nearby) or `SINGLE` (runs single-threaded before all other multithreaded entites)
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.13.2

# Mod Properties
mod_version = 1.0.4
mod_version = 1.1.0
maven_group = net.himeki
archives_base_name = mcmtfabric

Expand Down
184 changes: 184 additions & 0 deletions src/main/java/net/himeki/mcmtfabric/DebugHookTerminator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package net.himeki.mcmtfabric;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BooleanSupplier;

import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.ChunkSerializer;
import net.minecraft.world.biome.source.BiomeArray;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.biome.source.FixedBiomeSource;
import net.minecraft.world.chunk.ProtoChunk;
import net.minecraft.world.chunk.WorldChunk;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.himeki.mcmtfabric.config.GeneralConfig;

import com.mojang.datafixers.util.Either;

/* 1.15.2 code; AKA the only thing that changed
import net.minecraft.world.biome.provider.SingleBiomeProviderSettings;
/* */

// TODO Should be renamed ChunkRepairHookTerminator (Note requres coremod edit)

import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.MutableRegistry;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkStatus;


/**
* Handles chunk forcing in scenarios where world corruption has occured
*
* @author jediminer543
*
*/
public class DebugHookTerminator {

private static final Logger LOGGER = LogManager.getLogger();

private static boolean bypassLoadTarget = false;

public static class BrokenChunkLocator {
long chunkPos;
CompletableFuture<?> maincf;
CompletableFuture<?> brokecf;
public BrokenChunkLocator(long chunkPos, CompletableFuture<?> maincf, CompletableFuture<?> brokecf) {
super();
this.chunkPos = chunkPos;
this.maincf = maincf;
this.brokecf = brokecf;
}
public long getChunkPos() {
return chunkPos;
}

}

public static List<BrokenChunkLocator> breaks = new ArrayList<>();

public static boolean isBypassLoadTarget() {
return bypassLoadTarget;
}

public static AtomicBoolean mainThreadChunkLoad = new AtomicBoolean();
public static AtomicLong mainThreadChunkLoadCount = new AtomicLong();
public static String mainThread = "Server thread";

public static void chunkLoadDrive(ServerChunkManager.MainThreadExecutor executor, BooleanSupplier isDone, ServerChunkManager scp,
CompletableFuture<Either<Chunk, ChunkHolder.Unloaded>> completableFuture, long chunkpos) {
/*
if (!GeneralConfig.enableChunkTimeout) {
bypassLoadTarget = false;
executor.driveUntil(isDone);
return;
}
*/
GeneralConfig config = MCMT.config;
int failcount = 0;
if (Thread.currentThread().getName().equals(mainThread)) {
mainThreadChunkLoadCount.set(0);
mainThreadChunkLoad.set(true);
}
while (!isDone.getAsBoolean()) {
if (!executor.runTask()) {
if(isDone.getAsBoolean()) {
if (Thread.currentThread().getName().equals(mainThread)) {
mainThreadChunkLoad.set(false);
}
break;
}
// Nothing more to execute
if (!config.enableChunkTimeout || failcount++ < config.timeoutCount) {
if (Thread.currentThread().getName().equals(mainThread)) {
mainThreadChunkLoadCount.incrementAndGet();
}
Thread.yield();
LockSupport.parkNanos("THE END IS ~~NEVER~~ LOADING", 100000L);
} else {
LOGGER.error("", new TimeoutException("Error fetching chunk " + chunkpos));
bypassLoadTarget = true;
if (config.enableTimeoutRegen || config.enableBlankReturn) {

// TODO build a 1.15 version of this
if (config.enableBlankReturn) {
/* 1.16.1 code; AKA the only thing that changed */
// Generate a new empty chunk
MutableRegistry<Biome> biomeRegistry = scp.getWorld().getRegistryManager().getMutable(Registry.BIOME_KEY);
BiomeSource bp = new FixedBiomeSource(biomeRegistry.get(0));
Chunk out = new WorldChunk(scp.getWorld(), new ChunkPos(chunkpos),
new BiomeArray(biomeRegistry, scp.getWorld(),new ChunkPos(chunkpos), bp));
// SCIENCE
completableFuture.complete(Either.left(out));
/* */
/* 1.15.2 code; AKA the only thing that changed
// Generate a new empty chunk
// Null is legal here as it's literally not used
SingleBiomeProviderSettings sbps = new SingleBiomeProviderSettings(null);
sbps.setBiome(Registry.BIOME.getOrDefault(null));
BiomeProvider bp = new SingleBiomeProvider(sbps);
Chunk out = new Chunk(scp.world, new ChunkPos(chunkpos),
new BiomeContainer(new ChunkPos(chunkpos), bp));
// SCIENCE
completableFuture.complete(Either.left(out));
/* */
} else {
try {
NbtCompound cnbt = scp.threadedAnvilChunkStorage.getNbt(new ChunkPos(chunkpos));
if (cnbt != null) {
ProtoChunk cp = ChunkSerializer.deserialize((ServerWorld) scp.getWorld(), scp.threadedAnvilChunkStorage.structureManager, scp.threadedAnvilChunkStorage.pointOfInterestStorage, new ChunkPos(chunkpos), cnbt);
completableFuture.complete(Either.left(new WorldChunk((ServerWorld) scp.getWorld(), cp, null)));
}
} catch (IOException e) {
e.printStackTrace();
}
completableFuture.complete(ChunkHolder.UNLOADED_CHUNK);
}
} else {
System.err.println(completableFuture.toString());
ChunkHolder chunkholder = scp.getChunkHolder(chunkpos);
CompletableFuture<?> firstBroke = null;
for (ChunkStatus cs : ChunkStatus.createOrderedList()) {
CompletableFuture<Either<Chunk, ChunkHolder.Unloaded>> cf = chunkholder.getFutureFor(cs);
if (cf == ChunkHolder.UNLOADED_CHUNK_FUTURE) {
System.out.println("Status: " + cs.toString() + " is not yet loaded");
} else {
System.out.println("Status: " + cs.toString() + " is " + cf.toString());
if (firstBroke == null && !cf.toString().contains("Completed normally")) {
firstBroke = cf;
}
}
}
breaks.add(new BrokenChunkLocator(chunkpos, completableFuture, firstBroke));
completableFuture.complete(Either.right(new ChunkHolder.Unloaded() {
@Override
public String toString() {
return "TIMEOUT";
}
}));
}
}
}
}
}

public static void checkNull(Object o) {
if (o == null) {
System.out.println("Null warning:");
new Throwable("Null trace").printStackTrace();
}
}
}
5 changes: 4 additions & 1 deletion src/main/java/net/himeki/mcmtfabric/MCMT.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
import net.himeki.mcmtfabric.commands.ConfigCommand;
import net.himeki.mcmtfabric.commands.StatsCommand;
import net.himeki.mcmtfabric.config.GeneralConfig;
import net.himeki.mcmtfabric.jmx.JMXRegistration;
import net.himeki.mcmtfabric.serdes.SerDesRegistry;
import net.minecraft.util.ActionResult;
import org.apache.logging.log4j.LogManager;
Expand All @@ -33,6 +33,9 @@ public void onInitialize() {
holder.load(); // Load again to run loadTELists() handler
config= holder.getConfig();

if (System.getProperty("jmt.mcmt.jmx") != null) {
JMXRegistration.register();
}

StatsCommand.runDataThread();
SerDesRegistry.init();
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/net/himeki/mcmtfabric/ParallelProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.himeki.mcmtfabric.serdes.SerDesHookTypes;
import net.himeki.mcmtfabric.serdes.SerDesRegistry;
import net.himeki.mcmtfabric.serdes.filter.ISerDesFilter;
import net.himeki.mcmtfabric.serdes.pools.PostExecutePool;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.PistonBlockEntity;
import net.minecraft.entity.Entity;
Expand Down Expand Up @@ -83,11 +84,14 @@ public static boolean serverExecutionThreadPatch(MinecraftServer ms) {
return isThreadPooled("MCMT", Thread.currentThread());
}

static long tickStart = 0;

public static void preTick(MinecraftServer server) {
if (p != null) {
LOGGER.warn("Multiple servers?");
return;
} else {
tickStart = System.nanoTime();
isTicking.set(true);
p = new Phaser();
p.register();
Expand Down Expand Up @@ -132,6 +136,10 @@ public static void callTick(ServerWorld serverworld, BooleanSupplier hasTimeLeft

}

public static long[] lastTickTime = new long[32];
public static int lastTickTimePos = 0;
public static int lastTickTimeFill = 0;

public static void postTick(MinecraftServer server) {
if (mcs != server) {
LOGGER.warn("Multiple servers?");
Expand All @@ -140,6 +148,17 @@ public static void postTick(MinecraftServer server) {
p.arriveAndAwaitAdvance();
isTicking.set(false);
p = null;
//PostExecute logic
Deque<Runnable> queue = PostExecutePool.POOL.getQueue();
Iterator<Runnable> qi = queue.iterator();
while (qi.hasNext()) {
Runnable r = qi.next();
r.run();
qi.remove();
}
lastTickTime[lastTickTimePos] = System.nanoTime() - tickStart;
lastTickTimePos = (lastTickTimePos+1)%lastTickTime.length;
lastTickTimeFill = Math.min(lastTickTimeFill+1, lastTickTime.length-1);
}
}

Expand Down Expand Up @@ -276,4 +295,9 @@ public static void sendQueuedBlockEvents(Deque<BlockEvent> d, ServerWorld sw) {
bed.remove();
}
}

public static boolean shouldThreadChunks() {
return MCMT.config.disableMultiChunk;
}

}
6 changes: 6 additions & 0 deletions src/main/java/net/himeki/mcmtfabric/config/GeneralConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class GeneralConfig implements ConfigData {
@Comment("Disable world post tick parallelisation")
public boolean disableWorldPostTick = false;

@Comment("Disable world parallel chunk loading")
public boolean disableMultiChunk = false;

// Entity
@Comment("Disable entity parallelisation")
public boolean disableEntity = false;
Expand Down Expand Up @@ -85,6 +88,9 @@ public class GeneralConfig implements ConfigData {
@Comment("Attempts to re-load timed out chunks; Seems to work")
public boolean enableTimeoutRegen = false;

@Comment("Simply returns a new empty chunk instead of a re-generating fully")
public boolean enableBlankReturn = false;

@Comment("Amount of workless iterations to wait before declaring a chunk load attempt as timed out\n"
+ "This is in ~100us iterations (plus minus yield time) so timeout >= timeoutCount * 100us")
public int timeoutCount = 5000;
Expand Down
Loading

0 comments on commit 08573b6

Please sign in to comment.