More comments for the command API

This commit is contained in:
themode 2020-10-11 15:27:23 +02:00
parent d2d0fd33d8
commit f2004f1ecd
19 changed files with 160 additions and 42 deletions

View File

@ -4,10 +4,14 @@ import fr.themode.demo.blocks.StoneBlock;
import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.demo.generator.NoiseTestGenerator;
import net.minestom.server.MinecraftServer;
import net.minestom.server.attribute.Attribute;
import net.minestom.server.attribute.AttributeOperation;
import net.minestom.server.benchmark.BenchmarkManager;
import net.minestom.server.benchmark.ThreadResult;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ChatHoverEvent;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.chat.RichMessage;
import net.minestom.server.data.Data;
import net.minestom.server.entity.*;
import net.minestom.server.entity.damage.DamageType;
@ -24,14 +28,15 @@ import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.Enchantment;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.attribute.AttributeSlot;
import net.minestom.server.item.attribute.ItemAttribute;
import net.minestom.server.item.metadata.MapMeta;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.ping.ResponseDataConsumer;
import net.minestom.server.scoreboard.Sidebar;
import net.minestom.server.storage.StorageLocation;
import net.minestom.server.storage.StorageOptions;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Position;
@ -48,17 +53,17 @@ public class PlayerInit {
private static volatile Inventory inventory;
static {
StorageLocation storageLocation = MinecraftServer.getStorageManager().getLocation("instance_data", new StorageOptions().setCompression(true));
//StorageLocation storageLocation = MinecraftServer.getStorageManager().getLocation("instance_data", new StorageOptions().setCompression(true));
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
NoiseTestGenerator noiseTestGenerator = new NoiseTestGenerator();
instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.OVERWORLD, storageLocation);
instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.OVERWORLD);
instanceContainer.enableAutoChunkLoad(true);
//instanceContainer.setChunkDecider((x,y) -> (pos) -> pos.getY()>40?(short)0:(short)1);
instanceContainer.setChunkGenerator(noiseTestGenerator);
// Load some chunks beforehand
final int loopStart = -10;
final int loopEnd = 10;
final int loopStart = -3;
final int loopEnd = 3;
for (int x = loopStart; x < loopEnd; x++)
for (int z = loopStart; z < loopEnd; z++) {
instanceContainer.loadChunk(x, z);
@ -70,7 +75,7 @@ public class PlayerInit {
System.out.println("slot inv: " + slot);
inventoryConditionResult.setCancel(false);
});
inventory.setItemStack(0, new ItemStack(Material.DIAMOND, (byte) 34));
//inventory.setItemStack(0, new ItemStack(Material.DIAMOND, (byte) 34));
}
public static void init() {
@ -266,8 +271,25 @@ public class PlayerInit {
//player.setHeldItemSlot((byte) 5);
ColoredText coloredText = ColoredText.of(ChatColor.RED + "" + ChatColor.BOLD + " test" + ChatColor.BRIGHT_GREEN + " lol");
coloredText.append("test");
player.sendMessage(coloredText);
System.out.println(coloredText.toString());
{
RichMessage richMessage = RichMessage.of(ColoredText.of(ChatColor.RED + " HEY MESSAGE"));
richMessage.setHoverEvent(ChatHoverEvent.showItem(new ItemStack(Material.STONE, (byte) 5)));
//player.sendMessage(richMessage);
}
player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 1));
player.setGlowing(true);
player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 127));
ItemStack stone = new ItemStack(Material.DIAMOND_SWORD, (byte) 127);
stone.setEnchantment(Enchantment.AQUA_AFFINITY, (short) 1);
stone.addAttribute(new ItemAttribute(UUID.randomUUID(),
"test_name",
Attribute.ATTACK_DAMAGE, AttributeOperation.ADDITION, 50, AttributeSlot.MAINHAND));
player.getInventory().addItemStack(stone);
/*for (int i = 0; i < 9; i++) {
player.getInventory().setItemStack(i, new ItemStack(Material.STONE, (byte) 127));
}*/
@ -293,11 +315,11 @@ public class PlayerInit {
//item.getLore().add(ColoredText.of(ChatColor.RED + "a lore line " + ChatColor.BLACK + " BLACK"));
//item.addItemFlags(ItemFlag.HIDE_ENCHANTS);
//item.setEnchantment(Enchantment.SHARPNESS, (short) 50);
player.getInventory().addItemStack(item);
//player.getInventory().addItemStack(item);
player.setHelmet(new ItemStack(Material.DIAMOND_HELMET, (byte) 1));
//player.setHelmet(new ItemStack(Material.DIAMOND_HELMET, (byte) 1));
inventory.addItemStack(item.clone());
//inventory.addItemStack(item.clone());
//player.openInventory(inventory);
//player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 100));
@ -342,6 +364,10 @@ public class PlayerInit {
event.setRespawnPosition(new Position(0f, 75f, 0f));
});
player.addEventCallback(PlayerStartDiggingEvent.class, event -> {
//event.setCancelled(true);
});
player.addEventCallback(PlayerCommandEvent.class, event -> {
System.out.println("COMMAND EVENT");
});

View File

@ -42,7 +42,7 @@ public class StoneBlock extends CustomBlock {
@Override
public int getBreakDelay(Player player, BlockPosition position, byte stage, Set<Player> breakers) {
return -2;
return 2;
}
@Override

View File

@ -30,7 +30,7 @@ public class GamemodeCommand extends Command {
}
Argument mode = ArgumentType.Word("mode").from(names);
addCallback(this::gameModeCallback, mode);
setArgumentCallback(this::gameModeCallback, mode);
addSyntax(this::executeOnSelf, mode);
addSyntax(this::executeOnOther, player, mode);

View File

@ -21,8 +21,8 @@ public class HealthCommand extends Command {
Argument arg1 = ArgumentType.Integer("value").between(0, 100);
addCallback(this::modeCallback, arg0);
addCallback(this::valueCallback, arg1);
setArgumentCallback(this::modeCallback, arg0);
setArgumentCallback(this::valueCallback, arg1);
addSyntax(this::execute2, arg0, arg1);
addSyntax(this::execute, arg0);

View File

@ -20,7 +20,7 @@ public class SimpleCommand implements CommandProcessor {
if (!sender.isPlayer())
return false;
sender.asPlayer().getInstance().saveChunksToStorage(() -> System.out.println("END SAVE"));
//sender.asPlayer().getInstance().saveChunksToStorage(() -> System.out.println("END SAVE"));
System.gc();

View File

@ -18,7 +18,7 @@ public class TeleportCommand extends Command {
Argument z = ArgumentType.Float("z");
Argument playerArg = ArgumentType.Word("pl");
addCallback((source, value, error) -> {
setArgumentCallback((source, value, error) -> {
System.out.println("error: " + error);
}, x);

View File

@ -12,10 +12,21 @@ public class TestCommand extends Command {
public TestCommand() {
super("testcmd");
setDefaultExecutor(this::usage);
{
//Argument dynamicWord = ArgumentType.DynamicWord("test");
Argument dynamicWord = ArgumentType.DynamicWord("test");
//addSyntax(this::execute, dynamicWord);
}
addSyntax(this::execute, dynamicWord);
Argument test = ArgumentType.Word("test").from("hey");
Argument num = ArgumentType.Integer("num");
Argument test2 = ArgumentType.Word("test2").from("oh");
Argument num2 = ArgumentType.Float("num2");
addSyntax((source, args) -> {
}, test, num);
addSyntax((source, args) -> {
}, test2, num2);
}
private void usage(CommandSender sender, Arguments arguments) {

View File

@ -3,8 +3,6 @@ package fr.themode.demo.generator;
import de.articdive.jnoise.JNoise;
import de.articdive.jnoise.interpolation.InterpolationType;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.SerializableData;
import net.minestom.server.data.SerializableDataImpl;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.ChunkGenerator;
import net.minestom.server.instance.ChunkPopulator;
@ -47,9 +45,9 @@ public class NoiseTestGenerator implements ChunkGenerator {
batch.setBlock(x, y, z, Block.GRASS_BLOCK);
} else if (y > height - 7) {
// Data for debugging purpose
SerializableData serializableData = new SerializableDataImpl();
serializableData.set("test", 55, Integer.class);
batch.setBlockStateId(x, y, z, Block.DIRT.getBlockId(), serializableData);
//SerializableData serializableData = new SerializableDataImpl();
//serializableData.set("test", 55, Integer.class);
batch.setBlockStateId(x, y, z, Block.DIRT.getBlockId());
} else {
batch.setBlock(x, y, z, Block.STONE);
}

View File

@ -13,12 +13,16 @@ import java.util.Set;
public interface Viewable {
/**
* Add a viewer
*
* @param player the viewer to add
* @return true if the player has been added, false otherwise (could be because he is already a viewer)
*/
boolean addViewer(Player player);
/**
* Remove a viewer
*
* @param player the viewer to remove
* @return true if the player has been removed, false otherwise (could be because he was not a viewer)
*/
@ -86,6 +90,13 @@ public interface Viewable {
}
}
/**
* Send a packet to all the viewers and 'this'
* <p>
* Unsafe because of a cast to {@link Player} without any check beforehand
*
* @param packet the packet to send
*/
private void UNSAFE_sendPacketToViewersAndSelf(ServerPacket packet) {
Set<Player> recipients = new HashSet<>(getViewers());
recipients.add((Player) this);

View File

@ -1,7 +1,9 @@
package net.minestom.server.bossbar;
/**
* Represents the displayed color of a {@link BossBar}
*/
public enum BarColor {
PINK,
BLUE,
RED,
@ -9,5 +11,4 @@ public enum BarColor {
YELLOW,
PURPLE,
WHITE
}

View File

@ -1,11 +1,12 @@
package net.minestom.server.bossbar;
/**
* Used to define the number of segments on a {@link BossBar}
*/
public enum BarDivision {
SOLID,
SEGMENT_6,
SEGMENT_10,
SEGMENT_12,
SEGMENT_20
}

View File

@ -11,7 +11,11 @@ import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Represent a bossbar which can be showed to any player {@link #addViewer(Player)}
* Represents a boss bar which is displayed on the top of the client screen (max amount of boss bar defined by {@link #MAX_BOSSBAR}).
* <p>
* To use it, create a new instance and add the players you want using {@link #addViewer(Player)} and remove them using {@link #removeViewer(Player)}.
* <p>
* You can retrieve all the boss bars of a player with {@link #getBossBars(Player)}.
*/
public class BossBar implements Viewable {
@ -27,6 +31,13 @@ public class BossBar implements Viewable {
private BarDivision division;
private byte flags;
/**
* Create a new {@link BossBar}
*
* @param title the boss bar title
* @param color the boss bar color
* @param division the boss bar division
*/
public BossBar(ColoredText title, BarColor color, BarDivision division) {
this.title = title;
this.color = color;
@ -34,7 +45,7 @@ public class BossBar implements Viewable {
}
/**
* Get all the visible boss bars of a player
* Get all the visible boss bars of a {@link Player}
*
* @param player the player to check the boss bars
* @return all the visible boss bars of the player, null if not any

View File

@ -4,6 +4,12 @@ import net.minestom.server.entity.Player;
/**
* Represents a simple command which give you the whole string representation
* <p>
* {@link #process(CommandSender, String, String[])} is called no matter what if a {@link CommandSender} sends a command which
* start by {@link #getCommandName()} or any of the aliases in {@link #getAliases()}
* <p>
* Tab-completion can be activated by overriding {@link #enableWritingTracking()} and return true, you should then listen to
* {@link #onWrite(String)} and return the possible completions to suggest.
*/
public interface CommandProcessor {

View File

@ -1,9 +1,10 @@
package net.minestom.server.command.builder;
import net.minestom.server.command.CommandSender;
import net.minestom.server.command.builder.arguments.Argument;
/**
* Callback executed when an error is found within the argument
* Callback executed when an error is found within the {@link Argument}
*/
public interface ArgumentCallback {
@ -11,8 +12,8 @@ public interface ArgumentCallback {
* Executed when an error is found
*
* @param source the sender which executed the command
* @param value the raw argument which gave the error
* @param error the error id (you can check its meaning in the specific argument class)
* @param value the raw string argument which is responsive for the error
* @param error the error id (you can check its meaning in the specific argument class or ask the developer about it)
*/
void apply(CommandSender source, String value, int error);
}

View File

@ -4,6 +4,7 @@ import net.minestom.server.command.CommandSender;
import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.command.builder.arguments.ArgumentDynamicStringArray;
import net.minestom.server.command.builder.arguments.ArgumentDynamicWord;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.command.builder.condition.CommandCondition;
import java.util.ArrayList;
@ -12,6 +13,23 @@ import java.util.List;
/**
* Represents a command which have suggestion/auto-completion
* <p>
* The command works using a list of valid syntaxes.
* For instance we could build the command
* "/health set Notch 50" into multiple argument types -> "/health [set/add/remove] [Username] [Integer]"
* <p>
* All the default argument types can be found in {@link ArgumentType}
* and the syntax be created/registered using {@link #addSyntax(CommandExecutor, Argument[])}.
* <p>
* If the command is executed with an incorrect syntax or without any argument, the default {@link CommandExecutor} will be executed,
* you can set it using {@link #setDefaultExecutor(CommandExecutor)}.
* <p>
* Before any syntax to be successfully executed the {@link CommandSender} needs to validate
* the {@link CommandCondition} sets with {@link #setCondition(CommandCondition)} (ignored if null).
* <p>
* Some {@link Argument} could also require additional condition (eg: a number which need to be between 2 values),
* in this case, if the whole syntax is correct but not the argument condition,
* you can listen to its error code using {@link #setArgumentCallback(ArgumentCallback, Argument)} or {@link Argument#setCallback(ArgumentCallback)}.
*/
public class Command {
@ -22,6 +40,13 @@ public class Command {
private CommandCondition condition;
private List<CommandSyntax> syntaxes;
/**
* Create a {@link Command} with a name and one or multiple aliases
*
* @param name the name of the command
* @param aliases the command aliases
* @see #Command(String)
*/
public Command(String name, String... aliases) {
this.name = name;
this.aliases = aliases;
@ -29,12 +54,18 @@ public class Command {
this.syntaxes = new ArrayList<>();
}
/**
* Create a {@link Command} with a name without any aliases
*
* @param name the name of the command
* @see #Command(String, String...)
*/
public Command(String name) {
this(name, new String[0]);
}
/**
* Get the command condition
* Get the {@link CommandCondition}
* <p>
* It is called no matter the syntax used and can be used to check permissions or
* the {@link CommandSender} type
@ -46,7 +77,7 @@ public class Command {
}
/**
* Set the command condition
* Set the {@link CommandCondition}
*
* @param commandCondition the new command condition
*/
@ -55,14 +86,14 @@ public class Command {
}
/**
* Add an argument callback
* Set an {@link ArgumentCallback}
* <p>
* The argument callback is called when there's an error in the argument
*
* @param callback the callback for the argument
* @param argument the argument which get the callback
*/
public void addCallback(ArgumentCallback callback, Argument argument) {
public void setArgumentCallback(ArgumentCallback callback, Argument argument) {
argument.setCallback(callback);
}
@ -101,7 +132,7 @@ public class Command {
}
/**
* Get the default executor (which is called when there is no argument)
* Get the default {@link CommandExecutor} (which is called when there is no argument)
* or if no corresponding syntax has been found
*
* @return the default executor
@ -111,7 +142,7 @@ public class Command {
}
/**
* Set the default executor (which is called when there is no argument)
* Set the default {@link CommandExecutor} (which is called when there is no argument)
*
* @param executor the new default executor
*/

View File

@ -1,7 +1,15 @@
package net.minestom.server.command.builder.arguments;
import net.minestom.server.command.builder.ArgumentCallback;
import net.minestom.server.command.builder.Command;
/**
* An argument is meant to be parsed when added into a {@link Command} syntax.
* <p>
* You can create your own with your own special conditions.
*
* @param <T> the type of this parsed argument
*/
public abstract class Argument<T> {
public static final int SUCCESS = 0;
@ -93,7 +101,7 @@ public abstract class Argument<T> {
}
/**
* Set the argument callback
* Set the {@link ArgumentCallback}
*
* @param callback the argument callback
*/

View File

@ -11,7 +11,7 @@ import net.minestom.server.command.builder.arguments.number.ArgumentInteger;
import net.minestom.server.command.builder.arguments.number.ArgumentLong;
/**
* Class listing all the basic arguments
* Convenient class listing all the basic {@link Argument}
*/
public class ArgumentType {
@ -55,7 +55,7 @@ public class ArgumentType {
return new ArgumentDynamicStringArray(id);
}
// Minecraft specific
// Minecraft specific arguments
public static ArgumentColor Color(String id) {
return new ArgumentColor(id);
@ -89,6 +89,7 @@ public class ArgumentType {
return new ArgumentFloatRange(id);
}
@Deprecated
public static ArgumentEntities Entities(String id) {
return new ArgumentEntities(id);
}

View File

@ -11,6 +11,7 @@ import net.minestom.server.command.CommandManager;
import net.minestom.server.command.CommandSender;
import net.minestom.server.effects.Effects;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.fakeplayer.FakePlayer;
import net.minestom.server.entity.vehicle.PlayerVehicleInformation;
import net.minestom.server.event.inventory.InventoryOpenEvent;
import net.minestom.server.event.item.ItemDropEvent;
@ -26,10 +27,13 @@ import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.listener.PlayerDiggingListener;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.PlayerProvider;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.login.JoinGamePacket;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.permission.Permission;
import net.minestom.server.recipe.Recipe;
@ -57,6 +61,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
/**
* Those are the major actors of the server, they are not necessary backed by a {@link NettyPlayerConnection} as shown by {@link FakePlayer}
* <p>
* You can easily create your own implementation of this and use it with {@link ConnectionManager#setPlayerProvider(PlayerProvider)}.
*/
public class Player extends LivingEntity implements CommandSender {
private long lastKeepAlive;

View File

@ -21,6 +21,7 @@ import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.player.PlayerUtils;
import net.minestom.server.utils.validate.Check;
@ -36,6 +37,8 @@ import java.util.function.Consumer;
/**
* A chunk is a part of an {@link Instance}, limited by a size of 16x256x16 blocks and subdivided in 16 sections of 16 blocks height.
* Should contains all the blocks located at those positions and manage their tick updates.
* <p>
* You can create your own implementation of this class by extending it and create the objects in {@link InstanceContainer#setChunkSupplier(ChunkSupplier)}.
*/
public abstract class Chunk implements Viewable, DataContainer {