This commit is contained in:
Felix Cravic 2020-08-07 09:14:50 +02:00
parent 12ccbfc80e
commit 45fd0dc22a
23 changed files with 119 additions and 70 deletions

View File

@ -4,7 +4,6 @@ import fr.themode.demo.entity.ChickenCreature;
import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.demo.generator.NoiseTestGenerator;
import net.minestom.server.MinecraftServer;
import net.minestom.server.advancements.*;
import net.minestom.server.benchmark.BenchmarkManager;
import net.minestom.server.benchmark.ThreadResult;
import net.minestom.server.chat.ChatColor;
@ -69,7 +68,6 @@ public class PlayerInit {
end.loadChunk(x, z);
}
inventory = new Inventory(InventoryType.CHEST_1_ROW, "Test inventory");
inventory.addInventoryCondition((p, slot, clickType, inventoryConditionResult) -> {
p.sendMessage("click type inventory: " + clickType);
@ -149,10 +147,8 @@ public class PlayerInit {
p.teleport(player.getPosition());
}*/
for (int i = 0; i < 100; i++) {
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
chickenCreature.setInstance(player.getInstance());
}
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
chickenCreature.setInstance(player.getInstance());
/*EntityZombie zombie = new EntityZombie(player.getPosition());
zombie.setAttribute(Attribute.MOVEMENT_SPEED, 0.25f);
@ -228,7 +224,7 @@ public class PlayerInit {
scoreboard.setTitle("test");*/
{
AdvancementManager advancementManager = MinecraftServer.getAdvancementManager();
/*AdvancementManager advancementManager = MinecraftServer.getAdvancementManager();
AdvancementRoot root = new AdvancementRoot(ColoredText.of("title"), ColoredText.of(ChatColor.BLUE + "description"),
Material.APPLE, FrameType.TASK, 0, 0,
"minecraft:textures/block/red_wool.png");
@ -247,9 +243,7 @@ public class PlayerInit {
ColoredText.of("description of the advancement"),
Material.GOLD_BLOCK, FrameType.CHALLENGE, 3, 0)
.showToast(true).setHidden(false);
tab.createAdvancement("second2", advancement2, root);
//player.getPlayerConnection().sendPacket(tab.removePacket());
tab.createAdvancement("second2", advancement2, root);*/
}
});

View File

@ -192,7 +192,7 @@ public class MinecraftServer {
/**
* Change the server brand name, update the name to all connected players
*
* @param brandName
* @param brandName the server brand name
*/
public static void setBrandName(String brandName) {
Check.notNull(brandName, "The brand name cannot be null");

View File

@ -5,7 +5,6 @@ import net.minestom.server.chat.ColoredText;
import net.minestom.server.entity.EntityManager;
import net.minestom.server.entity.Player;
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.PerGroupChunkProvider;
@ -19,6 +18,7 @@ public final class UpdateManager {
private static final long KEEP_ALIVE_DELAY = 10_000;
private static final long KEEP_ALIVE_KICK = 30_000;
private static final ColoredText TIMEOUT_TEXT = ColoredText.of(ChatColor.RED + "Timeout");
private ExecutorService mainUpdate = new MinestomThread(1, MinecraftServer.THREAD_NAME_MAIN_UPDATE);
private boolean stopRequested;
@ -36,12 +36,14 @@ public final class UpdateManager {
protected UpdateManager() {
}
public void start() {
/**
* Start the server loop in the update thread
*/
protected void start() {
mainUpdate.execute(() -> {
final ConnectionManager connectionManager = MinecraftServer.getConnectionManager();
final EntityManager entityManager = MinecraftServer.getEntityManager();
final InstanceManager instanceManager = MinecraftServer.getInstanceManager();
final long tickDistance = MinecraftServer.TICK_MS * 1000000;
long currentTime;
@ -49,10 +51,10 @@ public final class UpdateManager {
currentTime = System.nanoTime();
final long time = System.currentTimeMillis();
// Server tick
// Server tick (instance/chunk/entity)
threadProvider.update(time);
// Waiting players update
// Waiting players update (newly connected waiting to get into the server)
entityManager.updateWaitingPlayers();
// Keep Alive Handling
@ -63,7 +65,7 @@ public final class UpdateManager {
player.refreshKeepAlive(time);
player.getPlayerConnection().sendPacket(keepAlivePacket);
} else if (lastKeepAlive >= KEEP_ALIVE_KICK) {
player.kick(ColoredText.of(ChatColor.RED + "Timeout"));
player.kick(TIMEOUT_TEXT);
}
}
@ -127,7 +129,9 @@ public final class UpdateManager {
this.threadProvider.onChunkUnload(instance, chunkX, chunkZ);
}
/**
* Stop the server loop
*/
public void stop() {
stopRequested = true;
}

View File

@ -121,13 +121,13 @@ public class CollisionUtils {
}
/**
* Steps once (by a length of 1 block) on the given axis. Returns false if this method encountered a collision
* Steps once (by a length of 1 block) on the given axis.
*
* @param instance instance to get blocks from
* @param axis the axis to move along
* @param cornersCopy the corners of the bounding box to consider (mutable)
* @param cornerPositions the corners, converted to BlockPosition (mutable)
* @return
* @return false if this method encountered a collision
*/
private static boolean stepOnce(Instance instance, Vector axis, float amount, Vector[] cornersCopy, BlockPosition[] cornerPositions) {
final float sign = Math.signum(amount);

View File

@ -68,8 +68,8 @@ public class Data {
/**
* Get if the data has a key
*
* @param key
* @return true if the data contains the key, false otherwise
* @param key the key to check
* @return true if the data contains the key
*/
public boolean hasKey(String key) {
return data.containsKey(key);

View File

@ -1125,8 +1125,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
/**
* Trigger {@link #remove()} after the specified time
*
* @param delay
* @param timeUnit to determine the delay unit
* @param delay the time before removing the entity
* @param timeUnit the unit of the delay
*/
public void scheduleRemove(long delay, TimeUnit timeUnit) {
delay = timeUnit.toMilliseconds(delay);

View File

@ -234,8 +234,8 @@ public class ItemEntity extends ObjectEntity {
/**
* Set the pickup delay of the ItemEntity
*
* @param delay
* @param timeUnit
* @param delay the pickup delay
* @param timeUnit the unit of the delay
*/
public void setPickupDelay(long delay, TimeUnit timeUnit) {
this.pickupDelay = timeUnit.toMilliseconds(delay);

View File

@ -1669,7 +1669,7 @@ public class Player extends LivingEntity implements CommandSender {
* <p>
* WARNING: this has nothing to do with {@link CustomBlock#getBreakDelay(Player, BlockPosition)}
*
* @param instantBreak
* @param instantBreak true to allow instant break
*/
public void setInstantBreak(boolean instantBreak) {
this.instantBreak = instantBreak;

View File

@ -27,8 +27,10 @@ public interface EventHandler {
<E extends Event> void removeEventCallback(Class<E> eventClass, EventCallback<E> eventCallback);
/**
* @param eventClass
* @param <E>
* Get the event callbacks of a specific event type
*
* @param eventClass the event class
* @param <E> the event type
* @return all event callbacks for the specified type {@code eventClass}
*/
<E extends Event> List<EventCallback> getEventCallbacks(Class<E> eventClass);

View File

@ -76,7 +76,7 @@ public class PlayerBlockPlaceEvent extends CancellableEvent {
* WARNING: this does not change the visual block id, see {@link #setBlockId(short)}
* or {@link #setCustomBlock(short)}
*
* @param customBlockId
* @param customBlockId the custom block id
*/
public void setCustomBlockId(short customBlockId) {
this.customBlockId = customBlockId;

View File

@ -4,13 +4,14 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.minestom.server.network.packet.server.play.TagsPacket;
import net.minestom.server.registry.ResourceGatherer;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.NamespaceID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -177,17 +178,19 @@ public class TagManager {
/**
* Loads a tag with the given name. This method attempts to read from "data/&lt;name.domain&gt;/tags/&lt;tagType&gt;/&lt;name.path&gt;.json" if the given name is not already present in cache
*
* @param name
* @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants)
* @return
* @throws FileNotFoundException if the file does not exist
*/
public Tag load(NamespaceID name, String tagType) throws FileNotFoundException {
return load(name, tagType, () -> new FileReader(new File(ResourceGatherer.DATA_FOLDER, "data/"+name.getDomain()+"/tags/"+tagType+"/"+name.getPath()+".json")));
return load(name, tagType, () -> new FileReader(new File(ResourceGatherer.DATA_FOLDER, "data/" + name.getDomain() + "/tags/" + tagType + "/" + name.getPath() + ".json")));
}
/**
* Loads a tag with the given name. This method attempts to read from 'reader' if the given name is not already present in cache
*
* @param name
* @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants)
* @param reader
@ -199,8 +202,9 @@ public class TagManager {
/**
* Loads a tag with the given name. This method reads from 'reader'. This will override the previous tag
*
* @param name
* @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants)
* @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants)
* @param readerSupplier
* @return
*/
@ -213,8 +217,9 @@ public class TagManager {
/**
* Loads a tag with the given name. This method attempts to read from 'reader' if the given name is not already present in cache
*
* @param name
* @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants)
* @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants)
* @param readerSupplier
* @return
*/
@ -240,10 +245,11 @@ public class TagManager {
/**
* Adds the required tags for the game to function correctly
*
* @param tags the packet to add the tags to
*/
public void addRequiredTagsToPacket(TagsPacket tags) {
for(RequiredTag requiredTag : requiredTags) {
for (RequiredTag requiredTag : requiredTags) {
Tag tag = silentLoad(requiredTag.getName(), requiredTag.getType().name().toLowerCase());
switch (requiredTag.getType()) {
case BLOCKS:
@ -267,6 +273,7 @@ public class TagManager {
/**
* Adds a required tag to send to players when they connect
*
* @param type type of tag to send. Required so the client knows its use
* @param name the name of the tag to load
*/

View File

@ -30,7 +30,7 @@ public interface IChunkLoader {
/**
* Does this ChunkLoader allow for multi-threaded saving of chunks?
*
* @return
* @return true if the chunk loader supports parallel saving
*/
default boolean supportsParallelSaving() {
return false;
@ -39,7 +39,7 @@ public interface IChunkLoader {
/**
* Does this ChunkLoader allow for multi-threaded loading of chunks?
*
* @return
* @return true if the chunk loader supports parallel loading
*/
default boolean supportsParallelLoading() {
return false;

View File

@ -919,10 +919,10 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
* Creates an explosion at the given position with the given strength.
* The algorithm used to compute damages is provided by {@link #getExplosionSupplier()}.
*
* @param centerX
* @param centerY
* @param centerZ
* @param strength
* @param centerX the center X
* @param centerY the center Y
* @param centerZ the center Z
* @param strength the strength of the explosion
* @throws IllegalStateException If no {@link ExplosionSupplier} was supplied
*/
public void explode(float centerX, float centerY, float centerZ, float strength) {

View File

@ -142,8 +142,8 @@ public class InstanceContainer extends Instance {
/**
* Has this block already changed since last update? Prevents StackOverflow with blocks trying to modify their position in onDestroy or onPlace
*
* @param blockPosition
* @param blockId
* @param blockPosition the block position
* @param blockId the block id
* @return
*/
private boolean isAlreadyChanged(BlockPosition blockPosition, short blockId) {

View File

@ -129,7 +129,7 @@ public abstract class CustomBlock {
/**
* Defines custom behaviour for entities touching this block.
*
* @param instance
* @param instance the instance
* @param position the position at which the block is
* @param touching the entity currently touching the block
*/
@ -220,7 +220,7 @@ public abstract class CustomBlock {
/**
* Called when an explosion wants to destroy this block.
*
* @param instance
* @param instance the instance
* @param lootTableArguments arguments used in the loot table loot generation
* @return 'true' if the explosion should happen on this block, 'false' to cancel the destruction.
* Returning true does NOT block the explosion rays, ie it does not change the block explosion resistance
@ -232,7 +232,7 @@ public abstract class CustomBlock {
/**
* Return the loot table associated to this block. Return null to use vanilla behavior
*
* @param tableManager
* @param tableManager the loot table manager
* @return the loot table associated to this block
*/
public LootTable getLootTable(LootTableManager tableManager) {

View File

@ -66,8 +66,8 @@ public class StorageManager {
/**
* Used to know if the specified folder already exist or not
*
* @param folderPath
* @param storageSystem
* @param folderPath the folder path
* @param storageSystem the storage system to use
* @return true if the folder exists, false otherwise
*/
public boolean folderExists(String folderPath, StorageSystem storageSystem) {
@ -77,8 +77,8 @@ public class StorageManager {
/**
* Call {@link #folderExists(String, StorageSystem)} with the default StorageSystem
*
* @param folderPath
* @return
* @param folderPath the folder path
* @return true if the folder exists
*/
public boolean folderExists(String folderPath) {
return folderExists(folderPath, defaultStorageSystemSupplier.get());
@ -93,6 +93,11 @@ public class StorageManager {
return Collections.unmodifiableCollection(folderMap.values());
}
/**
* Define the default storage system used for {@link StorageFolder}
*
* @param storageSystemSupplier the supplier called to get the default {@link StorageSystem}
*/
public void defineDefaultStorageSystem(Supplier<StorageSystem> storageSystemSupplier) {
if (this.defaultStorageSystemSupplier != null) {
LOGGER.warn("The default storage-system has been changed. This could lead to issues!");
@ -100,6 +105,11 @@ public class StorageManager {
this.defaultStorageSystemSupplier = storageSystemSupplier;
}
/**
* Get if the default storage system is set
*
* @return true if a default storage system is set
*/
public boolean isDefaultStorageSystemDefined() {
return defaultStorageSystemSupplier != null;
}

View File

@ -1,10 +1,16 @@
package net.minestom.server.storage;
/**
* Represent a way of storing data
* It works by using keys and values assigned to each one
*/
public interface StorageSystem {
/**
* @param folderPath
* @return true if the folder exists, false otherwise
* Get if the folder exists
*
* @param folderPath the folder path
* @return true if the folder exists
*/
boolean exists(String folderPath);
@ -17,7 +23,9 @@ public interface StorageSystem {
void open(String folderPath, StorageOptions storageOptions);
/**
* @param key
* Get the data associated to a key
*
* @param key the key to retrieve
* @return the retrieved data
*/
byte[] get(String key);
@ -25,15 +33,15 @@ public interface StorageSystem {
/**
* Set the specified data to the defined key
*
* @param key
* @param data
* @param key the key of the data
* @param data the data
*/
void set(String key, byte[] data);
/**
* Delete the specified key from the database
*
* @param key
* @param key the key to delete
*/
void delete(String key);

View File

@ -25,7 +25,6 @@ public class PerGroupChunkProvider extends ThreadProvider {
@Override
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
Map<ChunkCoordinate, Set<ChunkCoordinate>> chunksGroupMap = getChunksGroupMap(instance);
Map<Set<ChunkCoordinate>, Instance> instanceMap = getInstanceMap(instance);
@ -56,10 +55,13 @@ public class PerGroupChunkProvider extends ThreadProvider {
return;
}
// Represent the merged group of all the neighbours
Set<ChunkCoordinate> finalGroup = new HashSet<>();
// Add the newly loaded chunk to the group
finalGroup.add(new ChunkCoordinate(chunkX, chunkZ));
// Add all the neighbours groups to the final one
for (Set<ChunkCoordinate> chunkCoordinates : neighboursGroups) {
finalGroup.addAll(chunkCoordinates);
}
@ -80,11 +82,13 @@ public class PerGroupChunkProvider extends ThreadProvider {
final ChunkCoordinate chunkCoordinate = new ChunkCoordinate(chunkX, chunkZ);
if (chunksGroupMap.containsKey(chunkCoordinate)) {
// The unloaded chunk is part of a group, remove it from the group
Set<ChunkCoordinate> chunkCoordinates = chunksGroupMap.get(chunkCoordinate);
chunkCoordinates.remove(chunkCoordinate);
chunksGroupMap.remove(chunkCoordinate);
if (chunkCoordinates.isEmpty()) {
// The chunk group is empty, remove it entirely
instanceMap.entrySet().removeIf(entry -> entry.getKey().isEmpty());
}
}
@ -92,20 +96,20 @@ public class PerGroupChunkProvider extends ThreadProvider {
@Override
public void update(long time) {
// Set of already-updated instances
// Set of already-updated instances this tick
final Set<Instance> updatedInstance = new HashSet<>();
instanceInstanceMap.entrySet().forEach(entry -> {
final Instance instance = entry.getKey();
final Map<Set<ChunkCoordinate>, Instance> instanceMap = entry.getValue();
// Update all the chunks
// Update all the chunks + instances
for (Map.Entry<Set<ChunkCoordinate>, Instance> ent : instanceMap.entrySet()) {
final Set<ChunkCoordinate> chunks = ent.getKey();
final boolean updateInstance = updatedInstance.add(instance);
pool.execute(() -> {
// Used to check if the instance has already been updated this tick
if (updateInstance) {
updateInstance(instance, time);
}
@ -127,6 +131,14 @@ public class PerGroupChunkProvider extends ThreadProvider {
});
}
/**
* Get all the neighbours of a chunk and itself, no diagonals
*
* @param instance the instance of the chunks
* @param chunkX the chunk X
* @param chunkZ the chunk Z
* @return the loaded neighbours of the chunk
*/
private List<ChunkCoordinate> getNeighbours(Instance instance, int chunkX, int chunkZ) {
List<ChunkCoordinate> chunks = new ArrayList<>();
// Constants used to loop through the neighbors
@ -144,9 +156,8 @@ public class PerGroupChunkProvider extends ThreadProvider {
final int targetZ = chunkZ + z;
final Chunk chunk = instance.getChunk(targetX, targetZ);
if (!ChunkUtils.isChunkUnloaded(chunk)) {
// Chunk is loaded, add it
chunks.add(toChunkCoordinate(chunk));
} else {
//System.out.println(targetX+" : "+targetZ);
}
}

View File

@ -18,6 +18,7 @@ public class PerInstanceThreadProvider extends ThreadProvider {
@Override
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
// Add the loaded chunk to the instance chunks list
Set<ChunkCoordinate> chunkCoordinates = getChunkCoordinates(instance);
chunkCoordinates.add(new ChunkCoordinate(chunkX, chunkZ));
}
@ -25,7 +26,7 @@ public class PerInstanceThreadProvider extends ThreadProvider {
@Override
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
Set<ChunkCoordinate> chunkCoordinates = getChunkCoordinates(instance);
// Remove the unloaded chunk from the instance list
chunkCoordinates.removeIf(chunkCoordinate -> chunkCoordinate.chunkX == chunkX &&
chunkCoordinate.chunkZ == chunkZ);

View File

@ -183,10 +183,20 @@ public abstract class ThreadProvider {
}
}
/**
* Convert a {@link Chunk} to a {@link ChunkCoordinate}
*
* @param chunk the chunk to convert
* @return the converted {@link ChunkCoordinate}
*/
protected ChunkCoordinate toChunkCoordinate(Chunk chunk) {
return new ChunkCoordinate(chunk.getChunkX(), chunk.getChunkZ());
}
/**
* Represent the coordinates of a {@link Chunk}
* Used so the chunks objects can be cleared by the garbage collector properly¬
*/
protected static class ChunkCoordinate {
public int chunkX, chunkZ;

View File

@ -26,8 +26,10 @@ public class ArrayUtils {
}
/**
* @param a
* @param b
* Get the differences between 2 arrays
*
* @param a the first array
* @param b the second array
* @return an array containing a's indexes that aren't in b array
*/
public static int[] getDifferencesBetweenArray(long[] a, long[] b) {

View File

@ -33,8 +33,8 @@ public class NBTUtils {
/**
* Loads all the items from the 'items' list into the given inventory
*
* @param items
* @param destination
* @param items the items to save
* @param destination the inventory destination
*/
public static void loadAllItems(NBTList<NBTCompound> items, Inventory destination) {
destination.clear();

View File

@ -36,7 +36,7 @@ public class WeightedRandom<E extends WeightedRandomItem> {
* Gets a random element from this set
*
* @param rng Random Number Generator to generate random numbers with
* @return
* @return a random element from this set
*/
public E get(Random rng) {
final double p = rng.nextDouble() * totalWeight;