mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-30 21:17:53 +01:00
Merge branch 'master' into zero_cost_event
This commit is contained in:
commit
6a2b48aee2
@ -99,22 +99,17 @@ public final class CommandManager {
|
||||
* @return the execution result
|
||||
*/
|
||||
public @NotNull CommandResult execute(@NotNull CommandSender sender, @NotNull String command) {
|
||||
|
||||
// Command event
|
||||
if (sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
|
||||
final Player player = (Player) sender;
|
||||
PlayerCommandEvent playerCommandEvent = new PlayerCommandEvent(player, command);
|
||||
EventDispatcher.call(playerCommandEvent);
|
||||
|
||||
if (playerCommandEvent.isCancelled())
|
||||
return CommandResult.of(CommandResult.Type.CANCELLED, command);
|
||||
|
||||
command = playerCommandEvent.getCommand();
|
||||
}
|
||||
|
||||
// Process the command
|
||||
final var result = dispatcher.execute(sender, command);
|
||||
final CommandResult result = dispatcher.execute(sender, command);
|
||||
if (result.getType() == CommandResult.Type.UNKNOWN) {
|
||||
if (unknownCommandCallback != null) {
|
||||
this.unknownCommandCallback.apply(sender, command);
|
||||
|
@ -65,8 +65,7 @@ public class CommandDispatcher {
|
||||
this.cache.invalidateAll();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<Command> getCommands() {
|
||||
public @NotNull Set<Command> getCommands() {
|
||||
return Collections.unmodifiableSet(commands);
|
||||
}
|
||||
|
||||
@ -76,8 +75,7 @@ public class CommandDispatcher {
|
||||
* @param commandName the command name
|
||||
* @return the {@link Command} associated with the name, null if not any
|
||||
*/
|
||||
@Nullable
|
||||
public Command findCommand(@NotNull String commandName) {
|
||||
public @Nullable Command findCommand(@NotNull String commandName) {
|
||||
commandName = commandName.toLowerCase();
|
||||
return commandMap.getOrDefault(commandName, null);
|
||||
}
|
||||
@ -89,8 +87,7 @@ public class CommandDispatcher {
|
||||
* @param commandString the command with the argument(s)
|
||||
* @return the command result
|
||||
*/
|
||||
@NotNull
|
||||
public CommandResult execute(@NotNull CommandSender source, @NotNull String commandString) {
|
||||
public @NotNull CommandResult execute(@NotNull CommandSender source, @NotNull String commandString) {
|
||||
CommandResult commandResult = parse(commandString);
|
||||
ParsedCommand parsedCommand = commandResult.parsedCommand;
|
||||
if (parsedCommand != null) {
|
||||
@ -105,10 +102,8 @@ public class CommandDispatcher {
|
||||
* @param commandString the command (containing the command name and the args if any)
|
||||
* @return the parsing result
|
||||
*/
|
||||
@NotNull
|
||||
public CommandResult parse(@NotNull String commandString) {
|
||||
public @NotNull CommandResult parse(@NotNull String commandString) {
|
||||
commandString = commandString.trim();
|
||||
|
||||
// Verify if the result is cached
|
||||
{
|
||||
final CommandResult cachedResult = cache.getIfPresent(commandString);
|
||||
@ -134,18 +129,15 @@ public class CommandDispatcher {
|
||||
findParsedCommand(command, commandName, commandQueryResult.args, commandString, result);
|
||||
|
||||
// Cache result
|
||||
{
|
||||
this.cache.put(commandString, result);
|
||||
}
|
||||
this.cache.put(commandString, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ParsedCommand findParsedCommand(@NotNull Command command,
|
||||
@NotNull String commandName, @NotNull String[] args,
|
||||
@NotNull String commandString,
|
||||
@NotNull CommandResult result) {
|
||||
private @Nullable ParsedCommand findParsedCommand(@NotNull Command command,
|
||||
@NotNull String commandName, @NotNull String[] args,
|
||||
@NotNull String commandString,
|
||||
@NotNull CommandResult result) {
|
||||
final boolean hasArgument = args.length > 0;
|
||||
|
||||
// Search for subcommand
|
||||
@ -162,41 +154,37 @@ public class CommandDispatcher {
|
||||
|
||||
final String input = commandName + StringUtils.SPACE + String.join(StringUtils.SPACE, args);
|
||||
|
||||
|
||||
ParsedCommand parsedCommand = new ParsedCommand();
|
||||
parsedCommand.command = command;
|
||||
parsedCommand.commandString = commandString;
|
||||
|
||||
// The default executor should be used if no argument is provided
|
||||
{
|
||||
if (!hasArgument) {
|
||||
Optional<CommandSyntax> optionalSyntax = command.getSyntaxes()
|
||||
.stream()
|
||||
.filter(syntax -> syntax.getArguments().length == 0)
|
||||
.findFirst();
|
||||
if (!hasArgument) {
|
||||
Optional<CommandSyntax> optionalSyntax = command.getSyntaxes()
|
||||
.stream()
|
||||
.filter(syntax -> syntax.getArguments().length == 0)
|
||||
.findFirst();
|
||||
|
||||
if (optionalSyntax.isPresent()) {
|
||||
// Empty syntax found
|
||||
final CommandSyntax syntax = optionalSyntax.get();
|
||||
if (optionalSyntax.isPresent()) {
|
||||
// Empty syntax found
|
||||
final CommandSyntax syntax = optionalSyntax.get();
|
||||
parsedCommand.syntax = syntax;
|
||||
parsedCommand.executor = syntax.getExecutor();
|
||||
parsedCommand.context = new CommandContext(input);
|
||||
|
||||
parsedCommand.syntax = syntax;
|
||||
parsedCommand.executor = syntax.getExecutor();
|
||||
result.type = CommandResult.Type.SUCCESS;
|
||||
result.parsedCommand = parsedCommand;
|
||||
return parsedCommand;
|
||||
} else {
|
||||
// No empty syntax, use default executor if any
|
||||
final CommandExecutor defaultExecutor = command.getDefaultExecutor();
|
||||
if (defaultExecutor != null) {
|
||||
parsedCommand.executor = defaultExecutor;
|
||||
parsedCommand.context = new CommandContext(input);
|
||||
|
||||
result.type = CommandResult.Type.SUCCESS;
|
||||
result.parsedCommand = parsedCommand;
|
||||
return parsedCommand;
|
||||
} else {
|
||||
// No empty syntax, use default executor if any
|
||||
final CommandExecutor defaultExecutor = command.getDefaultExecutor();
|
||||
if (defaultExecutor != null) {
|
||||
parsedCommand.executor = defaultExecutor;
|
||||
parsedCommand.context = new CommandContext(input);
|
||||
|
||||
result.type = CommandResult.Type.SUCCESS;
|
||||
result.parsedCommand = parsedCommand;
|
||||
return parsedCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,7 +195,6 @@ public class CommandDispatcher {
|
||||
final Collection<CommandSyntax> syntaxes = command.getSyntaxes();
|
||||
// Contains all the fully validated syntaxes (we later find the one with the most amount of arguments)
|
||||
List<ValidSyntaxHolder> validSyntaxes = new ArrayList<>(syntaxes.size());
|
||||
|
||||
// Contains all the syntaxes that are not fully correct, used to later, retrieve the "most correct syntax"
|
||||
// Number of correct argument - The data about the failing argument
|
||||
Int2ObjectRBTreeMap<CommandSuggestionHolder> syntaxesSuggestions = new Int2ObjectRBTreeMap<>(Collections.reverseOrder());
|
||||
@ -233,29 +220,25 @@ public class CommandDispatcher {
|
||||
result.parsedCommand = parsedCommand;
|
||||
return parsedCommand;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No all-correct syntax, find the closest one to use the argument callback
|
||||
{
|
||||
// Get closest valid syntax
|
||||
if (!syntaxesSuggestions.isEmpty()) {
|
||||
final int max = syntaxesSuggestions.firstIntKey(); // number of correct arguments in the most correct syntax
|
||||
final CommandSuggestionHolder suggestionHolder = syntaxesSuggestions.get(max);
|
||||
final CommandSyntax syntax = suggestionHolder.syntax;
|
||||
final ArgumentSyntaxException argumentSyntaxException = suggestionHolder.argumentSyntaxException;
|
||||
final int argIndex = suggestionHolder.argIndex;
|
||||
if (!syntaxesSuggestions.isEmpty()) {
|
||||
final int max = syntaxesSuggestions.firstIntKey(); // number of correct arguments in the most correct syntax
|
||||
final CommandSuggestionHolder suggestionHolder = syntaxesSuggestions.get(max);
|
||||
final CommandSyntax syntax = suggestionHolder.syntax;
|
||||
final ArgumentSyntaxException argumentSyntaxException = suggestionHolder.argumentSyntaxException;
|
||||
final int argIndex = suggestionHolder.argIndex;
|
||||
|
||||
// Found the closest syntax with at least 1 correct argument
|
||||
final Argument<?> argument = syntax.getArguments()[argIndex];
|
||||
if (argument.hasErrorCallback()) {
|
||||
parsedCommand.callback = argument.getCallback();
|
||||
parsedCommand.argumentSyntaxException = argumentSyntaxException;
|
||||
// Found the closest syntax with at least 1 correct argument
|
||||
final Argument<?> argument = syntax.getArguments()[argIndex];
|
||||
if (argument.hasErrorCallback() && argumentSyntaxException != null) {
|
||||
parsedCommand.callback = argument.getCallback();
|
||||
parsedCommand.argumentSyntaxException = argumentSyntaxException;
|
||||
|
||||
result.type = CommandResult.Type.INVALID_SYNTAX;
|
||||
result.parsedCommand = parsedCommand;
|
||||
return parsedCommand;
|
||||
}
|
||||
result.type = CommandResult.Type.INVALID_SYNTAX;
|
||||
result.parsedCommand = parsedCommand;
|
||||
return parsedCommand;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ public final class Pos implements Point {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.yaw = fixYaw(yaw);
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ public final class Pos implements Point {
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull Pos withYaw(@NotNull DoubleUnaryOperator operator) {
|
||||
return new Pos(x, y, z, (float) operator.applyAsDouble(yaw), pitch);
|
||||
return withYaw((float) operator.applyAsDouble(yaw));
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
@ -118,7 +118,7 @@ public final class Pos implements Point {
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull Pos withPitch(@NotNull DoubleUnaryOperator operator) {
|
||||
return new Pos(x, y, z, yaw, (float) operator.applyAsDouble(pitch));
|
||||
return withPitch((float) operator.applyAsDouble(pitch));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,4 +325,21 @@ public final class Pos implements Point {
|
||||
public interface Operator {
|
||||
@NotNull Pos apply(double x, double y, double z, float yaw, float pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 static float fixYaw(float yaw) {
|
||||
yaw = yaw % 360;
|
||||
if (yaw < -180.0F) {
|
||||
yaw += 360.0F;
|
||||
} else if (yaw > 180.0F) {
|
||||
yaw -= 360.0F;
|
||||
}
|
||||
return yaw;
|
||||
}
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
if (expandedBoundingBox.intersect(itemBoundingBox)) {
|
||||
if (experienceOrb.shouldRemove() || experienceOrb.isRemoveScheduled())
|
||||
continue;
|
||||
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(experienceOrb);
|
||||
PickupExperienceEvent pickupExperienceEvent = new PickupExperienceEvent(this, experienceOrb);
|
||||
EventDispatcher.callCancellable(pickupExperienceEvent, () -> {
|
||||
short experienceCount = pickupExperienceEvent.getExperienceCount(); // TODO give to player
|
||||
entity.remove();
|
||||
|
@ -6,8 +6,8 @@ import net.minestom.server.entity.ai.GoalSelector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomStrollGoal extends GoalSelector {
|
||||
|
||||
@ -15,6 +15,7 @@ public class RandomStrollGoal extends GoalSelector {
|
||||
|
||||
private final int radius;
|
||||
private final List<Vec> closePositions;
|
||||
private final Random random = new Random();
|
||||
|
||||
private long lastStroll;
|
||||
|
||||
@ -31,8 +32,11 @@ public class RandomStrollGoal extends GoalSelector {
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Collections.shuffle(closePositions);
|
||||
for (var position : closePositions) {
|
||||
int remainingAttempt = closePositions.size();
|
||||
while (remainingAttempt-- > 0) {
|
||||
final int index = random.nextInt(closePositions.size());
|
||||
final Vec position = closePositions.get(index);
|
||||
|
||||
final var target = entityCreature.getPosition().add(position);
|
||||
final boolean result = entityCreature.getNavigator().setPathTo(target);
|
||||
if (result) {
|
||||
|
@ -1,21 +1,30 @@
|
||||
package net.minestom.server.event.item;
|
||||
|
||||
import net.minestom.server.entity.ExperienceOrb;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.trait.CancellableEvent;
|
||||
import net.minestom.server.event.trait.PlayerEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PickupExperienceEvent implements CancellableEvent {
|
||||
public class PickupExperienceEvent implements CancellableEvent, PlayerEvent {
|
||||
|
||||
private final Player player;
|
||||
private final ExperienceOrb experienceOrb;
|
||||
private short experienceCount;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
public PickupExperienceEvent(@NotNull ExperienceOrb experienceOrb) {
|
||||
public PickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) {
|
||||
this.player = player;
|
||||
this.experienceOrb = experienceOrb;
|
||||
this.experienceCount = experienceOrb.getExperienceCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExperienceOrb getExperienceOrb() {
|
||||
return experienceOrb;
|
||||
|
@ -233,6 +233,7 @@ public class AnvilLoader implements IChunkLoader {
|
||||
try {
|
||||
LOGGER.debug("Attempt saving at {} {}", chunk.getChunkX(), chunk.getChunkZ());
|
||||
mcaFile.writeColumn(column);
|
||||
mcaFile.forget(column);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to save chunk " + chunkX + ", " + chunkZ, e);
|
||||
EXCEPTION_MANAGER.handleException(e);
|
||||
|
@ -4,18 +4,15 @@ package net.minestom.server.item;
|
||||
* Represents a hide flag which can be applied to an {@link ItemStack} using {@link ItemMetaBuilder#hideFlag(int)}.
|
||||
*/
|
||||
public enum ItemHideFlag {
|
||||
HIDE_ENCHANTS(1),
|
||||
HIDE_ATTRIBUTES(2),
|
||||
HIDE_UNBREAKABLE(4),
|
||||
HIDE_DESTROYS(8),
|
||||
HIDE_PLACED_ON(16),
|
||||
HIDE_POTION_EFFECTS(32);
|
||||
HIDE_ENCHANTS,
|
||||
HIDE_ATTRIBUTES,
|
||||
HIDE_UNBREAKABLE,
|
||||
HIDE_DESTROYS,
|
||||
HIDE_PLACED_ON,
|
||||
HIDE_POTION_EFFECTS,
|
||||
HIDE_DYE;
|
||||
|
||||
private final int bitFieldPart;
|
||||
|
||||
ItemHideFlag(int bit) {
|
||||
this.bitFieldPart = bit;
|
||||
}
|
||||
private final int bitFieldPart = 1 << this.ordinal();
|
||||
|
||||
public int getBitFieldPart() {
|
||||
return bitFieldPart;
|
||||
|
@ -31,8 +31,7 @@ import static net.minestom.server.MinecraftServer.*;
|
||||
* Be aware that this is not the most accurate method, you should use a proper java profiler depending on your needs.
|
||||
*/
|
||||
public final class BenchmarkManager {
|
||||
|
||||
public static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
|
||||
private static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
|
||||
private static final List<String> THREADS = new ArrayList<>();
|
||||
|
||||
static {
|
||||
@ -46,12 +45,10 @@ public final class BenchmarkManager {
|
||||
private final Long2LongMap lastUserTimeMap = new Long2LongOpenHashMap();
|
||||
private final Long2LongMap lastWaitedMap = new Long2LongOpenHashMap();
|
||||
private final Long2LongMap lastBlockedMap = new Long2LongOpenHashMap();
|
||||
|
||||
private final Map<String, ThreadResult> resultMap = new ConcurrentHashMap<>();
|
||||
|
||||
private boolean enabled = false;
|
||||
private volatile boolean stop = false;
|
||||
|
||||
private long time;
|
||||
|
||||
public void enable(@NotNull Duration duration) {
|
||||
@ -96,13 +93,11 @@ public final class BenchmarkManager {
|
||||
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<String, ThreadResult> getResultMap() {
|
||||
public @NotNull Map<String, ThreadResult> getResultMap() {
|
||||
return Collections.unmodifiableMap(resultMap);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Component getCpuMonitoringMessage() {
|
||||
public @NotNull Component getCpuMonitoringMessage() {
|
||||
Check.stateCondition(!enabled, "CPU monitoring is only possible when the benchmark manager is enabled.");
|
||||
TextComponent.Builder benchmarkMessage = Component.text();
|
||||
for (var resultEntry : resultMap.entrySet()) {
|
||||
@ -121,23 +116,16 @@ public final class BenchmarkManager {
|
||||
benchmarkMessage.append(Component.text("% WAITED ", NamedTextColor.GREEN));
|
||||
benchmarkMessage.append(Component.newline());
|
||||
}
|
||||
|
||||
return benchmarkMessage.build();
|
||||
}
|
||||
|
||||
private void refreshData() {
|
||||
ThreadInfo[] threadInfo = THREAD_MX_BEAN.getThreadInfo(THREAD_MX_BEAN.getAllThreadIds());
|
||||
for (ThreadInfo threadInfo2 : threadInfo) {
|
||||
if (threadInfo2 == null) continue; // Can happen if the thread does not exist
|
||||
final String name = threadInfo2.getThreadName();
|
||||
boolean shouldBenchmark = false;
|
||||
for (String thread : THREADS) {
|
||||
if (name.startsWith(thread)) {
|
||||
shouldBenchmark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shouldBenchmark)
|
||||
continue;
|
||||
final boolean shouldBenchmark = THREADS.stream().anyMatch(name::startsWith);
|
||||
if (!shouldBenchmark) continue;
|
||||
|
||||
final long id = threadInfo2.getThreadId();
|
||||
|
||||
|
@ -349,11 +349,14 @@ public final class ConnectionManager {
|
||||
if (playerConnection instanceof PlayerSocketConnection) {
|
||||
final PlayerSocketConnection socketConnection = (PlayerSocketConnection) playerConnection;
|
||||
socketConnection.writeAndFlush(disconnectPacket);
|
||||
playerConnection.disconnect();
|
||||
try {
|
||||
socketConnection.getChannel().close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
player.remove();
|
||||
}
|
||||
}
|
||||
this.players.clear();
|
||||
|
@ -17,7 +17,7 @@ public final class Server {
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(Server.class);
|
||||
public static final int WORKER_COUNT = Integer.getInteger("minestom.workers",
|
||||
Runtime.getRuntime().availableProcessors());
|
||||
public static final int SOCKET_BUFFER_SIZE = Integer.getInteger("minestom.buffer-size", 262_143);
|
||||
public static final int SOCKET_BUFFER_SIZE = Integer.getInteger("minestom.buffer-size", 1_048_575);
|
||||
public static final int MAX_PACKET_SIZE = 2_097_151; // 3 bytes var-int
|
||||
public static final boolean NO_DELAY = true;
|
||||
|
||||
|
@ -235,6 +235,7 @@ public class BinaryWriter extends OutputStream {
|
||||
* @param bytes the byte array to write
|
||||
*/
|
||||
public void writeBytes(byte @NotNull [] bytes) {
|
||||
if (bytes.length == 0) return;
|
||||
ensureSize(bytes.length);
|
||||
buffer.put(bytes);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user