mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-01 05:58:00 +01:00
Rework of the thread provider + ConnectionManager#getPlayer for UUID
This commit is contained in:
parent
118ed220e3
commit
a38a143bba
@ -149,9 +149,10 @@ public class PlayerInit {
|
||||
p.teleport(player.getPosition());
|
||||
}*/
|
||||
|
||||
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
|
||||
chickenCreature.setInstance(player.getInstance());
|
||||
chickenCreature.setTarget(player);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
|
||||
chickenCreature.setInstance(player.getInstance());
|
||||
}
|
||||
|
||||
/*EntityZombie zombie = new EntityZombie(player.getPosition());
|
||||
zombie.setAttribute(Attribute.MOVEMENT_SPEED, 0.25f);
|
||||
|
@ -1,7 +1,7 @@
|
||||
package fr.themode.demo.entity;
|
||||
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.entity.ai.goal.FollowTargetGoal;
|
||||
import net.minestom.server.entity.ai.goal.RandomStrollGoal;
|
||||
import net.minestom.server.entity.ai.target.PlayerTarget;
|
||||
import net.minestom.server.entity.type.EntityChicken;
|
||||
import net.minestom.server.utils.Position;
|
||||
@ -12,8 +12,8 @@ public class ChickenCreature extends EntityChicken {
|
||||
super(defaultPosition);
|
||||
|
||||
//goalSelectors.add(new DoNothingGoal(this, 500, 0.1f));
|
||||
//goalSelectors.add(new RandomStrollGoal(this, 2));
|
||||
goalSelectors.add(new FollowTargetGoal(this));
|
||||
goalSelectors.add(new RandomStrollGoal(this, 2));
|
||||
//goalSelectors.add(new FollowTargetGoal(this));
|
||||
|
||||
|
||||
targetSelectors.add(new PlayerTarget(this, 15));
|
||||
|
@ -288,6 +288,10 @@ public class MinecraftServer {
|
||||
return tagManager;
|
||||
}
|
||||
|
||||
public static UpdateManager getUpdateManager() {
|
||||
return updateManager;
|
||||
}
|
||||
|
||||
public void start(String address, int port, ResponseDataConsumer responseDataConsumer) {
|
||||
LOGGER.info("Starting Minestom server.");
|
||||
MinecraftServer.responseDataConsumer = responseDataConsumer;
|
||||
|
@ -4,12 +4,11 @@ import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.entity.EntityManager;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.packet.server.play.KeepAlivePacket;
|
||||
import net.minestom.server.thread.SingleThreadProvider;
|
||||
import net.minestom.server.thread.PerInstanceThreadProvider;
|
||||
import net.minestom.server.thread.ThreadProvider;
|
||||
import net.minestom.server.utils.thread.MinestomThread;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
@ -27,8 +26,7 @@ public final class UpdateManager {
|
||||
private ThreadProvider threadProvider;
|
||||
|
||||
{
|
||||
threadProvider = new SingleThreadProvider();
|
||||
//threadProvider = new PerInstanceThreadProvider();
|
||||
threadProvider = new PerInstanceThreadProvider();
|
||||
//threadProvider = new PerGroupChunkProvider();
|
||||
}
|
||||
|
||||
@ -49,24 +47,15 @@ public final class UpdateManager {
|
||||
long currentTime;
|
||||
while (!stopRequested) {
|
||||
currentTime = System.nanoTime();
|
||||
final long time = System.currentTimeMillis();
|
||||
|
||||
// Server tick
|
||||
//long testTime = System.nanoTime();
|
||||
threadProvider.start();
|
||||
for (Instance instance : instanceManager.getInstances()) {
|
||||
for (Chunk chunk : instance.getChunks()) {
|
||||
threadProvider.linkThread(instance, chunk);
|
||||
}
|
||||
}
|
||||
threadProvider.end();
|
||||
threadProvider.update();
|
||||
//System.out.println("time: " + (System.nanoTime() - testTime));
|
||||
threadProvider.update(time);
|
||||
|
||||
// Waiting players update
|
||||
entityManager.updateWaitingPlayers();
|
||||
|
||||
// Keep Alive Handling
|
||||
final long time = System.currentTimeMillis();
|
||||
final KeepAlivePacket keepAlivePacket = new KeepAlivePacket(time);
|
||||
for (Player player : connectionManager.getOnlinePlayers()) {
|
||||
final long lastKeepAlive = time - player.getLastKeepAlive();
|
||||
@ -112,6 +101,33 @@ public final class UpdateManager {
|
||||
this.threadProvider = threadProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal the thread provider that a chunk has been loaded
|
||||
*
|
||||
* @param instance the instance of the chunk
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
*/
|
||||
public void signalChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
if (this.threadProvider == null)
|
||||
return;
|
||||
this.threadProvider.onChunkLoad(instance, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal the thread provider that a chunk has been unloaded
|
||||
*
|
||||
* @param instance the instance of the chunk
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
*/
|
||||
public void signalChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
if (this.threadProvider == null)
|
||||
return;
|
||||
this.threadProvider.onChunkUnload(instance, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
|
||||
public void stop() {
|
||||
stopRequested = true;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.UpdateManager;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.data.DataContainer;
|
||||
import net.minestom.server.entity.*;
|
||||
@ -48,6 +49,7 @@ import java.util.function.Consumer;
|
||||
public abstract class Instance implements BlockModifier, EventHandler, DataContainer {
|
||||
|
||||
protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
||||
protected static final UpdateManager UPDATE_MANAGER = MinecraftServer.getUpdateManager();
|
||||
|
||||
private DimensionType dimensionType;
|
||||
|
||||
|
@ -342,6 +342,8 @@ public class InstanceContainer extends Instance {
|
||||
this.chunkEntities.remove(index);
|
||||
|
||||
chunk.unload();
|
||||
|
||||
UPDATE_MANAGER.signalChunkUnload(this, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -428,6 +430,7 @@ public class InstanceContainer extends Instance {
|
||||
final boolean loaded = chunkLoader.loadChunk(this, chunkX, chunkZ, chunk -> {
|
||||
cacheChunk(chunk);
|
||||
callChunkLoadEvent(chunkX, chunkZ);
|
||||
UPDATE_MANAGER.signalChunkLoad(this, chunkX, chunkZ);
|
||||
if (callback != null)
|
||||
callback.accept(chunk);
|
||||
});
|
||||
@ -459,6 +462,7 @@ public class InstanceContainer extends Instance {
|
||||
callback.accept(chunk);
|
||||
}
|
||||
|
||||
UPDATE_MANAGER.signalChunkLoad(this, chunkX, chunkZ);
|
||||
callChunkLoadEvent(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,22 @@ public final class ConnectionManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first player which validate {@link UUID#equals(Object)}
|
||||
* <p>
|
||||
* This can cause issue if two or more players have the same UUID
|
||||
*
|
||||
* @param uuid the player UUID
|
||||
* @return the first player who validate the UUID condition
|
||||
*/
|
||||
public Player getPlayer(UUID uuid) {
|
||||
for (Player player : getOnlinePlayers()) {
|
||||
if (player.getUuid().equals(uuid))
|
||||
return player;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a rich message to all online players who validate the condition {@code condition}
|
||||
*
|
||||
|
@ -2,6 +2,7 @@ package net.minestom.server.thread;
|
||||
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -13,66 +14,66 @@ import java.util.Set;
|
||||
* <p>
|
||||
* (1 chunks group = 1 thread execution)
|
||||
*/
|
||||
// FIXME: unusable at the moment, too much overhead because groups need to be created every tick
|
||||
// Should have a callback for when a chunk is loaded and unloaded, so groups are updated only once
|
||||
// TODO
|
||||
public class PerGroupChunkProvider extends ThreadProvider {
|
||||
|
||||
/**
|
||||
* Here are stored all cached chunks waiting for a ChunkGroup
|
||||
*/
|
||||
private Map<Chunk, Set<Chunk>> cachedChunks = new HashMap<>();
|
||||
private Map<Chunk, Set<ChunkCoordinate>> cachedChunks = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Used to know to which instance is linked a Set of chunks
|
||||
*/
|
||||
private Map<Set<Chunk>, Instance> instanceMap = new HashMap<>();
|
||||
private Map<Set<ChunkCoordinate>, Instance> instanceMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.cachedChunks.clear();
|
||||
this.instanceMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkThread(Instance instance, Chunk chunk) {
|
||||
startChunkQuery(instance, chunk.getChunkX(), chunk.getChunkZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
// The time of the tick
|
||||
final long time = System.currentTimeMillis();
|
||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(long time) {
|
||||
|
||||
// Set of already-updated instances
|
||||
final Set<Instance> updatedInstance = new HashSet<>();
|
||||
|
||||
// Update all the chunks
|
||||
for (Map.Entry<Set<Chunk>, Instance> entry : instanceMap.entrySet()) {
|
||||
Set<Chunk> chunks = entry.getKey();
|
||||
for (Map.Entry<Set<ChunkCoordinate>, Instance> entry : instanceMap.entrySet()) {
|
||||
Set<ChunkCoordinate> chunks = entry.getKey();
|
||||
Instance instance = entry.getValue();
|
||||
|
||||
final boolean updateInstance = updatedInstance.add(instance);
|
||||
pool.execute(() -> {
|
||||
/*if (updateInstance) {
|
||||
if (updateInstance) {
|
||||
updateInstance(instance, time);
|
||||
}
|
||||
|
||||
for (Chunk chunk : chunks) {
|
||||
for (ChunkCoordinate chunkCoordinate : chunks) {
|
||||
final Chunk chunk = instance.getChunk(chunkCoordinate.chunkX, chunkCoordinate.chunkZ);
|
||||
if (ChunkUtils.isChunkUnloaded(chunk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
updateChunk(instance, chunk, time);
|
||||
|
||||
updateEntities(instance, chunk, time);
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void linkThread(Instance instance, Chunk chunk) {
|
||||
startChunkQuery(instance, chunk.getChunkX(), chunk.getChunkZ());
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Check the four chunk neighbors (up/down/left/right)
|
||||
* and add them to the cache list
|
||||
@ -81,7 +82,7 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
*/
|
||||
private void startChunkQuery(Instance instance, int chunkX, int chunkZ) {
|
||||
/*private void startChunkQuery(Instance instance, int chunkX, int chunkZ) {
|
||||
// Constants used to loop through the neighbors
|
||||
final int[] posX = {1, 0, -1};
|
||||
final int[] posZ = {1, 0, -1};
|
||||
@ -124,6 +125,5 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
this.cachedChunks.put(cachedChunk, cache);
|
||||
}
|
||||
this.instanceMap.put(cache, instance);
|
||||
}
|
||||
|
||||
}*/
|
||||
}
|
||||
|
@ -2,96 +2,56 @@ package net.minestom.server.thread;
|
||||
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Separate work between instance (1 instance = 1 thread execution)
|
||||
*/
|
||||
public class PerInstanceThreadProvider extends ThreadProvider {
|
||||
|
||||
private Map<Instance, GroupedInstanceChunk> groupMap = new HashMap<>();
|
||||
private Map<Instance, Set<ChunkCoordinate>> instanceChunkMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.groupMap.clear();
|
||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
Set<ChunkCoordinate> chunkCoordinates = instanceChunkMap.computeIfAbsent(instance, inst -> new HashSet<>());
|
||||
chunkCoordinates.add(new ChunkCoordinate(chunkX, chunkZ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkThread(Instance instance, Chunk chunk) {
|
||||
InstanceChunk instanceChunk = new InstanceChunk(instance, chunk);
|
||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
Set<ChunkCoordinate> chunkCoordinates = instanceChunkMap.computeIfAbsent(instance, inst -> new HashSet<>());
|
||||
|
||||
GroupedInstanceChunk groupedInstanceChunk = groupMap.computeIfAbsent(instance, inst -> new GroupedInstanceChunk());
|
||||
groupedInstanceChunk.instanceChunks.add(instanceChunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
chunkCoordinates.removeIf(chunkCoordinate -> chunkCoordinate.chunkX == chunkX &&
|
||||
chunkCoordinate.chunkZ == chunkZ);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
final long time = System.currentTimeMillis();
|
||||
|
||||
for (Map.Entry<Instance, GroupedInstanceChunk> entry : groupMap.entrySet()) {
|
||||
public void update(long time) {
|
||||
for (Map.Entry<Instance, Set<ChunkCoordinate>> entry : instanceChunkMap.entrySet()) {
|
||||
final Instance instance = entry.getKey();
|
||||
final GroupedInstanceChunk groupedInstanceChunk = entry.getValue();
|
||||
final Set<ChunkCoordinate> chunkCoordinates = entry.getValue();
|
||||
|
||||
pool.execute(() -> {
|
||||
updateInstance(instance, time);
|
||||
|
||||
for (InstanceChunk instanceChunk : groupedInstanceChunk.instanceChunks) {
|
||||
Chunk chunk = instanceChunk.getChunk();
|
||||
for (ChunkCoordinate chunkCoordinate : chunkCoordinates) {
|
||||
final Chunk chunk = instance.getChunk(chunkCoordinate.chunkX, chunkCoordinate.chunkZ);
|
||||
if (ChunkUtils.isChunkUnloaded(chunk))
|
||||
continue;
|
||||
|
||||
updateChunk(instance, chunk, time);
|
||||
|
||||
updateEntities(instance, chunk, time);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains a list of {@link InstanceChunk}
|
||||
*/
|
||||
private static class GroupedInstanceChunk {
|
||||
private List<InstanceChunk> instanceChunks = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains both a chunk and its instance
|
||||
*/
|
||||
private static class InstanceChunk {
|
||||
|
||||
private Instance instance;
|
||||
private Chunk chunk;
|
||||
|
||||
protected InstanceChunk(Instance instance, Chunk chunk) {
|
||||
this.instance = instance;
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
public Instance getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Chunk getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
InstanceChunk that = (InstanceChunk) o;
|
||||
return Objects.equals(instance, that.instance) &&
|
||||
Objects.equals(chunk, that.chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(instance, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
package net.minestom.server.thread;
|
||||
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class SingleThreadProvider extends ThreadProvider {
|
||||
|
||||
private Set<Instance> instances = new HashSet<>();
|
||||
private long time;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.instances.clear();
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkThread(Instance instance, Chunk chunk) {
|
||||
|
||||
if (instances.add(instance)) {
|
||||
updateInstance(instance, time);
|
||||
}
|
||||
|
||||
updateChunk(instance, chunk, time);
|
||||
|
||||
updateEntities(instance, chunk, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
}
|
||||
}
|
@ -31,27 +31,29 @@ public abstract class ThreadProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to prepare the thread provider, to provide threads for the next server tick
|
||||
*/
|
||||
public abstract void start();
|
||||
|
||||
/**
|
||||
* Assign a thread to a chunk, create one if none is defined
|
||||
* Called when a chunk is loaded
|
||||
*
|
||||
* @param instance the instance where the chunk is
|
||||
* @param chunk the chunk which should get an assigned thread
|
||||
* @param instance the instance of the chunk
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
*/
|
||||
public abstract void linkThread(Instance instance, Chunk chunk);
|
||||
public abstract void onChunkLoad(Instance instance, int chunkX, int chunkZ);
|
||||
|
||||
/**
|
||||
* Inform the server that all chunks have been assigned to a thread
|
||||
* Called when a chunk is unloaded
|
||||
*
|
||||
* @param instance the instance of the chunk
|
||||
* @param chunkX the chunk X
|
||||
* @param chunkZ the chunk Z
|
||||
*/
|
||||
public abstract void end();
|
||||
public abstract void onChunkUnload(Instance instance, int chunkX, int chunkZ);
|
||||
|
||||
/**
|
||||
* Perform a server tick for all chunks based on their linked thread
|
||||
*
|
||||
* @param time the update time in milliseconds
|
||||
*/
|
||||
public abstract void update();
|
||||
public abstract void update(long time);
|
||||
|
||||
/**
|
||||
* Get the current size of the thread pool
|
||||
@ -180,4 +182,13 @@ public abstract class ThreadProvider {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ChunkCoordinate {
|
||||
public int chunkX, chunkZ;
|
||||
|
||||
public ChunkCoordinate(int chunkX, int chunkZ) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user