diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..2325a1cc2 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,67 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '27 19 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/build.gradle b/build.gradle index 9c3200bcb..70de947fc 100644 --- a/build.gradle +++ b/build.gradle @@ -124,17 +124,17 @@ dependencies { testCompileOnly "org.mockito:mockito-core:2.28.2" // Netty - api 'io.netty:netty-handler:4.1.59.Final' - api 'io.netty:netty-codec:4.1.59.Final' - api 'io.netty:netty-transport-native-epoll:4.1.59.Final:linux-x86_64' - api 'io.netty:netty-transport-native-kqueue:4.1.59.Final:osx-x86_64' + api 'io.netty:netty-handler:4.1.63.Final' + api 'io.netty:netty-codec:4.1.63.Final' + api 'io.netty:netty-transport-native-epoll:4.1.63.Final:linux-x86_64' + api 'io.netty:netty-transport-native-kqueue:4.1.63.Final:osx-x86_64' api 'io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.4.Final:linux-x86_64' // https://mvnrepository.com/artifact/org.apache.commons/commons-text compile group: 'org.apache.commons', name: 'commons-text', version: '1.9' // https://mvnrepository.com/artifact/it.unimi.dsi/fastutil - api 'it.unimi.dsi:fastutil:8.5.2' + api 'it.unimi.dsi:fastutil:8.5.4' // https://mvnrepository.com/artifact/com.google.code.gson/gson api 'com.google.code.gson:gson:2.8.6' @@ -144,7 +144,7 @@ dependencies { api 'com.github.Articdive:Jnoise:1.0.0' // https://mvnrepository.com/artifact/org.rocksdb/rocksdbjni - api 'org.rocksdb:rocksdbjni:6.15.2' + api 'org.rocksdb:rocksdbjni:6.16.4' // Logging api 'org.apache.logging.log4j:log4j-core:2.14.0' @@ -167,7 +167,7 @@ dependencies { implementation "com.velocitypowered:velocity-native:1.1.0-SNAPSHOT" // Path finding - api 'com.github.MadMartian:hydrazine-path-finding:1.5.4' + api 'com.github.MadMartian:hydrazine-path-finding:1.6.0' api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${project.kotlinVersion}" api "org.jetbrains.kotlin:kotlin-reflect:${project.kotlinVersion}" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f604ed164..28ff446a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=fd591a34af7385730970399f473afabdb8b28d57fd97d6625c388d090039d6fd distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/generators/java/net/minestom/codegen/EnumGenerator.java b/src/generators/java/net/minestom/codegen/EnumGenerator.java index c61f4d21d..60c2d193b 100644 --- a/src/generators/java/net/minestom/codegen/EnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/EnumGenerator.java @@ -139,8 +139,7 @@ public class EnumGenerator implements CodeGenerator { // constructor MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder(); - for (int i = 0; i < parameters.length; i++) { - ParameterSpec param = parameters[i]; + for (ParameterSpec param : parameters) { constructorBuilder.addParameter(param); // property assignment diff --git a/src/generators/java/net/minestom/codegen/enchantment/EnchantmentEnumGenerator.java b/src/generators/java/net/minestom/codegen/enchantment/EnchantmentEnumGenerator.java index a7d1a9455..b39c56679 100644 --- a/src/generators/java/net/minestom/codegen/enchantment/EnchantmentEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/enchantment/EnchantmentEnumGenerator.java @@ -1,7 +1,6 @@ package net.minestom.codegen.enchantment; import net.minestom.codegen.BasicEnumGenerator; -import net.minestom.codegen.stats.StatsEnumGenerator; import net.minestom.server.registry.ResourceGatherer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java b/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java index 086ca3abe..72086a33b 100644 --- a/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java @@ -1,7 +1,6 @@ package net.minestom.codegen.fluids; import net.minestom.codegen.BasicEnumGenerator; -import net.minestom.codegen.stats.StatsEnumGenerator; import net.minestom.server.registry.ResourceGatherer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/generators/java/net/minestom/codegen/potions/PotionEnumGenerator.java b/src/generators/java/net/minestom/codegen/potions/PotionEnumGenerator.java index 36f784bc1..4fe388658 100644 --- a/src/generators/java/net/minestom/codegen/potions/PotionEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/potions/PotionEnumGenerator.java @@ -1,7 +1,6 @@ package net.minestom.codegen.potions; import net.minestom.codegen.BasicEnumGenerator; -import net.minestom.codegen.stats.StatsEnumGenerator; import net.minestom.server.registry.ResourceGatherer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/lwjgl/java/net/minestom/demo/largeframebuffers/OpenGLRendering.java b/src/lwjgl/java/net/minestom/demo/largeframebuffers/OpenGLRendering.java index 6e7b3f6d9..3b2d5780a 100644 --- a/src/lwjgl/java/net/minestom/demo/largeframebuffers/OpenGLRendering.java +++ b/src/lwjgl/java/net/minestom/demo/largeframebuffers/OpenGLRendering.java @@ -12,7 +12,6 @@ import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.util.stream.Collectors; -import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL20.*; public final class OpenGLRendering { diff --git a/src/lwjgl/java/net/minestom/server/map/PaletteGenerator.java b/src/lwjgl/java/net/minestom/server/map/PaletteGenerator.java index cb3de987b..317caf92b 100644 --- a/src/lwjgl/java/net/minestom/server/map/PaletteGenerator.java +++ b/src/lwjgl/java/net/minestom/server/map/PaletteGenerator.java @@ -7,8 +7,6 @@ import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; public class PaletteGenerator { diff --git a/src/lwjgl/java/net/minestom/server/map/framebuffers/GLFWCapableBuffer.java b/src/lwjgl/java/net/minestom/server/map/framebuffers/GLFWCapableBuffer.java index fed4ede7b..1ab0676f7 100644 --- a/src/lwjgl/java/net/minestom/server/map/framebuffers/GLFWCapableBuffer.java +++ b/src/lwjgl/java/net/minestom/server/map/framebuffers/GLFWCapableBuffer.java @@ -14,7 +14,6 @@ import org.lwjgl.system.MemoryStack; import java.nio.ByteBuffer; import static org.lwjgl.glfw.GLFW.*; -import static org.lwjgl.glfw.GLFW.glfwTerminate; import static org.lwjgl.opengl.GL11.*; public abstract class GLFWCapableBuffer { diff --git a/src/lwjgl/java/net/minestom/server/map/framebuffers/MapColorRenderer.java b/src/lwjgl/java/net/minestom/server/map/framebuffers/MapColorRenderer.java index fb6bc3284..2115f1dc5 100644 --- a/src/lwjgl/java/net/minestom/server/map/framebuffers/MapColorRenderer.java +++ b/src/lwjgl/java/net/minestom/server/map/framebuffers/MapColorRenderer.java @@ -167,7 +167,7 @@ public class MapColorRenderer implements Runnable { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screenQuadIndices); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - }; + } glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/src/main/java/net/minestom/server/UpdateManager.java b/src/main/java/net/minestom/server/UpdateManager.java index d16841997..1222f0bc4 100644 --- a/src/main/java/net/minestom/server/UpdateManager.java +++ b/src/main/java/net/minestom/server/UpdateManager.java @@ -1,11 +1,14 @@ package net.minestom.server; import com.google.common.collect.Queues; +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.player.NettyPlayerConnection; import net.minestom.server.thread.PerInstanceThreadProvider; import net.minestom.server.thread.ThreadProvider; +import net.minestom.server.utils.async.AsyncUtils; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -80,6 +83,12 @@ public final class UpdateManager { // Tick end callbacks doTickCallback(tickEndCallbacks, tickTime / 1000000L); + // Flush all waiting packets + AsyncUtils.runAsync(() -> connectionManager.getOnlinePlayers().stream() + .filter(player -> player.getPlayerConnection() instanceof NettyPlayerConnection) + .map(player -> (NettyPlayerConnection) player.getPlayerConnection()) + .forEach(NettyPlayerConnection::flush)); + } catch (Exception e) { MinecraftServer.getExceptionManager().handleException(e); } @@ -175,13 +184,12 @@ public final class UpdateManager { * WARNING: should be automatically done by the {@link Instance} implementation. * * @param instance the instance of the chunk - * @param chunkX the chunk X - * @param chunkZ the chunk Z + * @param chunk the loaded chunk */ - public synchronized void signalChunkLoad(Instance instance, int chunkX, int chunkZ) { + public synchronized void signalChunkLoad(Instance instance, @NotNull Chunk chunk) { if (this.threadProvider == null) return; - this.threadProvider.onChunkLoad(instance, chunkX, chunkZ); + this.threadProvider.onChunkLoad(instance, chunk); } /** @@ -190,13 +198,12 @@ public final class UpdateManager { * WARNING: should be automatically done by the {@link Instance} implementation. * * @param instance the instance of the chunk - * @param chunkX the chunk X - * @param chunkZ the chunk Z + * @param chunk the unloaded chunk */ - public synchronized void signalChunkUnload(Instance instance, int chunkX, int chunkZ) { + public synchronized void signalChunkUnload(Instance instance, @NotNull Chunk chunk) { if (this.threadProvider == null) return; - this.threadProvider.onChunkUnload(instance, chunkX, chunkZ); + this.threadProvider.onChunkUnload(instance, chunk); } /** diff --git a/src/main/java/net/minestom/server/Viewable.java b/src/main/java/net/minestom/server/Viewable.java index 53a229dbc..de5324cc1 100644 --- a/src/main/java/net/minestom/server/Viewable.java +++ b/src/main/java/net/minestom/server/Viewable.java @@ -7,7 +7,6 @@ import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.utils.PacketUtils; import org.jetbrains.annotations.NotNull; -import java.util.Collections; import java.util.Set; /** diff --git a/src/main/java/net/minestom/server/adventure/AdventurePacketConvertor.java b/src/main/java/net/minestom/server/adventure/AdventurePacketConvertor.java index 592b440f9..e4e4cf5ea 100644 --- a/src/main/java/net/minestom/server/adventure/AdventurePacketConvertor.java +++ b/src/main/java/net/minestom/server/adventure/AdventurePacketConvertor.java @@ -2,13 +2,10 @@ package net.minestom.server.adventure; import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; -import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.sound.Sound; import net.kyori.adventure.sound.SoundStop; -import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minestom.server.entity.Entity; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.play.EntitySoundEffectPacket; diff --git a/src/main/java/net/minestom/server/chat/ChatColor.java b/src/main/java/net/minestom/server/chat/ChatColor.java index 9451b22c2..8788af914 100644 --- a/src/main/java/net/minestom/server/chat/ChatColor.java +++ b/src/main/java/net/minestom/server/chat/ChatColor.java @@ -4,9 +4,7 @@ import it.unimi.dsi.fastutil.chars.Char2ObjectMap; import it.unimi.dsi.fastutil.chars.Char2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.kyori.adventure.text.ComponentBuilder; import net.kyori.adventure.text.format.*; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.minestom.server.color.Color; import net.minestom.server.color.DyeColor; import net.minestom.server.utils.validate.Check; diff --git a/src/main/java/net/minestom/server/color/Color.java b/src/main/java/net/minestom/server/color/Color.java index 72f69d637..9fc613792 100644 --- a/src/main/java/net/minestom/server/color/Color.java +++ b/src/main/java/net/minestom/server/color/Color.java @@ -1,6 +1,5 @@ package net.minestom.server.color; -import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.util.RGBLike; import net.minestom.server.chat.ChatColor; import org.apache.commons.lang3.Validate; diff --git a/src/main/java/net/minestom/server/command/ServerSender.java b/src/main/java/net/minestom/server/command/ServerSender.java index 235630771..663c57d7d 100644 --- a/src/main/java/net/minestom/server/command/ServerSender.java +++ b/src/main/java/net/minestom/server/command/ServerSender.java @@ -2,7 +2,6 @@ package net.minestom.server.command; import net.minestom.server.command.builder.CommandContext; import net.kyori.adventure.audience.Audience; -import net.minestom.server.command.builder.Arguments; import net.minestom.server.permission.Permission; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/minestom/server/command/builder/arguments/Argument.java b/src/main/java/net/minestom/server/command/builder/arguments/Argument.java index bc0514fcc..22c67eb29 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/Argument.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/Argument.java @@ -220,6 +220,18 @@ public abstract class Argument { return suggestionCallback != null; } + /** + * Maps this argument's output to another result. + * + * @param mapper The mapper to use (this argument's input = desired output) + * @param The type of output expected. + * @return A new ArgumentMap that can get this complex object type. + */ + @Beta + public @NotNull ArgumentMap map(@NotNull ArgumentMap.Mapper mapper) { + return new ArgumentMap<>(this, mapper); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentMap.java b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentMap.java new file mode 100644 index 000000000..7eba556a7 --- /dev/null +++ b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentMap.java @@ -0,0 +1,57 @@ +package net.minestom.server.command.builder.arguments; + +import net.minestom.server.command.builder.NodeMaker; +import net.minestom.server.command.builder.exception.ArgumentSyntaxException; +import org.jetbrains.annotations.NotNull; + +/** + * Represents an argument that maps an existing argument to a value. + * + * @param The input (any object) + * @param The output (any object) + */ +public class ArgumentMap extends Argument { + + final Argument argument; + final Mapper mapper; + + protected ArgumentMap(@NotNull Argument argument, @NotNull Mapper mapper) { + super(argument.getId(), argument.allowSpace(), argument.useRemaining()); + + this.argument = argument; + this.mapper = mapper; + } + + @Override + public @NotNull O parse(@NotNull String input) throws ArgumentSyntaxException { + return mapper.accept(argument.parse(input)); + } + + @Override + public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) { + argument.processNodes(nodeMaker, executable); + } + + /** + * Represents a lambda that can turn an input into an output + * that also allows the throwing of ArgumentSyntaxException + * + * @param The input expected from the Argument + * @param The desired output type from this lambda. + */ + @FunctionalInterface + public interface Mapper { + + /** + * Accepts I data from the argument and returns O output + * + * @param i The input processed from an argument + * @return The complex data type that came as a result from this argument + * @throws ArgumentSyntaxException If the input can not be turned into the desired output + * (E.X. an invalid extension name) + */ + O accept(I i) throws ArgumentSyntaxException; + + } + +} diff --git a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentColor.java b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentColor.java index 0fc2363bb..91fcc6c4e 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentColor.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentColor.java @@ -2,7 +2,6 @@ package net.minestom.server.command.builder.arguments.minecraft; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; -import net.kyori.adventure.text.format.TextDecoration; import net.minestom.server.command.builder.NodeMaker; import net.minestom.server.command.builder.arguments.Argument; import net.minestom.server.command.builder.exception.ArgumentSyntaxException; diff --git a/src/main/java/net/minestom/server/command/builder/condition/CommandCondition.java b/src/main/java/net/minestom/server/command/builder/condition/CommandCondition.java index 181379166..d53f627f8 100644 --- a/src/main/java/net/minestom/server/command/builder/condition/CommandCondition.java +++ b/src/main/java/net/minestom/server/command/builder/condition/CommandCondition.java @@ -22,10 +22,10 @@ public interface CommandCondition { * but will instead be the raw command string given by the sender. * You should in this case warn the sender (eg by sending a message) if the condition is unsuccessful. * - * @param source the sender of the command + * @param sender the sender of the command * @param commandString the raw command string, * null if this is an access request * @return true if the sender has the right to use the command, false otherwise */ - boolean canUse(@NotNull CommandSender source, @Nullable String commandString); + boolean canUse(@NotNull CommandSender sender, @Nullable String commandString); } diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index cf44f6850..13ec16f05 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -1538,10 +1538,7 @@ public class Entity implements Viewable, EventHandler, DataContainer, Permission } private UpdateOption getSynchronizationCooldown() { - if (this.customSynchronizationCooldown != null) { - return this.customSynchronizationCooldown; - } - return SYNCHRONIZATION_COOLDOWN; + return Objects.requireNonNullElse(this.customSynchronizationCooldown, SYNCHRONIZATION_COOLDOWN); } public enum Pose { diff --git a/src/main/java/net/minestom/server/entity/Metadata.java b/src/main/java/net/minestom/server/entity/Metadata.java index ac54d707b..29124ea3c 100644 --- a/src/main/java/net/minestom/server/entity/Metadata.java +++ b/src/main/java/net/minestom/server/entity/Metadata.java @@ -163,9 +163,8 @@ public class Metadata { } public static Value NBT(@NotNull NBT nbt) { - return new Value<>(TYPE_NBT, nbt, writer -> { - writer.writeNBT("", nbt); - }, reader -> { + return new Value<>(TYPE_NBT, nbt, writer -> + writer.writeNBT("", nbt), reader -> { try { return reader.readTag(); } catch (IOException | NBTException e) { diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index 4d8cbee66..a9b177d08 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -59,8 +59,8 @@ import net.minestom.server.recipe.RecipeManager; import net.minestom.server.resourcepack.ResourcePack; import net.minestom.server.scoreboard.BelowNameTag; import net.minestom.server.scoreboard.Team; -import net.minestom.server.sound.SoundEvent; import net.minestom.server.sound.SoundCategory; +import net.minestom.server.sound.SoundEvent; import net.minestom.server.stat.PlayerStatistic; import net.minestom.server.utils.*; import net.minestom.server.utils.callback.OptionalCallback; @@ -2691,8 +2691,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable, private byte displayedSkinParts; private MainHand mainHand; - private boolean firstRefresh = true; - /** * The player game language. * @@ -2768,8 +2766,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable, metadata.setIndex((byte) 16, Metadata.Byte(displayedSkinParts)); - this.firstRefresh = false; - // Client changed his view distance in the settings if (viewDistanceChanged) { refreshVisibleChunks(); diff --git a/src/main/java/net/minestom/server/entity/damage/DamageType.java b/src/main/java/net/minestom/server/entity/damage/DamageType.java index ae42bb111..711469936 100644 --- a/src/main/java/net/minestom/server/entity/damage/DamageType.java +++ b/src/main/java/net/minestom/server/entity/damage/DamageType.java @@ -1,11 +1,7 @@ package net.minestom.server.entity.damage; -import com.google.gson.stream.JsonReader; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.chat.ColoredText; import net.minestom.server.chat.JsonMessage; -import net.minestom.server.chat.RichMessage; import net.minestom.server.data.Data; import net.minestom.server.data.DataContainer; import net.minestom.server.entity.Entity; diff --git a/src/main/java/net/minestom/server/entity/hologram/Hologram.java b/src/main/java/net/minestom/server/entity/hologram/Hologram.java index 9f7fa0e12..22d4c7596 100644 --- a/src/main/java/net/minestom/server/entity/hologram/Hologram.java +++ b/src/main/java/net/minestom/server/entity/hologram/Hologram.java @@ -2,7 +2,6 @@ package net.minestom.server.entity.hologram; import net.kyori.adventure.text.Component; import net.minestom.server.Viewable; -import net.minestom.server.chat.ColoredText; import net.minestom.server.chat.JsonMessage; import net.minestom.server.entity.Player; import net.minestom.server.entity.type.decoration.EntityArmorStand; diff --git a/src/main/java/net/minestom/server/entity/metadata/animal/MooshroomMeta.java b/src/main/java/net/minestom/server/entity/metadata/animal/MooshroomMeta.java index ee580ed2a..badbae55f 100644 --- a/src/main/java/net/minestom/server/entity/metadata/animal/MooshroomMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/animal/MooshroomMeta.java @@ -23,7 +23,7 @@ public class MooshroomMeta extends CowMeta { public enum Variant { RED, - BROWN; + BROWN } } diff --git a/src/main/java/net/minestom/server/entity/metadata/minecart/CommandBlockMinecartMeta.java b/src/main/java/net/minestom/server/entity/metadata/minecart/CommandBlockMinecartMeta.java index fdb994154..6d55b3e6c 100644 --- a/src/main/java/net/minestom/server/entity/metadata/minecart/CommandBlockMinecartMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/minecart/CommandBlockMinecartMeta.java @@ -1,7 +1,6 @@ package net.minestom.server.entity.metadata.minecart; import net.kyori.adventure.text.Component; -import net.minestom.server.chat.ColoredText; import net.minestom.server.chat.JsonMessage; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; diff --git a/src/main/java/net/minestom/server/entity/pathfinding/Navigator.java b/src/main/java/net/minestom/server/entity/pathfinding/Navigator.java index e78a0bf66..ff2b5d7e6 100644 --- a/src/main/java/net/minestom/server/entity/pathfinding/Navigator.java +++ b/src/main/java/net/minestom/server/entity/pathfinding/Navigator.java @@ -1,6 +1,7 @@ package net.minestom.server.entity.pathfinding; import com.extollit.gaming.ai.path.HydrazinePathFinder; +import com.extollit.gaming.ai.path.PathOptions; import com.extollit.gaming.ai.path.model.IPath; import net.minestom.server.collision.CollisionUtils; import net.minestom.server.entity.Entity; @@ -140,11 +141,14 @@ public class Navigator { final Position targetPosition = position.clone(); + final PathOptions pathOptions = new PathOptions() + .targetingStrategy(bestEffort ? PathOptions.TargetingStrategy.gravitySnap : + PathOptions.TargetingStrategy.none); final IPath path = pathFinder.initiatePathTo( targetPosition.getX(), targetPosition.getY(), targetPosition.getZ(), - bestEffort); + pathOptions); this.path = path; final boolean success = path != null; diff --git a/src/main/java/net/minestom/server/entity/pathfinding/PFPathingEntity.java b/src/main/java/net/minestom/server/entity/pathfinding/PFPathingEntity.java index 5193af333..bac0578af 100644 --- a/src/main/java/net/minestom/server/entity/pathfinding/PFPathingEntity.java +++ b/src/main/java/net/minestom/server/entity/pathfinding/PFPathingEntity.java @@ -45,6 +45,11 @@ public class PFPathingEntity implements IPathingEntity { return (int) entity.getAliveTicks(); } + @Override + public boolean bound() { + return entity.hasVelocity(); + } + @Override public float searchRange() { return searchRange; diff --git a/src/main/java/net/minestom/server/entity/type/animal/EntityLlama.java b/src/main/java/net/minestom/server/entity/type/animal/EntityLlama.java index be1c1b66b..da945b483 100644 --- a/src/main/java/net/minestom/server/entity/type/animal/EntityLlama.java +++ b/src/main/java/net/minestom/server/entity/type/animal/EntityLlama.java @@ -2,7 +2,6 @@ package net.minestom.server.entity.type.animal; import net.minestom.server.entity.EntityCreature; import net.minestom.server.entity.EntityType; -import net.minestom.server.entity.Metadata; import net.minestom.server.instance.Instance; import net.minestom.server.utils.Position; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/minestom/server/event/handler/EventHandler.java b/src/main/java/net/minestom/server/event/handler/EventHandler.java index 5bb0bf40a..2b8a1b4ad 100644 --- a/src/main/java/net/minestom/server/event/handler/EventHandler.java +++ b/src/main/java/net/minestom/server/event/handler/EventHandler.java @@ -13,7 +13,6 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Map; -import java.util.Optional; import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Stream; @@ -52,7 +51,7 @@ public interface EventHandler extends IExtensionObserver { if(extensionSource != null) { MinecraftServer.getExtensionManager().getExtension(extensionSource).observe(this); getExtensionCallbacks(extensionSource).add(eventCallback); - }; + } Collection callbacks = getEventCallbacks(eventClass); return callbacks.add(eventCallback); @@ -71,7 +70,7 @@ public interface EventHandler extends IExtensionObserver { String extensionSource = MinestomRootClassLoader.findExtensionObjectOwner(eventCallback); if(extensionSource != null) { getExtensionCallbacks(extensionSource).remove(eventCallback); - }; + } return callbacks.remove(eventCallback); } diff --git a/src/main/java/net/minestom/server/event/player/PlayerChatEvent.java b/src/main/java/net/minestom/server/event/player/PlayerChatEvent.java index 4be97291f..b840e81e2 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerChatEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerChatEvent.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.function.Function; +import java.util.function.Supplier; /** * Called every time a {@link Player} write and send something in the chat. @@ -19,14 +20,18 @@ import java.util.function.Function; public class PlayerChatEvent extends PlayerEvent implements CancellableEvent { private final Collection recipients; + private final Supplier defaultChatFormat; private String message; private Function chatFormat; private boolean cancelled; - public PlayerChatEvent(@NotNull Player player, @NotNull Collection recipients, @NotNull String message) { + public PlayerChatEvent(@NotNull Player player, @NotNull Collection recipients, + @NotNull Supplier defaultChatFormat, + @NotNull String message) { super(player); this.recipients = new ArrayList<>(recipients); + this.defaultChatFormat = defaultChatFormat; this.message = message; } @@ -57,8 +62,7 @@ public class PlayerChatEvent extends PlayerEvent implements CancellableEvent { * * @return a modifiable list of message targets */ - @NotNull - public Collection getRecipients() { + public @NotNull Collection getRecipients() { return recipients; } @@ -67,8 +71,7 @@ public class PlayerChatEvent extends PlayerEvent implements CancellableEvent { * * @return the sender's message */ - @NotNull - public String getMessage() { + public @NotNull String getMessage() { return message; } @@ -88,11 +91,14 @@ public class PlayerChatEvent extends PlayerEvent implements CancellableEvent { * * @return the chat format which will be used, null if this is the default one */ - @Nullable - public Function getChatFormatFunction() { + public @Nullable Function<@NotNull PlayerChatEvent, @NotNull Component> getChatFormatFunction() { return chatFormat; } + public @NotNull Supplier<@NotNull Component> getDefaultChatFormat() { + return defaultChatFormat; + } + @Override public boolean isCancelled() { return cancelled; diff --git a/src/main/java/net/minestom/server/event/player/PlayerDeathEvent.java b/src/main/java/net/minestom/server/event/player/PlayerDeathEvent.java index 477e8deca..466c26d62 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerDeathEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerDeathEvent.java @@ -1,6 +1,5 @@ package net.minestom.server.event.player; -import com.google.gson.stream.JsonReader; import net.kyori.adventure.text.Component; import net.minestom.server.chat.JsonMessage; import net.minestom.server.entity.Player; diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index 409a3b302..c0782ee10 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -53,7 +53,7 @@ import java.util.function.Consumer; * WARNING: when making your own implementation registering the instance manually is required * with {@link InstanceManager#registerInstance(Instance)}, and * you need to be sure to signal the {@link UpdateManager} of the changes using - * {@link UpdateManager#signalChunkLoad(Instance, int, int)} and {@link UpdateManager#signalChunkUnload(Instance, int, int)}. + * {@link UpdateManager#signalChunkLoad(Instance, Chunk)} and {@link UpdateManager#signalChunkUnload(Instance, Chunk)}. */ public abstract class Instance implements BlockModifier, EventHandler, DataContainer, PacketGroupingAudience { @@ -252,7 +252,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta * Used when a {@link Chunk} is not currently loaded in memory and need to be retrieved from somewhere else. * Could be read from disk, or generated from scratch. *

- * Be sure to signal the chunk using {@link UpdateManager#signalChunkLoad(Instance, int, int)} and to cache + * Be sure to signal the chunk using {@link UpdateManager#signalChunkLoad(Instance, Chunk)} and to cache * that this chunk has been loaded. *

* WARNING: it has to retrieve a chunk, this is not optional and should execute the callback in all case. @@ -266,7 +266,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta /** * Called to generated a new {@link Chunk} from scratch. *

- * Be sure to signal the chunk using {@link UpdateManager#signalChunkLoad(Instance, int, int)} and to cache + * Be sure to signal the chunk using {@link UpdateManager#signalChunkLoad(Instance, Chunk)} and to cache * that this chunk has been loaded. *

* This is where you can put your chunk generation code. @@ -485,8 +485,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta * @return an unmodifiable {@link Set} containing all the entities in a chunk, * if {@code chunk} is unloaded, return an empty {@link HashSet} */ - @NotNull - public Set getChunkEntities(Chunk chunk) { + public @NotNull Set getChunkEntities(Chunk chunk) { if (!ChunkUtils.isLoaded(chunk)) return new HashSet<>(); diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index 5f2f67369..a2bfaaa36 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -1,8 +1,5 @@ package net.minestom.server.instance; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minestom.server.MinecraftServer; import net.minestom.server.data.Data; import net.minestom.server.data.SerializableData; @@ -34,6 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; @@ -56,7 +54,7 @@ public class InstanceContainer extends Instance { // the chunk generator used, can be null private ChunkGenerator chunkGenerator; // (chunk index -> chunk) map, contains all the chunks in the instance - private final Long2ObjectMap chunks = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); + private final Map chunks = new ConcurrentHashMap<>(); // contains all the chunks to remove during the next instance tick, should be synchronized protected final Set scheduledChunksToRemove = new HashSet<>(); @@ -508,7 +506,7 @@ public class InstanceContainer extends Instance { protected void retrieveChunk(int chunkX, int chunkZ, @Nullable ChunkCallback callback) { final boolean loaded = chunkLoader.loadChunk(this, chunkX, chunkZ, chunk -> { cacheChunk(chunk); - UPDATE_MANAGER.signalChunkLoad(this, chunkX, chunkZ); + UPDATE_MANAGER.signalChunkLoad(this, chunk); // Execute callback and event in the instance thread scheduleNextTick(instance -> { callChunkLoadEvent(chunkX, chunkZ); @@ -546,7 +544,7 @@ public class InstanceContainer extends Instance { OptionalCallback.execute(callback, chunk); } - UPDATE_MANAGER.signalChunkLoad(this, chunkX, chunkZ); + UPDATE_MANAGER.signalChunkLoad(this, chunk); callChunkLoadEvent(chunkX, chunkZ); } @@ -643,7 +641,7 @@ public class InstanceContainer extends Instance { final Chunk copiedChunk = chunk.copy(chunkX, chunkZ); copiedInstance.cacheChunk(copiedChunk); - UPDATE_MANAGER.signalChunkLoad(copiedInstance, chunkX, chunkZ); + UPDATE_MANAGER.signalChunkLoad(copiedInstance, copiedChunk); } return copiedInstance; @@ -684,7 +682,7 @@ public class InstanceContainer extends Instance { * Adds a {@link Chunk} to the internal instance map. *

* WARNING: the chunk will not automatically be sent to players and - * {@link net.minestom.server.UpdateManager#signalChunkLoad(Instance, int, int)} must be called manually. + * {@link net.minestom.server.UpdateManager#signalChunkLoad(Instance, Chunk)} must be called manually. * * @param chunk the chunk to cache */ @@ -825,7 +823,7 @@ public class InstanceContainer extends Instance { chunk.unload(); - UPDATE_MANAGER.signalChunkUnload(this, chunkX, chunkZ); + UPDATE_MANAGER.signalChunkUnload(this, chunk); } this.scheduledChunksToRemove.clear(); } diff --git a/src/main/java/net/minestom/server/instance/block/rule/vanilla/StairsPlacementRule.java b/src/main/java/net/minestom/server/instance/block/rule/vanilla/StairsPlacementRule.java index efc86fb2a..4a53096f2 100644 --- a/src/main/java/net/minestom/server/instance/block/rule/vanilla/StairsPlacementRule.java +++ b/src/main/java/net/minestom/server/instance/block/rule/vanilla/StairsPlacementRule.java @@ -42,7 +42,7 @@ public class StairsPlacementRule extends BlockPlacementRule { OUTER_LEFT, OUTER_RIGHT, INNER_LEFT, - INNER_RIGHT; + INNER_RIGHT } private enum Facing { diff --git a/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java b/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java index af753fba5..0591a85a8 100644 --- a/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java +++ b/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java @@ -10,8 +10,6 @@ import net.minestom.server.utils.clone.PublicCloneable; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; - import static net.minestom.server.instance.Chunk.CHUNK_SECTION_COUNT; import static net.minestom.server.instance.Chunk.CHUNK_SECTION_SIZE; diff --git a/src/main/java/net/minestom/server/inventory/Inventory.java b/src/main/java/net/minestom/server/inventory/Inventory.java index 409eb38a4..27d396a8b 100644 --- a/src/main/java/net/minestom/server/inventory/Inventory.java +++ b/src/main/java/net/minestom/server/inventory/Inventory.java @@ -291,7 +291,7 @@ public class Inventory extends AbstractInventory implements Viewable { final int clickSlot = isInWindow ? slot : PlayerInventoryUtils.convertSlot(slot, offset); final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot); - final InventoryClickResult clickResult = clickProcessor.leftClick(this, player, slot, clicked, cursor); + final InventoryClickResult clickResult = clickProcessor.leftClick(isInWindow ? this : null, player, slot, clicked, cursor); if (clickResult.doRefresh()) { updateFromClick(clickResult, player); @@ -305,7 +305,7 @@ public class Inventory extends AbstractInventory implements Viewable { setCursorPlayerItem(player, clickResult.getCursor()); if (!clickResult.isCancel()) - callClickEvent(player, this, slot, ClickType.LEFT_CLICK, clicked, cursor); + callClickEvent(player, isInWindow ? this : null, slot, ClickType.LEFT_CLICK, clicked, cursor); return !clickResult.isCancel(); } @@ -318,7 +318,7 @@ public class Inventory extends AbstractInventory implements Viewable { final int clickSlot = isInWindow ? slot : PlayerInventoryUtils.convertSlot(slot, offset); final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot); - final InventoryClickResult clickResult = clickProcessor.rightClick(this, player, slot, clicked, cursor); + final InventoryClickResult clickResult = clickProcessor.rightClick(isInWindow ? this : null, player, slot, clicked, cursor); if (clickResult.doRefresh()) { updateFromClick(clickResult, player); @@ -332,7 +332,7 @@ public class Inventory extends AbstractInventory implements Viewable { setCursorPlayerItem(player, clickResult.getCursor()); if (!clickResult.isCancel()) - callClickEvent(player, this, slot, ClickType.RIGHT_CLICK, clicked, cursor); + callClickEvent(player, isInWindow ? this : null, slot, ClickType.RIGHT_CLICK, clicked, cursor); return !clickResult.isCancel(); } @@ -364,7 +364,7 @@ public class Inventory extends AbstractInventory implements Viewable { } })); } else { - clickResult = clickProcessor.shiftClick(this, player, slot, clicked, cursor, + clickResult = clickProcessor.shiftClick(null, player, slot, clicked, cursor, // Window loop new InventoryClickLoopHandler(0, getSize(), 1, i -> i, @@ -402,7 +402,7 @@ public class Inventory extends AbstractInventory implements Viewable { final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot); final ItemStack heldItem = playerInventory.getItemStack(key); - final InventoryClickResult clickResult = clickProcessor.changeHeld(this, player, slot, key, clicked, heldItem); + final InventoryClickResult clickResult = clickProcessor.changeHeld(isInWindow ? this : null, player, slot, key, clicked, heldItem); if (clickResult.doRefresh()) { updateFromClick(clickResult, player); @@ -416,7 +416,7 @@ public class Inventory extends AbstractInventory implements Viewable { playerInventory.setItemStack(key, clickResult.getCursor()); if (!clickResult.isCancel()) - callClickEvent(player, this, slot, ClickType.CHANGE_HELD, clicked, getCursorItem(player)); + callClickEvent(player, isInWindow ? this : null, slot, ClickType.CHANGE_HELD, clicked, getCursorItem(player)); // Weird synchronization issue when omitted updateFromClick(clickResult, player); @@ -440,7 +440,7 @@ public class Inventory extends AbstractInventory implements Viewable { ItemStack.AIR : (isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot)); final ItemStack cursor = getCursorItem(player); - final InventoryClickResult clickResult = clickProcessor.drop(this, player, + final InventoryClickResult clickResult = clickProcessor.drop(isInWindow ? this : null, player, mode, slot, button, clicked, cursor); if (clickResult.doRefresh()) { @@ -471,7 +471,7 @@ public class Inventory extends AbstractInventory implements Viewable { ItemStack.AIR; final ItemStack cursor = getCursorItem(player); - final InventoryClickResult clickResult = clickProcessor.dragging(this, player, + final InventoryClickResult clickResult = clickProcessor.dragging(isInWindow ? this : null, player, slot, button, clicked, cursor, @@ -503,8 +503,9 @@ public class Inventory extends AbstractInventory implements Viewable { public boolean doubleClick(@NotNull Player player, int slot) { final PlayerInventory playerInventory = player.getInventory(); final ItemStack cursor = getCursorItem(player); + final boolean isInWindow = isClickInWindow(slot); - final InventoryClickResult clickResult = clickProcessor.doubleClick(this, player, slot, cursor, + final InventoryClickResult clickResult = clickProcessor.doubleClick(isInWindow ? this : null, player, slot, cursor, // Start by looping through the opened inventory new InventoryClickLoopHandler(0, getSize(), 1, i -> i, diff --git a/src/main/java/net/minestom/server/item/firework/FireworkEffect.java b/src/main/java/net/minestom/server/item/firework/FireworkEffect.java index 59c8a3c7c..dcb8008b4 100644 --- a/src/main/java/net/minestom/server/item/firework/FireworkEffect.java +++ b/src/main/java/net/minestom/server/item/firework/FireworkEffect.java @@ -1,46 +1,33 @@ package net.minestom.server.item.firework; -import net.kyori.adventure.text.format.TextColor; import net.minestom.server.chat.ChatColor; import net.minestom.server.color.Color; +import net.minestom.server.exception.ExceptionManager; +import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.NotNull; -import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import org.jglrxavpok.hephaistos.nbt.*; -import java.util.Objects; +import java.util.*; public class FireworkEffect { private final boolean flicker; private final boolean trail; private final FireworkEffectType type; - private final Color color; - private final Color fadeColor; + private final List color; + private final List fadeColor; + //FIXME: fix javadoc /** * Initializes a new firework effect. * * @param flicker {@code true} if this explosion has the Twinkle effect (glowstone dust), otherwise {@code false}. * @param trail {@code true} if this explosion hsa the Trail effect (diamond), otherwise {@code false}. * @param type The shape of this firework's explosion. - * @param color The primary color of this firework effect. - * @param fadeColor The secondary color of this firework effect. - * @deprecated Use {@link #FireworkEffect(boolean, boolean, FireworkEffectType, Color, Color)} + * @param color The primary colors of this firework effect. + * @param fadeColor The secondary colors of this firework effect. */ - @Deprecated - public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, ChatColor color, ChatColor fadeColor) { - this(flicker, trail, type, color.asColor(), fadeColor.asColor()); - } - - /** - * Initializes a new firework effect. - * - * @param flicker {@code true} if this explosion has the Twinkle effect (glowstone dust), otherwise {@code false}. - * @param trail {@code true} if this explosion hsa the Trail effect (diamond), otherwise {@code false}. - * @param type The shape of this firework's explosion. - * @param color The primary color of this firework effect. - * @param fadeColor The secondary color of this firework effect. - */ - public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, Color color, Color fadeColor) { + public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, List color, List fadeColor) { this.flicker = flicker; this.trail = trail; this.type = type; @@ -56,18 +43,21 @@ public class FireworkEffect { */ public static FireworkEffect fromCompound(@NotNull NBTCompound compound) { - Color primaryColor = null; - Color secondaryColor = null; + List primaryColor = new ArrayList<>(); + List secondaryColor = new ArrayList<>(); if (compound.containsKey("Colors")) { int[] color = compound.getIntArray("Colors"); - primaryColor = new Color(color[0], color[1], color[2]); + for (int i = 0; i < color.length; i++) { + primaryColor.add(new Color(color[i])); + } } if (compound.containsKey("FadeColors")) { int[] fadeColor = compound.getIntArray("FadeColors"); - secondaryColor = new Color(fadeColor[0], fadeColor[1], fadeColor[2]); - + for (int i = 0; i < fadeColor.length; i++) { + secondaryColor.add(new Color(fadeColor[i])); + } } boolean flicker = compound.containsKey("Flicker") && compound.getByte("Flicker") == 1; @@ -119,11 +109,11 @@ public class FireworkEffect { * @return An array of integer values corresponding to the primary colors of this firework's explosion. */ public int[] getColors() { - return new int[]{ - this.color.getRed(), - this.color.getGreen(), - this.color.getBlue() - }; + int[] primary = new int[color.size()]; + for (int i = 0; i < color.size(); i++) { + primary[i] = color.get(i).asRGB(); + } + return primary; } /** @@ -134,11 +124,11 @@ public class FireworkEffect { * @return An array of integer values corresponding to the fading colors of this firework's explosion. */ public int[] getFadeColors() { - return new int[]{ - this.fadeColor.getRed(), - this.fadeColor.getGreen(), - this.fadeColor.getBlue() - }; + int[] secondary = new int[fadeColor.size()]; + for (int i = 0; i < fadeColor.size(); i++) { + secondary[i] = fadeColor.get(i).asRGB(); + } + return secondary; } /** diff --git a/src/main/java/net/minestom/server/item/metadata/PotionMeta.java b/src/main/java/net/minestom/server/item/metadata/PotionMeta.java index 6d84324ac..7ad2b281b 100644 --- a/src/main/java/net/minestom/server/item/metadata/PotionMeta.java +++ b/src/main/java/net/minestom/server/item/metadata/PotionMeta.java @@ -1,6 +1,5 @@ package net.minestom.server.item.metadata; -import net.kyori.adventure.text.format.TextColor; import net.minestom.server.chat.ChatColor; import net.minestom.server.color.Color; import net.minestom.server.potion.CustomPotionEffect; diff --git a/src/main/java/net/minestom/server/listener/ChatMessageListener.java b/src/main/java/net/minestom/server/listener/ChatMessageListener.java index 8b1f3daae..1f5e56a49 100644 --- a/src/main/java/net/minestom/server/listener/ChatMessageListener.java +++ b/src/main/java/net/minestom/server/listener/ChatMessageListener.java @@ -10,6 +10,7 @@ import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.packet.client.play.ClientChatMessagePacket; import net.minestom.server.network.packet.server.play.ChatMessagePacket; import net.minestom.server.utils.PacketUtils; +import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.function.Function; @@ -34,7 +35,8 @@ public class ChatMessageListener { } final Collection players = CONNECTION_MANAGER.getOnlinePlayers(); - PlayerChatEvent playerChatEvent = new PlayerChatEvent(player, players, message); + String finalMessage = message; + PlayerChatEvent playerChatEvent = new PlayerChatEvent(player, players, () -> buildDefaultChatMessage(player, finalMessage), message); // Call the event player.callCancellableEvent(PlayerChatEvent.class, playerChatEvent, () -> { @@ -48,7 +50,7 @@ public class ChatMessageListener { textObject = formatFunction.apply(playerChatEvent); } else { // Default format - textObject = buildDefaultChatMessage(playerChatEvent); + textObject = playerChatEvent.getDefaultChatFormat().get(); } final Collection recipients = playerChatEvent.getRecipients(); @@ -64,15 +66,14 @@ public class ChatMessageListener { } - private static Component buildDefaultChatMessage(PlayerChatEvent chatEvent) { - final String username = chatEvent.getPlayer().getUsername(); - + private static @NotNull Component buildDefaultChatMessage(@NotNull Player player, @NotNull String message) { + final String username = player.getUsername(); return Component.translatable("chat.type.text") .args(Component.text(username) .insertion(username) .clickEvent(ClickEvent.suggestCommand("/msg " + username + " ")) - .hoverEvent(chatEvent.getPlayer()), - Component.text(chatEvent.getMessage()) + .hoverEvent(player), + Component.text(message) ); } diff --git a/src/main/java/net/minestom/server/network/ConnectionManager.java b/src/main/java/net/minestom/server/network/ConnectionManager.java index c141b2384..0e7fdce47 100644 --- a/src/main/java/net/minestom/server/network/ConnectionManager.java +++ b/src/main/java/net/minestom/server/network/ConnectionManager.java @@ -2,12 +2,10 @@ package net.minestom.server.network; import io.netty.channel.Channel; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.MinecraftServer; import net.minestom.server.adventure.audience.Audiences; -import net.minestom.server.adventure.audience.PacketGroupingAudience; import net.minestom.server.chat.JsonMessage; import net.minestom.server.entity.Player; import net.minestom.server.entity.fakeplayer.FakePlayer; diff --git a/src/main/java/net/minestom/server/network/packet/server/ServerPacket.java b/src/main/java/net/minestom/server/network/packet/server/ServerPacket.java index 4c48415cf..eb94d671b 100644 --- a/src/main/java/net/minestom/server/network/packet/server/ServerPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/ServerPacket.java @@ -6,8 +6,6 @@ import net.minestom.server.utils.binary.Readable; import net.minestom.server.utils.binary.Writeable; import org.jetbrains.annotations.NotNull; -import java.nio.CharBuffer; - /** * Represents a packet which can be sent to a player using {@link PlayerConnection#sendPacket(ServerPacket)}. */ diff --git a/src/main/java/net/minestom/server/network/packet/server/play/BlockEntityDataPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/BlockEntityDataPacket.java index 4ae249b53..181355a69 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/BlockEntityDataPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/BlockEntityDataPacket.java @@ -37,7 +37,7 @@ public class BlockEntityDataPacket implements ServerPacket { @Override public void read(@NotNull BinaryReader reader) { - blockPosition = reader.readBlockPosition();; + blockPosition = reader.readBlockPosition(); action = reader.readByte(); try { NBT tag = reader.readTag(); diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java index 8a5a206fa..2db5515e3 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java @@ -19,6 +19,7 @@ import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.cache.CacheablePacket; import net.minestom.server.utils.cache.TemporaryCache; +import net.minestom.server.utils.cache.TemporaryPacketCache; import net.minestom.server.utils.cache.TimedBuffer; import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.world.biomes.Biome; @@ -34,8 +35,7 @@ import java.util.concurrent.TimeUnit; public class ChunkDataPacket implements ServerPacket, CacheablePacket { private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager(); - private static final TemporaryCache CACHE = new TemporaryCache<>(5, TimeUnit.MINUTES, - notification -> notification.getValue().getBuffer().release()); + private static final TemporaryCache CACHE = new TemporaryPacketCache(5, TimeUnit.MINUTES); public boolean fullChunk; public Biome[] biomes; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/DeclareCommandsPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/DeclareCommandsPacket.java index a92a39b63..47972539c 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/DeclareCommandsPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/DeclareCommandsPacket.java @@ -8,8 +8,6 @@ import net.minestom.server.utils.binary.Readable; import net.minestom.server.utils.binary.Writeable; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; - public class DeclareCommandsPacket implements ServerPacket { public Node[] nodes = new Node[0]; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/EntityMetaDataPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/EntityMetaDataPacket.java index 8d8ea85e9..158ee1baf 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/EntityMetaDataPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/EntityMetaDataPacket.java @@ -43,7 +43,7 @@ public class EntityMetaDataPacket implements ServerPacket { break; } - entries.add(new Metadata.Entry(reader)); + entries.add(new Metadata.Entry<>(reader)); } } diff --git a/src/main/java/net/minestom/server/network/packet/server/play/EntitySoundEffectPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/EntitySoundEffectPacket.java index 90f1f2533..a697e1de6 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/EntitySoundEffectPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/EntitySoundEffectPacket.java @@ -4,7 +4,6 @@ import net.kyori.adventure.sound.Sound; import net.minestom.server.adventure.AdventurePacketConvertor; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; -import net.minestom.server.sound.SoundCategory; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/MultiBlockChangePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/MultiBlockChangePacket.java index 92d4ffadd..14954d844 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/MultiBlockChangePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/MultiBlockChangePacket.java @@ -17,7 +17,8 @@ public class MultiBlockChangePacket implements ServerPacket { public boolean suppressLightUpdates = true; public BlockChange[] blockChanges = new BlockChange[0]; - public MultiBlockChangePacket() {} + public MultiBlockChangePacket() { + } @Override public void write(@NotNull BinaryWriter writer) { @@ -27,7 +28,7 @@ public class MultiBlockChangePacket implements ServerPacket { final int length = blockChanges.length; writer.writeVarInt(length); for (final BlockChange blockChange : blockChanges) { - writer.writeVarLong(blockChange.newBlockId << 12 | getLocalBlockPosAsShort(blockChange.positionX, blockChange.positionY, blockChange.positionZ)); + writer.writeVarLong((long) blockChange.newBlockId << 12 | getLocalBlockPosAsShort(blockChange.positionX, blockChange.positionY, blockChange.positionZ)); } } else { writer.writeVarInt(0); diff --git a/src/main/java/net/minestom/server/network/packet/server/play/NamedSoundEffectPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/NamedSoundEffectPacket.java index 8f83cfce8..2a4f5ca5a 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/NamedSoundEffectPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/NamedSoundEffectPacket.java @@ -4,7 +4,6 @@ import net.kyori.adventure.sound.Sound.Source; import net.minestom.server.adventure.AdventurePacketConvertor; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; -import net.minestom.server.sound.SoundCategory; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/OpenSignEditorPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/OpenSignEditorPacket.java index 7bb4fd571..44454f589 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/OpenSignEditorPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/OpenSignEditorPacket.java @@ -3,7 +3,6 @@ package net.minestom.server.network.packet.server.play; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.utils.BlockPosition; -import net.minestom.server.utils.Position; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java index 2c9ca4441..005ca13c8 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ParticlePacket.java @@ -6,8 +6,6 @@ import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; - public class ParticlePacket implements ServerPacket { public int particleId; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java index 17cac62c5..96d8de55c 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java @@ -7,8 +7,6 @@ import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -import java.io.IOException; - public class PluginMessagePacket implements ServerPacket { public String channel = "none"; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java index 31537a767..f1702983a 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java @@ -2,7 +2,6 @@ package net.minestom.server.network.packet.server.play; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; -import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.Position; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java index 86bd295aa..b46d15ab7 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java @@ -10,7 +10,6 @@ import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/UpdateLightPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/UpdateLightPacket.java index 55ff304be..9fee9fd22 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/UpdateLightPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/UpdateLightPacket.java @@ -6,20 +6,19 @@ import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.cache.CacheablePacket; import net.minestom.server.utils.cache.TemporaryCache; +import net.minestom.server.utils.cache.TemporaryPacketCache; import net.minestom.server.utils.cache.TimedBuffer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; public class UpdateLightPacket implements ServerPacket, CacheablePacket { - private static final TemporaryCache CACHE = new TemporaryCache<>(5, TimeUnit.MINUTES, - notification -> notification.getValue().getBuffer().release()); + private static final TemporaryCache CACHE = new TemporaryPacketCache(5, TimeUnit.MINUTES); public int chunkX; public int chunkZ; @@ -103,7 +102,7 @@ public class UpdateLightPacket implements ServerPacket, CacheablePacket { skyLight.clear(); for (int i = 0; i < 14; i++) { int length = reader.readVarInt(); - if(length != 2048) { + if (length != 2048) { throw new IllegalStateException("Length must be 2048."); } @@ -115,7 +114,7 @@ public class UpdateLightPacket implements ServerPacket, CacheablePacket { blockLight.clear(); for (int i = 0; i < 6; i++) { int length = reader.readVarInt(); - if(length != 2048) { + if (length != 2048) { throw new IllegalStateException("Length must be 2048."); } diff --git a/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java b/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java index 0efb81a11..70f570ed1 100644 --- a/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java +++ b/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java @@ -71,22 +71,6 @@ public class NettyPlayerConnection extends PlayerConnection { this.tickBuffer.ensureWritable(INITIAL_BUFFER_SIZE); } - @Override - public void update() { - // Flush - final int bufferSize = tickBuffer.writerIndex(); - if (bufferSize > 0) { - this.channel.eventLoop().submit(() -> { - if (channel.isActive()) { - writeWaitingPackets(); - channel.flush(); - } - }); - } - // Network stats - super.update(); - } - /** * Sets the encryption key and add the codecs to the pipeline. * @@ -134,12 +118,8 @@ public class NettyPlayerConnection extends PlayerConnection { if (getPlayer() != null) { // Flush happen during #update() if (serverPacket instanceof CacheablePacket && MinecraftServer.hasPacketCaching()) { - // Check if the packet is cached or can be - final FramedPacket cachedPacket = CacheablePacket.getCache(serverPacket); - if (cachedPacket != null) { - write(cachedPacket); - } else { - write(serverPacket, skipTranslating); + synchronized (tickBuffer) { + CacheablePacket.writeCache(tickBuffer, serverPacket); } } else { write(serverPacket, skipTranslating); @@ -196,7 +176,7 @@ public class NettyPlayerConnection extends PlayerConnection { } } - private void writeWaitingPackets() { + public void writeWaitingPackets() { if (tickBuffer.writerIndex() == 0) { // Nothing to write return; @@ -221,6 +201,16 @@ public class NettyPlayerConnection extends PlayerConnection { } } + public void flush() { + final int bufferSize = tickBuffer.writerIndex(); + if (bufferSize > 0) { + if (channel.isActive()) { + writeWaitingPackets(); + channel.flush(); + } + } + } + @NotNull @Override public SocketAddress getRemoteAddress() { diff --git a/src/main/java/net/minestom/server/resourcepack/ResourcePack.java b/src/main/java/net/minestom/server/resourcepack/ResourcePack.java index f0837c540..dab2418ee 100644 --- a/src/main/java/net/minestom/server/resourcepack/ResourcePack.java +++ b/src/main/java/net/minestom/server/resourcepack/ResourcePack.java @@ -1,7 +1,6 @@ package net.minestom.server.resourcepack; import net.minestom.server.entity.Player; -import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/net/minestom/server/scoreboard/Scoreboard.java b/src/main/java/net/minestom/server/scoreboard/Scoreboard.java index 01831e231..eaa042e9a 100644 --- a/src/main/java/net/minestom/server/scoreboard/Scoreboard.java +++ b/src/main/java/net/minestom/server/scoreboard/Scoreboard.java @@ -1,7 +1,5 @@ package net.minestom.server.scoreboard; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.text.Component; import net.minestom.server.Viewable; import net.minestom.server.adventure.audience.PacketGroupingAudience; diff --git a/src/main/java/net/minestom/server/scoreboard/Team.java b/src/main/java/net/minestom/server/scoreboard/Team.java index e851aad54..83e3ef4f5 100644 --- a/src/main/java/net/minestom/server/scoreboard/Team.java +++ b/src/main/java/net/minestom/server/scoreboard/Team.java @@ -1,8 +1,6 @@ package net.minestom.server.scoreboard; import com.google.common.collect.MapMaker; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.minestom.server.MinecraftServer; diff --git a/src/main/java/net/minestom/server/sound/SoundCategory.java b/src/main/java/net/minestom/server/sound/SoundCategory.java index 15c4d62d2..4b650a2ee 100644 --- a/src/main/java/net/minestom/server/sound/SoundCategory.java +++ b/src/main/java/net/minestom/server/sound/SoundCategory.java @@ -1,6 +1,5 @@ package net.minestom.server.sound; -import net.kyori.adventure.sound.Sound; import org.jetbrains.annotations.NotNull; import static net.kyori.adventure.sound.Sound.*; diff --git a/src/main/java/net/minestom/server/thread/PerGroupChunkProvider.java b/src/main/java/net/minestom/server/thread/PerGroupChunkProvider.java deleted file mode 100644 index 22178cbef..000000000 --- a/src/main/java/net/minestom/server/thread/PerGroupChunkProvider.java +++ /dev/null @@ -1,173 +0,0 @@ -package net.minestom.server.thread; - -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minestom.server.MinecraftServer; -import net.minestom.server.instance.Instance; -import net.minestom.server.utils.chunk.ChunkUtils; -import org.jetbrains.annotations.NotNull; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; - -/** - * Separate chunks into group of linked chunks - *

- * (1 chunks group = 1 thread execution) - */ -public class PerGroupChunkProvider extends ThreadProvider { - - /** - * Chunk -> its chunk group - */ - private final Map> instanceChunksGroupMap = new ConcurrentHashMap<>(); - - /** - * Used to know to which instance is linked a Set of chunks - */ - private final Map> instanceInstanceMap = new ConcurrentHashMap<>(); - - @Override - public void onInstanceCreate(@NotNull Instance instance) { - this.instanceChunksGroupMap.putIfAbsent(instance, new Long2ObjectOpenHashMap<>()); - this.instanceInstanceMap.putIfAbsent(instance, new HashMap<>()); - } - - @Override - public void onInstanceDelete(@NotNull Instance instance) { - this.instanceChunksGroupMap.remove(instance); - this.instanceInstanceMap.remove(instance); - } - - @Override - public void onChunkLoad(@NotNull Instance instance, int chunkX, int chunkZ) { - final long loadedChunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ); - - Long2ObjectMap chunksGroupMap = getChunksGroupMap(instance); - Map instanceMap = getInstanceMap(instance); - - // List of groups which are neighbours - List neighboursGroups = new ArrayList<>(); - - final long[] chunks = ChunkUtils.getNeighbours(instance, chunkX, chunkZ); - boolean findGroup = false; - for (long chunkIndex : chunks) { - if (chunksGroupMap.containsKey(chunkIndex)) { - final LongSet group = chunksGroupMap.get(chunkIndex); - neighboursGroups.add(group); - chunksGroupMap.remove(chunkIndex); - instanceMap.remove(group); - findGroup = true; - } - } - - if (!findGroup) { - // Create group of one chunk - LongSet chunkIndexes = new LongArraySet(); - chunkIndexes.add(loadedChunkIndex); - - chunksGroupMap.put(loadedChunkIndex, chunkIndexes); - instanceMap.put(chunkIndexes, instance); - - return; - } - - // The size of the final list, used as the initial capacity - final int size = neighboursGroups.stream().mapToInt(Set::size).sum() + 1; - - // Represent the merged group of all the neighbours - LongSet finalGroup = new LongArraySet(size); - - // Add the newly loaded chunk to the group - finalGroup.add(loadedChunkIndex); - - // Add all the neighbours groups to the final one - for (LongSet chunkCoordinates : neighboursGroups) { - finalGroup.addAll(chunkCoordinates); - } - - // Complete maps - for (long index : finalGroup) { - chunksGroupMap.put(index, finalGroup); - } - - instanceMap.put(finalGroup, instance); - - } - - @Override - public void onChunkUnload(@NotNull Instance instance, int chunkX, int chunkZ) { - Long2ObjectMap chunksGroupMap = getChunksGroupMap(instance); - Map instanceMap = getInstanceMap(instance); - - final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ); - if (chunksGroupMap.containsKey(chunkIndex)) { - // The unloaded chunk is part of a group, remove it from the group - LongSet chunkCoordinates = chunksGroupMap.get(chunkIndex); - chunkCoordinates.remove(chunkIndex); - chunksGroupMap.remove(chunkIndex); - - if (chunkCoordinates.isEmpty()) { - // The chunk group is empty, remove it entirely - instanceMap.entrySet().removeIf(entry -> entry.getKey().isEmpty()); - } - } - } - - @NotNull - @Override - public List> update(long time) { - - List> futures; - int potentialSize = 0; - - // Compute the potential array size - { - for (Map longSetInstanceMap : instanceInstanceMap.values()) { - potentialSize += 1 + longSetInstanceMap.size(); - } - futures = new ArrayList<>(potentialSize); - } - - instanceInstanceMap.forEach((instance, instanceMap) -> { - - // True if the instance ended its tick call - final CountDownLatch countDownLatch = new CountDownLatch(1); - - // instance tick - futures.add(pool.submit(() -> { - updateInstance(instance, time); - countDownLatch.countDown(); - })); - - // Update all the chunks - instanceMap.keySet().forEach(chunksIndexes -> futures.add(pool.submit(() -> { - // Wait for the instance to be updated - // Needed because the instance tick is used to unload waiting chunks - try { - countDownLatch.await(); - } catch (InterruptedException e) { - MinecraftServer.getExceptionManager().handleException(e); - } - - // Tick all this chunk group - chunksIndexes.forEach((long chunkIndex) -> processChunkTick(instance, chunkIndex, time)); - }))); - }); - - return futures; - } - - private Long2ObjectMap getChunksGroupMap(Instance instance) { - return instanceChunksGroupMap.computeIfAbsent(instance, inst -> new Long2ObjectOpenHashMap<>()); - } - - private Map getInstanceMap(Instance instance) { - return instanceInstanceMap.computeIfAbsent(instance, inst -> new HashMap<>()); - } - -} diff --git a/src/main/java/net/minestom/server/thread/PerInstanceThreadProvider.java b/src/main/java/net/minestom/server/thread/PerInstanceThreadProvider.java index bf5e5c8a3..d1b3a9065 100644 --- a/src/main/java/net/minestom/server/thread/PerInstanceThreadProvider.java +++ b/src/main/java/net/minestom/server/thread/PerInstanceThreadProvider.java @@ -1,15 +1,14 @@ package net.minestom.server.thread; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongSet; +import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; -import net.minestom.server.utils.chunk.ChunkUtils; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; /** @@ -17,11 +16,11 @@ import java.util.concurrent.Future; */ public class PerInstanceThreadProvider extends ThreadProvider { - private final Map instanceChunkMap = new HashMap<>(); + private final Map> instanceChunkMap = new ConcurrentHashMap<>(); @Override public void onInstanceCreate(@NotNull Instance instance) { - this.instanceChunkMap.putIfAbsent(instance, new LongArraySet()); + this.instanceChunkMap.putIfAbsent(instance, ConcurrentHashMap.newKeySet()); } @Override @@ -30,20 +29,16 @@ public class PerInstanceThreadProvider extends ThreadProvider { } @Override - public void onChunkLoad(@NotNull Instance instance, int chunkX, int chunkZ) { + public void onChunkLoad(@NotNull Instance instance, @NotNull Chunk chunk) { // Add the loaded chunk to the instance chunks list - LongSet chunkCoordinates = getChunkCoordinates(instance); - final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ); - chunkCoordinates.add(index); + Set chunks = getChunks(instance); + chunks.add(chunk); } @Override - public void onChunkUnload(@NotNull Instance instance, int chunkX, int chunkZ) { - LongSet chunkCoordinates = getChunkCoordinates(instance); - final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ); - // Remove the unloaded chunk from the instance list - chunkCoordinates.remove(index); - + public void onChunkUnload(@NotNull Instance instance, @NotNull Chunk chunk) { + Set chunks = getChunks(instance); + chunks.remove(chunk); } @NotNull @@ -51,17 +46,19 @@ public class PerInstanceThreadProvider extends ThreadProvider { public List> update(long time) { List> futures = new ArrayList<>(); - instanceChunkMap.forEach((instance, chunkIndexes) -> futures.add(pool.submit(() -> { + instanceChunkMap.forEach((instance, chunks) -> futures.add(pool.submit(() -> { // Tick instance updateInstance(instance, time); // Tick chunks - chunkIndexes.forEach((long chunkIndex) -> processChunkTick(instance, chunkIndex, time)); + for (Chunk chunk : chunks) { + processChunkTick(instance, chunk, time); + } }))); return futures; } - private LongSet getChunkCoordinates(Instance instance) { - return instanceChunkMap.computeIfAbsent(instance, inst -> new LongArraySet()); + private Set getChunks(Instance instance) { + return instanceChunkMap.computeIfAbsent(instance, inst -> ConcurrentHashMap.newKeySet()); } } diff --git a/src/main/java/net/minestom/server/thread/SingleThreadProvider.java b/src/main/java/net/minestom/server/thread/SingleThreadProvider.java index 49d6eb8a2..d1c02082c 100644 --- a/src/main/java/net/minestom/server/thread/SingleThreadProvider.java +++ b/src/main/java/net/minestom/server/thread/SingleThreadProvider.java @@ -2,7 +2,6 @@ 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 org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -33,12 +32,12 @@ public class SingleThreadProvider extends ThreadProvider { } @Override - public void onChunkLoad(@NotNull Instance instance, int chunkX, int chunkZ) { + public void onChunkLoad(@NotNull Instance instance, @NotNull Chunk chunk) { } @Override - public void onChunkUnload(@NotNull Instance instance, int chunkX, int chunkZ) { + public void onChunkUnload(@NotNull Instance instance, @NotNull Chunk chunk) { } @@ -49,8 +48,7 @@ public class SingleThreadProvider extends ThreadProvider { for (Instance instance : instances) { updateInstance(instance, time); for (Chunk chunk : instance.getChunks()) { - final long index = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ()); - processChunkTick(instance, index, time); + processChunkTick(instance, chunk, time); } } })); diff --git a/src/main/java/net/minestom/server/thread/ThreadProvider.java b/src/main/java/net/minestom/server/thread/ThreadProvider.java index 7ed136228..937fb3237 100644 --- a/src/main/java/net/minestom/server/thread/ThreadProvider.java +++ b/src/main/java/net/minestom/server/thread/ThreadProvider.java @@ -61,19 +61,17 @@ public abstract class ThreadProvider { * Be aware that this is possible for an instance to load chunks before being registered. * * @param instance the instance of the chunk - * @param chunkX the chunk X - * @param chunkZ the chunk Z + * @param chunk the loaded chunk */ - public abstract void onChunkLoad(@NotNull Instance instance, int chunkX, int chunkZ); + public abstract void onChunkLoad(@NotNull Instance instance, @NotNull Chunk chunk); /** * Called when a chunk is unloaded. * * @param instance the instance of the chunk - * @param chunkX the chunk X - * @param chunkZ the chunk Z + * @param chunk the unloaded chunk */ - public abstract void onChunkUnload(@NotNull Instance instance, int chunkX, int chunkZ); + public abstract void onChunkUnload(@NotNull Instance instance, @NotNull Chunk chunk); /** * Performs a server tick for all chunks based on their linked thread. @@ -115,20 +113,15 @@ public abstract class ThreadProvider { /** * Processes a whole tick for a chunk. * - * @param instance the instance of the chunk - * @param chunkIndex the index of the chunk {@link ChunkUtils#getChunkIndex(int, int)} - * @param time the time of the update in milliseconds + * @param instance the instance of the chunk + * @param chunk the chunk to update + * @param time the time of the update in milliseconds */ - protected void processChunkTick(@NotNull Instance instance, long chunkIndex, long time) { - final int chunkX = ChunkUtils.getChunkCoordX(chunkIndex); - final int chunkZ = ChunkUtils.getChunkCoordZ(chunkIndex); - - final Chunk chunk = instance.getChunk(chunkX, chunkZ); + protected void processChunkTick(@NotNull Instance instance, @NotNull Chunk chunk, long time) { if (!ChunkUtils.isLoaded(chunk)) return; updateChunk(instance, chunk, time); - updateEntities(instance, chunk, time); } @@ -221,13 +214,15 @@ public abstract class ThreadProvider { */ protected void conditionalEntityUpdate(@NotNull Instance instance, @NotNull Chunk chunk, long time, @Nullable EntityValidator condition) { - final Set entities = instance.getChunkEntities(chunk); + if (!instance.getEntities().isEmpty()) { + final Set entities = instance.getChunkEntities(chunk); - if (!entities.isEmpty()) { - for (Entity entity : entities) { - if (condition != null && !condition.isValid(entity)) - continue; - entity.tick(time); + if (!entities.isEmpty()) { + for (Entity entity : entities) { + if (condition != null && !condition.isValid(entity)) + continue; + entity.tick(time); + } } } diff --git a/src/main/java/net/minestom/server/utils/NamespaceID.java b/src/main/java/net/minestom/server/utils/NamespaceID.java index 7e51559aa..8cad56e8f 100644 --- a/src/main/java/net/minestom/server/utils/NamespaceID.java +++ b/src/main/java/net/minestom/server/utils/NamespaceID.java @@ -2,7 +2,6 @@ package net.minestom.server.utils; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.kyori.adventure.key.Key; -import net.kyori.adventure.key.Keyed; import org.jetbrains.annotations.NotNull; import java.util.Objects; @@ -11,7 +10,7 @@ import java.util.Objects; * Represents a namespaced ID * https://minecraft.gamepedia.com/Namespaced_ID */ -public class NamespaceID implements CharSequence, Keyed { +public class NamespaceID implements CharSequence, Key { private static final Int2ObjectOpenHashMap cache = new Int2ObjectOpenHashMap<>(); private static final String legalLetters = "[0123456789abcdefghijklmnopqrstuvwxyz_-]+"; private static final String legalPathLetters = "[0123456789abcdefghijklmnopqrstuvwxyz./_-]+"; @@ -19,7 +18,6 @@ public class NamespaceID implements CharSequence, Keyed { private final String domain; private final String path; private final String full; - private final Key key; /** * Extracts the domain from the namespace ID. "minecraft:stone" would return "minecraft". @@ -80,7 +78,6 @@ public class NamespaceID implements CharSequence, Keyed { } this.full = toString(); validate(); - this.key = Key.key(this.domain, this.path); } private NamespaceID(String domain, String path) { @@ -88,7 +85,6 @@ public class NamespaceID implements CharSequence, Keyed { this.path = path; this.full = toString(); validate(); - this.key = Key.key(this.domain, this.path); } private void validate() { @@ -141,7 +137,17 @@ public class NamespaceID implements CharSequence, Keyed { } @Override - public @NotNull Key key() { - return this.key; + public @NotNull String namespace() { + return this.domain; + } + + @Override + public @NotNull String value() { + return this.path; + } + + @Override + public @NotNull String asString() { + return this.full; } } diff --git a/src/main/java/net/minestom/server/utils/Position.java b/src/main/java/net/minestom/server/utils/Position.java index 238647e3a..2faf754b7 100644 --- a/src/main/java/net/minestom/server/utils/Position.java +++ b/src/main/java/net/minestom/server/utils/Position.java @@ -20,7 +20,7 @@ public class Position implements PublicCloneable { this.x = x; this.y = y; this.z = z; - this.yaw = yaw; + this.yaw = fixYaw(yaw); this.pitch = pitch; } @@ -356,7 +356,24 @@ public class Position implements PublicCloneable { * @param yaw the new yaw */ public void setYaw(float yaw) { - this.yaw = yaw; + this.yaw = fixYaw(yaw); + } + + /** + * Fixes a yaw value that is not between -180.0F and 180.0F + * So for example -1355.0F becomes 85.0F and 225.0F becomes -135.0F + * + * @param yaw The possible "wrong" yaw + * @return a fixed yaw + */ + private float fixYaw(float yaw) { + yaw = yaw % 360; + if(yaw < -180.0F) { + yaw += 360.0F; + } else if(yaw > 180.0F) { + yaw -= 360.0F; + } + return yaw; } /** diff --git a/src/main/java/net/minestom/server/utils/binary/BinaryReader.java b/src/main/java/net/minestom/server/utils/binary/BinaryReader.java index a547228b9..596e12e86 100644 --- a/src/main/java/net/minestom/server/utils/binary/BinaryReader.java +++ b/src/main/java/net/minestom/server/utils/binary/BinaryReader.java @@ -102,13 +102,19 @@ public class BinaryReader extends InputStream { * * @param maxLength the max length of the string * @return the string - * @throws IllegalStateException if the string length is higher than {@code maxLength} + * @throws IllegalStateException if the string length is invalid or higher than {@code maxLength} */ public String readSizedString(int maxLength) { final int length = readVarInt(); - Check.stateCondition(length > maxLength, + Check.stateCondition(!buffer.isReadable(length), + "Trying to read a string that is too long (wanted {0}, only have {1})", + length, + buffer.readableBytes()); + final String str = buffer.toString(buffer.readerIndex(), length, StandardCharsets.UTF_8); + buffer.skipBytes(length); + Check.stateCondition(str.length() > maxLength, "String length ({0}) was higher than the max length of {1}", length, maxLength); - return buffer.readCharSequence(length, StandardCharsets.UTF_8).toString(); + return str; } public byte[] readBytes(int length) { @@ -146,7 +152,7 @@ public class BinaryReader extends InputStream { } public byte[] readRemainingBytes() { - return readBytes(buffer.readableBytes()); + return readBytes(available()); } public BlockPosition readBlockPosition() { @@ -195,13 +201,13 @@ public class BinaryReader extends InputStream { } /** - * Creates a new object from the given supplier and calls its {@link Readable#read(BinaryReader)} method with this reader + * Creates a new object from the given supplier and calls its {@link Readable#read(BinaryReader)} method with this reader. * * @param supplier supplier to create new instances of your object - * @param + * @param the readable object type * @return the read object */ - public T read(Supplier supplier) { + public T read(@NotNull Supplier<@NotNull T> supplier) { T result = supplier.get(); result.read(this); return result; @@ -212,16 +218,16 @@ public class BinaryReader extends InputStream { * their respective {@link Readable#read(BinaryReader)} methods. * * @param supplier supplier to create new instances of your object - * @param + * @param the readable object type * @return the read objects */ - public T[] readArray(Supplier supplier) { - T[] result = (T[]) new Object[readVarInt()]; + public @NotNull T[] readArray(@NotNull Supplier<@NotNull T> supplier) { + Readable[] result = new Readable[readVarInt()]; for (int i = 0; i < result.length; i++) { result[i] = supplier.get(); result[i].read(this); } - return result; + return (T[]) result; } public ByteBuf getBuffer() { diff --git a/src/main/java/net/minestom/server/utils/binary/BinaryWriter.java b/src/main/java/net/minestom/server/utils/binary/BinaryWriter.java index 0c9f1a90f..152f65268 100644 --- a/src/main/java/net/minestom/server/utils/binary/BinaryWriter.java +++ b/src/main/java/net/minestom/server/utils/binary/BinaryWriter.java @@ -281,17 +281,21 @@ public class BinaryWriter extends OutputStream { * * @param writeable the object to write */ - public void write(Writeable writeable) { + public void write(@NotNull Writeable writeable) { writeable.write(this); } + public void write(@NotNull BinaryWriter writer) { + this.buffer.writeBytes(writer.getBuffer()); + } + /** * Writes an array of writeable objects to this writer. Will prepend the binary stream with a var int to denote the * length of the array. * * @param writeables the array of writeables to write */ - public void writeArray(Writeable[] writeables) { + public void writeArray(@NotNull Writeable[] writeables) { writeVarInt(writeables.length); for (Writeable w : writeables) { write(w); @@ -343,7 +347,7 @@ public class BinaryWriter extends OutputStream { * * @return the raw buffer */ - public ByteBuf getBuffer() { + public @NotNull ByteBuf getBuffer() { return buffer; } @@ -368,7 +372,7 @@ public class BinaryWriter extends OutputStream { /** * Returns a byte[] with the contents written via BinaryWriter */ - public static byte[] makeArray(Consumer writing) { + public static byte[] makeArray(@NotNull Consumer<@NotNull BinaryWriter> writing) { BinaryWriter writer = new BinaryWriter(); writing.accept(writer); return writer.toByteArray(); diff --git a/src/main/java/net/minestom/server/utils/cache/CacheablePacket.java b/src/main/java/net/minestom/server/utils/cache/CacheablePacket.java index b8507164e..86050351d 100644 --- a/src/main/java/net/minestom/server/utils/cache/CacheablePacket.java +++ b/src/main/java/net/minestom/server/utils/cache/CacheablePacket.java @@ -46,6 +46,9 @@ public interface CacheablePacket { @Nullable static FramedPacket getCache(@NotNull ServerPacket serverPacket) { + if (!(serverPacket instanceof CacheablePacket)) + return null; + final CacheablePacket cacheablePacket = (CacheablePacket) serverPacket; final UUID identifier = cacheablePacket.getIdentifier(); if (identifier == null) { @@ -72,4 +75,20 @@ public interface CacheablePacket { } } + static void writeCache(@NotNull ByteBuf buffer, @NotNull ServerPacket serverPacket) { + FramedPacket framedPacket = CacheablePacket.getCache(serverPacket); + if (framedPacket == null) { + PacketUtils.writeFramedPacket(buffer, serverPacket); + return; + } + final ByteBuf body = framedPacket.getBody(); + synchronized (body) { + if (framedPacket.getBody().refCnt() != 0) { + buffer.writeBytes(body, body.readerIndex(), body.readableBytes()); + } else { + PacketUtils.writeFramedPacket(buffer, serverPacket); + } + } + } + } diff --git a/src/main/java/net/minestom/server/utils/cache/TemporaryPacketCache.java b/src/main/java/net/minestom/server/utils/cache/TemporaryPacketCache.java new file mode 100644 index 000000000..6d6fe1d5e --- /dev/null +++ b/src/main/java/net/minestom/server/utils/cache/TemporaryPacketCache.java @@ -0,0 +1,16 @@ +package net.minestom.server.utils.cache; + +import io.netty.buffer.ByteBuf; + +import java.util.concurrent.TimeUnit; + +public class TemporaryPacketCache extends TemporaryCache { + public TemporaryPacketCache(long duration, TimeUnit timeUnit) { + super(duration, timeUnit, notification -> { + final ByteBuf buffer = notification.getValue().getBuffer(); + synchronized (buffer) { + buffer.release(); + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/net/minestom/server/utils/location/RelativeBlockPosition.java b/src/main/java/net/minestom/server/utils/location/RelativeBlockPosition.java index 372597b95..b1b183e77 100644 --- a/src/main/java/net/minestom/server/utils/location/RelativeBlockPosition.java +++ b/src/main/java/net/minestom/server/utils/location/RelativeBlockPosition.java @@ -1,6 +1,5 @@ package net.minestom.server.utils.location; -import net.minestom.server.entity.Entity; import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.Position; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/net/minestom/server/utils/location/RelativeVec.java b/src/main/java/net/minestom/server/utils/location/RelativeVec.java index ad3e838a9..42d948c84 100644 --- a/src/main/java/net/minestom/server/utils/location/RelativeVec.java +++ b/src/main/java/net/minestom/server/utils/location/RelativeVec.java @@ -1,6 +1,5 @@ package net.minestom.server.utils.location; -import net.minestom.server.entity.Entity; import net.minestom.server.utils.Position; import net.minestom.server.utils.Vector; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/net/minestom/server/utils/time/UpdateOption.java b/src/main/java/net/minestom/server/utils/time/UpdateOption.java index 37ccd6361..c190330fd 100644 --- a/src/main/java/net/minestom/server/utils/time/UpdateOption.java +++ b/src/main/java/net/minestom/server/utils/time/UpdateOption.java @@ -2,6 +2,8 @@ package net.minestom.server.utils.time; import org.jetbrains.annotations.NotNull; +import java.util.Objects; + public class UpdateOption { private final long value; @@ -20,4 +22,17 @@ public class UpdateOption { public TimeUnit getTimeUnit() { return timeUnit; } + + @Override + public int hashCode() { + return Objects.hash(value, timeUnit); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UpdateOption updateOption = (UpdateOption) o; + return Objects.equals(value, updateOption.value) && Objects.equals(timeUnit, updateOption.timeUnit); + } } diff --git a/src/main/java/net/minestom/server/utils/validate/Check.java b/src/main/java/net/minestom/server/utils/validate/Check.java index 2b6827bd3..14404cf7a 100644 --- a/src/main/java/net/minestom/server/utils/validate/Check.java +++ b/src/main/java/net/minestom/server/utils/validate/Check.java @@ -37,6 +37,13 @@ public final class Check { } } + @Contract("true, _, _ -> fail") + public static void argCondition(boolean condition, @NotNull String reason, Object... arguments) { + if (condition) { + throw new IllegalArgumentException(MessageFormat.format(reason, arguments)); + } + } + @Contract("_ -> fail") public static void fail(@NotNull String reason) { throw new IllegalArgumentException(reason); diff --git a/src/test/java/demo/commands/EntitySelectorCommand.java b/src/test/java/demo/commands/EntitySelectorCommand.java index 178d63931..35e044f81 100644 --- a/src/test/java/demo/commands/EntitySelectorCommand.java +++ b/src/test/java/demo/commands/EntitySelectorCommand.java @@ -6,7 +6,6 @@ import net.minestom.server.command.builder.CommandContext; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.arguments.minecraft.ArgumentEntity; import net.minestom.server.entity.Entity; -import net.minestom.server.instance.Instance; import net.minestom.server.utils.entity.EntityFinder; import java.util.List; diff --git a/src/test/java/demo/commands/ReloadExtensionCommand.java b/src/test/java/demo/commands/ReloadExtensionCommand.java index 898251957..dfadd78b3 100644 --- a/src/test/java/demo/commands/ReloadExtensionCommand.java +++ b/src/test/java/demo/commands/ReloadExtensionCommand.java @@ -5,7 +5,6 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.command.CommandSender; import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.CommandContext; -import net.minestom.server.command.builder.arguments.Argument; import net.minestom.server.command.builder.arguments.ArgumentString; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.exception.ArgumentSyntaxException; diff --git a/src/test/java/demo/commands/SummonCommand.java b/src/test/java/demo/commands/SummonCommand.java index 3ee4dd736..0e03ef215 100644 --- a/src/test/java/demo/commands/SummonCommand.java +++ b/src/test/java/demo/commands/SummonCommand.java @@ -4,7 +4,6 @@ import net.minestom.server.command.CommandSender; import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.CommandContext; import net.minestom.server.command.builder.arguments.ArgumentType; -import net.minestom.server.command.builder.arguments.minecraft.ArgumentEntity; import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEntityType; import net.minestom.server.command.builder.arguments.relative.ArgumentRelativeVec3; import net.minestom.server.command.builder.condition.Conditions; diff --git a/src/test/java/demo/commands/UnloadExtensionCommand.java b/src/test/java/demo/commands/UnloadExtensionCommand.java index 115242638..4f686adaf 100644 --- a/src/test/java/demo/commands/UnloadExtensionCommand.java +++ b/src/test/java/demo/commands/UnloadExtensionCommand.java @@ -5,13 +5,11 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.command.CommandSender; import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.CommandContext; -import net.minestom.server.command.builder.arguments.Argument; -import net.minestom.server.command.builder.arguments.ArgumentString; +import net.minestom.server.command.builder.arguments.ArgumentMap; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.exception.ArgumentSyntaxException; import net.minestom.server.extensions.Extension; import net.minestom.server.extensions.ExtensionManager; -import org.apache.commons.lang3.StringUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -20,14 +18,20 @@ import java.nio.charset.StandardCharsets; public class UnloadExtensionCommand extends Command { - private final ArgumentString extensionName; + private final ArgumentMap extensionName; public UnloadExtensionCommand() { super("unload"); setDefaultExecutor(this::usage); - extensionName = ArgumentType.String("extensionName"); + extensionName = ArgumentType.String("extensionName").map((input) -> { + Extension extension = MinecraftServer.getExtensionManager().getExtension(input); + + if (extension == null) throw new ArgumentSyntaxException("The specified extension was not found", input, 1); + + return extension; + }); setArgumentCallback(this::extensionCallback, extensionName); @@ -39,29 +43,25 @@ public class UnloadExtensionCommand extends Command { } private void execute(CommandSender sender, CommandContext context) { - final String name = context.get(extensionName); - sender.sendMessage(Component.text("extensionName = " + name + "....")); + final Extension ext = context.get(extensionName); + sender.sendMessage(Component.text("extensionName = " + ext.getOrigin().getName() + "....")); ExtensionManager extensionManager = MinecraftServer.getExtensionManager(); - Extension ext = extensionManager.getExtension(name); - if (ext != null) { + + try { + extensionManager.unloadExtension(ext.getOrigin().getName()); + } catch (Throwable t) { try { - extensionManager.unloadExtension(name); - } catch (Throwable t) { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - t.printStackTrace(); - t.printStackTrace(new PrintStream(baos)); - baos.flush(); - baos.close(); - String contents = baos.toString(StandardCharsets.UTF_8); - contents.lines().map(Component::text).forEach(sender::sendMessage); - } catch (IOException e) { - e.printStackTrace(); - } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + t.printStackTrace(); + t.printStackTrace(new PrintStream(baos)); + baos.flush(); + baos.close(); + String contents = baos.toString(StandardCharsets.UTF_8); + contents.lines().map(Component::text).forEach(sender::sendMessage); + } catch (IOException e) { + e.printStackTrace(); } - } else { - sender.sendMessage(Component.text("Extension '" + name + "' does not exist.")); } } diff --git a/src/test/java/improveextensions/unloadextensiononstop/UnloadExtensionOnStop.java b/src/test/java/improveextensions/unloadextensiononstop/UnloadExtensionOnStop.java index 7491c2e8a..f2e3c6358 100644 --- a/src/test/java/improveextensions/unloadextensiononstop/UnloadExtensionOnStop.java +++ b/src/test/java/improveextensions/unloadextensiononstop/UnloadExtensionOnStop.java @@ -1,20 +1,9 @@ package improveextensions.unloadextensiononstop; import net.minestom.server.MinecraftServer; -import net.minestom.server.entity.type.monster.EntityZombie; -import net.minestom.server.event.EventCallback; -import net.minestom.server.event.GlobalEventHandler; -import net.minestom.server.event.entity.EntityTickEvent; -import net.minestom.server.event.instance.InstanceTickEvent; import net.minestom.server.extensions.Extension; -import net.minestom.server.extras.selfmodification.MinestomRootClassLoader; -import net.minestom.server.instance.Instance; -import net.minestom.server.utils.Position; import net.minestom.server.utils.time.TimeUnit; import org.junit.jupiter.api.Assertions; -import org.opentest4j.AssertionFailedError; - -import java.util.concurrent.atomic.AtomicBoolean; public class UnloadExtensionOnStop extends Extension { diff --git a/src/test/java/testextension/TestExtensionLauncherNoSetup.java b/src/test/java/testextension/TestExtensionLauncherNoSetup.java index ef4b757fe..16e2d5e66 100644 --- a/src/test/java/testextension/TestExtensionLauncherNoSetup.java +++ b/src/test/java/testextension/TestExtensionLauncherNoSetup.java @@ -1,8 +1,6 @@ package testextension; import net.minestom.server.Bootstrap; -import org.spongepowered.asm.launch.MixinBootstrap; -import org.spongepowered.asm.mixin.Mixins; // To launch with VM arguments: // -Dminestom.extension.indevfolder.classes=build/classes/java/test/ -Dminestom.extension.indevfolder.resources=build/resources/test/ diff --git a/src/test/java/testextension/mixins/InstanceContainerMixin.java b/src/test/java/testextension/mixins/InstanceContainerMixin.java index b3299afbd..7bed56a2c 100644 --- a/src/test/java/testextension/mixins/InstanceContainerMixin.java +++ b/src/test/java/testextension/mixins/InstanceContainerMixin.java @@ -1,13 +1,9 @@ package testextension.mixins; -import net.minestom.server.data.Data; import net.minestom.server.instance.InstanceContainer; -import net.minestom.server.instance.block.Block; -import net.minestom.server.instance.block.CustomBlock; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InstanceContainer.class)