Shared random to world w/ thread safety fixes

This commit is contained in:
Sotr
2018-08-14 19:05:39 +08:00
parent 01c40ed0d3
commit f0d17e54e9
6 changed files with 36 additions and 11 deletions

View File

@@ -70,7 +70,7 @@ public abstract class Akari {
public static boolean isPrimaryThread(boolean assign) { public static boolean isPrimaryThread(boolean assign) {
Thread current = Thread.currentThread(); Thread current = Thread.currentThread();
return current == MinecraftServer.getServer().primaryThread || (assign ? current instanceof AssignableThread : false); return current == MinecraftServer.getServer().primaryThread || (assign ? (current.getClass() == AssignableThread.class) : false);
} }
public static final String EMPTY_STRING = ""; public static final String EMPTY_STRING = "";

View File

@@ -1,5 +1,6 @@
package io.akarin.api.internal.mixin; package io.akarin.api.internal.mixin;
public interface IMixinLockProvider { public interface IMixinWorldServer {
public Object lock(); public Object lock();
public Object rand();
} }

View File

@@ -27,7 +27,7 @@ import co.aikar.timings.MinecraftTimings;
import co.aikar.timings.TimingHandler; import co.aikar.timings.TimingHandler;
import io.akarin.api.internal.Akari; import io.akarin.api.internal.Akari;
import io.akarin.api.internal.Akari.AssignableFactory; import io.akarin.api.internal.Akari.AssignableFactory;
import io.akarin.api.internal.mixin.IMixinLockProvider; import io.akarin.api.internal.mixin.IMixinWorldServer;
import io.akarin.server.core.AkarinGlobalConfig; import io.akarin.server.core.AkarinGlobalConfig;
import io.akarin.server.core.AkarinSlackScheduler; import io.akarin.server.core.AkarinSlackScheduler;
import net.minecraft.server.BlockPosition; import net.minecraft.server.BlockPosition;
@@ -241,7 +241,7 @@ public abstract class MixinMinecraftServer {
entityWorld.timings.tickEntities.startTiming(); entityWorld.timings.tickEntities.startTiming();
WorldServer fEntityWorld = entityWorld; WorldServer fEntityWorld = entityWorld;
Akari.STAGE_ENTITY_TICK.submit(() -> { Akari.STAGE_ENTITY_TICK.submit(() -> {
synchronized (((IMixinLockProvider) fEntityWorld).lock()) { synchronized (((IMixinWorldServer) fEntityWorld).lock()) {
tickEntities(fEntityWorld); tickEntities(fEntityWorld);
fEntityWorld.getTracker().updatePlayers(); fEntityWorld.getTracker().updatePlayers();
fEntityWorld.explosionDensityCache.clear(); // Paper - Optimize explosions fEntityWorld.explosionDensityCache.clear(); // Paper - Optimize explosions
@@ -253,7 +253,7 @@ public abstract class MixinMinecraftServer {
WorldServer world = worlds.get(interlaceWorld); WorldServer world = worlds.get(interlaceWorld);
world.timings.doTick.startTiming(); world.timings.doTick.startTiming();
Akari.STAGE_WORLD_TICK.submit(() -> { Akari.STAGE_WORLD_TICK.submit(() -> {
synchronized (((IMixinLockProvider) world).lock()) { synchronized (((IMixinWorldServer) world).lock()) {
tickWorld(world); tickWorld(world);
} }
}, world); }, world);
@@ -262,7 +262,7 @@ public abstract class MixinMinecraftServer {
WorldServer primaryWorld = worlds.get(0); WorldServer primaryWorld = worlds.get(0);
primaryWorld.timings.doTick.startTiming(); primaryWorld.timings.doTick.startTiming();
synchronized (((IMixinLockProvider) primaryWorld).lock()) { synchronized (((IMixinWorldServer) primaryWorld).lock()) {
tickWorld(primaryWorld); tickWorld(primaryWorld);
} }
primaryWorld.timings.doTick.stopTiming(); primaryWorld.timings.doTick.stopTiming();

View File

@@ -1,15 +1,37 @@
package io.akarin.server.mixin.core; package io.akarin.server.mixin.core;
import java.util.Random;
import org.apache.logging.log4j.LogManager;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import io.akarin.api.internal.mixin.IMixinLockProvider; import io.akarin.api.internal.mixin.IMixinWorldServer;
import net.minecraft.server.WorldServer; import net.minecraft.server.WorldServer;
@Mixin(value = WorldServer.class, remap = false) @Mixin(value = WorldServer.class, remap = false)
public abstract class MixinWorldServer implements IMixinLockProvider { public abstract class MixinWorldServer implements IMixinWorldServer {
private final Object tickLock = new Object(); private final Object tickLock = new Object();
@Override @Override
public Object lock() { public Object lock() {
return tickLock; return tickLock;
} }
private final Random sharedRandom = new io.akarin.api.internal.utils.random.LightRandom() {
private static final long serialVersionUID = 1L;
private boolean locked = false;
@Override
public synchronized void setSeed(long seed) {
if (locked) {
LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable());
} else {
super.setSeed(seed);
locked = true;
}
}
};
@Override
public Random rand() {
return sharedRandom;
}
} }

View File

@@ -27,6 +27,8 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Vehicle; import org.bukkit.entity.Vehicle;
import co.aikar.timings.MinecraftTimings; // Paper import co.aikar.timings.MinecraftTimings; // Paper
import co.aikar.timings.Timing; // Paper import co.aikar.timings.Timing; // Paper
import io.akarin.api.internal.mixin.IMixinWorldServer;
import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; import org.bukkit.event.vehicle.VehicleBlockCollisionEvent;
@@ -51,7 +53,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
// CraftBukkit start // CraftBukkit start
private static final int CURRENT_LEVEL = 2; private static final int CURRENT_LEVEL = 2;
// Paper start // Paper start
public static Random SHARED_RANDOM = new io.akarin.api.internal.utils.random.LightRandom() { // Akarin - LightRNG public static Random SHARED_RANDOM = new java.util.Random() {
private boolean locked = false; private boolean locked = false;
@Override @Override
public synchronized void setSeed(long seed) { public synchronized void setSeed(long seed) {
@@ -208,7 +210,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
this.length = 1.8F; this.length = 1.8F;
this.ax = 1; this.ax = 1;
this.ay = 1.0F; this.ay = 1.0F;
this.random = SHARED_RANDOM; // Paper this.random = ((IMixinWorldServer) world).rand(); // Paper // Akarin
this.fireTicks = -this.getMaxFireTicks(); this.fireTicks = -this.getMaxFireTicks();
this.justCreated = true; this.justCreated = true;
this.uniqueID = MathHelper.a(this.random); this.uniqueID = MathHelper.a(this.random);

View File

@@ -9,7 +9,7 @@ import javax.annotation.Nullable;
/** /**
* Akarin Changes Note * Akarin Changes Note
* 1) FastBitSet for faster access (performance) * 1) BitSet for faster access (performance)
*/ */
public class RegistryID<K> implements Registry { public class RegistryID<K> implements Registry {