mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-09 01:47:54 +01:00
Merge branch 'master' into item-api
# Conflicts: # src/main/java/net/minestom/server/item/ItemStack.java
This commit is contained in:
commit
e3867c659b
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@ -2,7 +2,7 @@
|
|||||||
#### **Did you find a bug?**
|
#### **Did you find a bug?**
|
||||||
* Open a new GitHub issue if it's not already reported.
|
* Open a new GitHub issue if it's not already reported.
|
||||||
|
|
||||||
* Use the relevant bug report template to create the issue.
|
* Explain it clearly, with steps (or code) to reproduce it.
|
||||||
|
|
||||||
#### **Did you write some code that fixes a bug?**
|
#### **Did you write some code that fixes a bug?**
|
||||||
* Open a new GitHub pull-request with the commits if it hasn't already been proposed.
|
* Open a new GitHub pull-request with the commits if it hasn't already been proposed.
|
||||||
|
22
.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md
vendored
22
.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md
vendored
@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
labels: Bug
|
|
||||||
about: Use this to report unexpected behavior (bugs and errors).
|
|
||||||
---
|
|
||||||
### What is the current behavior?
|
|
||||||
|
|
||||||
|
|
||||||
### What is the expected behavior?
|
|
||||||
|
|
||||||
|
|
||||||
### What steps will reproduce the problem?
|
|
||||||
|
|
||||||
|
|
||||||
### What operating system and java version is being used?
|
|
||||||
|
|
||||||
|
|
||||||
### If there is an exception, use pastebin/hastebin (NB: no expiry date!) to send the stacktrace
|
|
||||||
|
|
||||||
|
|
||||||
### Additional information / Possible thoughts on why this bug is happening
|
|
||||||
|
|
15
.github/ISSUE_TEMPLATE/FEATURE_TEMPLATE.md
vendored
15
.github/ISSUE_TEMPLATE/FEATURE_TEMPLATE.md
vendored
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
labels: Enhancement
|
|
||||||
about: Use this to request an addition (feature).
|
|
||||||
---
|
|
||||||
### What would you like added/changed?
|
|
||||||
|
|
||||||
|
|
||||||
### Why do you think this is a good addition/alteration?
|
|
||||||
|
|
||||||
|
|
||||||
### Why do you want this to be added?
|
|
||||||
|
|
||||||
|
|
||||||
### Additional Information
|
|
7
.github/ISSUE_TEMPLATE/QUESTION_TEMPLATE.md
vendored
7
.github/ISSUE_TEMPLATE/QUESTION_TEMPLATE.md
vendored
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
name: Question
|
|
||||||
labels: Question
|
|
||||||
about: Use this to ask a question.
|
|
||||||
---
|
|
||||||
### Your Question:
|
|
||||||
|
|
12
build.gradle
12
build.gradle
@ -47,6 +47,18 @@ allprojects {
|
|||||||
options {
|
options {
|
||||||
destinationDir(file("docs"))
|
destinationDir(file("docs"))
|
||||||
addBooleanOption('html5', true)
|
addBooleanOption('html5', true)
|
||||||
|
links "https://jd.adventure.kyori.net/api/$adventureVersion/"
|
||||||
|
links "https://docs.oracle.com/en/java/javase/11/docs/api/"
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://stackoverflow.com/a/56641766
|
||||||
|
doLast {
|
||||||
|
// Append the fix to the file
|
||||||
|
def searchScript = new File(destinationDir.getAbsolutePath() + '/search.js')
|
||||||
|
searchScript.append '\n\n' +
|
||||||
|
'getURLPrefix = function(ui) {\n' +
|
||||||
|
' return \'\';\n' +
|
||||||
|
'};\n'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package net.minestom.server.bossbar;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the displayed color of a {@link BossBar}.
|
* Represents the displayed color of a {@link BossBar}.
|
||||||
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar}
|
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar.Color}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public enum BarColor {
|
public enum BarColor {
|
||||||
|
@ -3,7 +3,7 @@ package net.minestom.server.bossbar;
|
|||||||
/**
|
/**
|
||||||
* Used to define the number of segments on a {@link BossBar}.
|
* Used to define the number of segments on a {@link BossBar}.
|
||||||
*
|
*
|
||||||
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar}
|
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar.Overlay}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public enum BarDivision {
|
public enum BarDivision {
|
||||||
|
@ -20,7 +20,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
* <p>
|
* <p>
|
||||||
* You can retrieve all the boss bars of a {@link Player} with {@link #getBossBars(Player)}.
|
* You can retrieve all the boss bars of a {@link Player} with {@link #getBossBars(Player)}.
|
||||||
*
|
*
|
||||||
* @deprecated Use {@link net.kyori.adventure.audience.Audience#showBossBar(net.kyori.adventure.bossbar.BossBar)}
|
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BossBar implements Viewable {
|
public class BossBar implements Viewable {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package net.minestom.server.chat;
|
package net.minestom.server.chat;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a click event for a specific portion of the message.
|
* Represents a click event for a specific portion of the message.
|
||||||
|
* @deprecated Use {@link ClickEvent}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class ChatClickEvent {
|
public class ChatClickEvent {
|
||||||
|
@ -4,24 +4,31 @@ import it.unimi.dsi.fastutil.chars.Char2ObjectMap;
|
|||||||
import it.unimi.dsi.fastutil.chars.Char2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.chars.Char2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
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.Color;
|
||||||
|
import net.minestom.server.color.DyeColor;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a color in a text. You can either use one of the pre-made colors
|
* Represents a color in a text. You can either use one of the pre-made colors
|
||||||
* or make your own using RGB. {@link ChatColor#fromRGB(byte, byte, byte)}.
|
* or make your own using RGB. {@link ChatColor#fromRGB(byte, byte, byte)}.
|
||||||
* <p>
|
* <p>
|
||||||
* Immutable class.
|
* Immutable class.
|
||||||
|
* @deprecated For chat colors, use {@link TextColor} or {@link NamedTextColor}. For styles, use {@link TextDecoration}.
|
||||||
|
* For colors in other contexts, see {@link Color} or {@link DyeColor}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final class ChatColor {
|
public final class ChatColor implements StyleBuilderApplicable {
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
public static final ChatColor NO_COLOR = new ChatColor();
|
public static final ChatColor NO_COLOR = new ChatColor();
|
||||||
@ -310,4 +317,26 @@ public final class ChatColor {
|
|||||||
|
|
||||||
return header + code + footer;
|
return header + code + footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Contract(mutates = "param")
|
||||||
|
public void styleApply(Style.@NotNull Builder style) {
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
style.color(NamedTextColor.WHITE);
|
||||||
|
} else if (Objects.equals(this.codeName, "reset")) {
|
||||||
|
style.color(NamedTextColor.WHITE);
|
||||||
|
|
||||||
|
for (TextDecoration value : TextDecoration.NAMES.values()) {
|
||||||
|
style.decoration(value, TextDecoration.State.FALSE);
|
||||||
|
}
|
||||||
|
} else if (this.isSpecial() && this.codeName != null) {
|
||||||
|
TextDecoration decoration = TextDecoration.NAMES.value(this.codeName);
|
||||||
|
|
||||||
|
if (decoration != null) {
|
||||||
|
style.decorate(decoration);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
style.color(TextColor.color(this.red, this.green, this.blue));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a hover event for a specific portion of the message.
|
* Represents a hover event for a specific portion of the message.
|
||||||
|
* @deprecated Use {@link HoverEvent}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class ChatHoverEvent {
|
public class ChatHoverEvent {
|
||||||
|
@ -2,10 +2,12 @@ package net.minestom.server.chat;
|
|||||||
|
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to convert JSON string to proper chat message representation.
|
* Class used to convert JSON string to proper chat message representation.
|
||||||
|
* @deprecated Use {@link GsonComponentSerializer}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final class ChatParser {
|
public final class ChatParser {
|
||||||
|
@ -2,6 +2,8 @@ package net.minestom.server.chat;
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -16,6 +18,7 @@ import java.util.regex.Pattern;
|
|||||||
* <p>
|
* <p>
|
||||||
* To create one, you simply call one of the static methods like {@link #of(ChatColor, String)},
|
* To create one, you simply call one of the static methods like {@link #of(ChatColor, String)},
|
||||||
* you can then continue to append text with {@link #append(ChatColor, String)}.
|
* you can then continue to append text with {@link #append(ChatColor, String)}.
|
||||||
|
* @deprecated Use {@link Component#text(String, TextColor)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class ColoredText extends JsonMessage {
|
public class ColoredText extends JsonMessage {
|
||||||
|
@ -16,6 +16,7 @@ import java.util.Objects;
|
|||||||
* Examples are {@link ColoredText} and {@link RichMessage}.
|
* Examples are {@link ColoredText} and {@link RichMessage}.
|
||||||
*
|
*
|
||||||
* @see <a href="https://wiki.vg/Chat">Chat Format</a>
|
* @see <a href="https://wiki.vg/Chat">Chat Format</a>
|
||||||
|
* @deprecated Use {@link Component}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public abstract class JsonMessage implements ComponentLike {
|
public abstract class JsonMessage implements ComponentLike {
|
||||||
|
@ -2,6 +2,7 @@ package net.minestom.server.chat;
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -18,6 +19,7 @@ import java.util.List;
|
|||||||
* You will need to call the static method to initialize the message {@link #of(ColoredText)},
|
* You will need to call the static method to initialize the message {@link #of(ColoredText)},
|
||||||
* events can be assigned with {@link #setClickEvent(ChatClickEvent)} and {@link #setHoverEvent(ChatHoverEvent)}
|
* events can be assigned with {@link #setClickEvent(ChatClickEvent)} and {@link #setHoverEvent(ChatHoverEvent)}
|
||||||
* and new text element can also be appended {@link #append(ColoredText)}.
|
* and new text element can also be appended {@link #append(ColoredText)}.
|
||||||
|
* @deprecated Use {@link Component}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class RichMessage extends JsonMessage {
|
public class RichMessage extends JsonMessage {
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package net.minestom.server.chat;
|
package net.minestom.server.chat;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a translatable component which can be used in {@link ColoredText}.
|
* Represents a translatable component which can be used in {@link ColoredText}.
|
||||||
|
* @deprecated Use {@link TranslatableComponent}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class TranslatableText {
|
public class TranslatableText {
|
||||||
|
@ -18,21 +18,17 @@ public interface CommandSender extends PermissionHandler, Audience {
|
|||||||
* Sends a raw string message.
|
* Sends a raw string message.
|
||||||
*
|
*
|
||||||
* @param message the message to send
|
* @param message the message to send
|
||||||
*
|
|
||||||
* @deprecated Use {@link #sendMessage(Component)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
default void sendMessage(@NotNull String message) {
|
||||||
default void sendMessage(@NotNull String message) { this.sendMessage(Component.text(message)); }
|
this.sendMessage(Component.text(message));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends multiple raw string messages.
|
* Sends multiple raw string messages.
|
||||||
*
|
*
|
||||||
* @param messages the messages to send
|
* @param messages the messages to send
|
||||||
*
|
|
||||||
* @deprecated Use {@link #sendMessage(Component)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
default void sendMessage(@NotNull String @NotNull[] messages) {
|
||||||
default void sendMessage(@NotNull String[] messages) {
|
|
||||||
for (String message : messages) {
|
for (String message : messages) {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
@ -57,7 +53,7 @@ public interface CommandSender extends PermissionHandler, Audience {
|
|||||||
* @return true if 'this' is a player, false otherwise
|
* @return true if 'this' is a player, false otherwise
|
||||||
*/
|
*/
|
||||||
default boolean isPlayer() {
|
default boolean isPlayer() {
|
||||||
return this instanceof Player;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +62,7 @@ public interface CommandSender extends PermissionHandler, Audience {
|
|||||||
* @return true if 'this' is the console, false otherwise
|
* @return true if 'this' is the console, false otherwise
|
||||||
*/
|
*/
|
||||||
default boolean isConsole() {
|
default boolean isConsole() {
|
||||||
return this instanceof ConsoleSender;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +73,7 @@ public interface CommandSender extends PermissionHandler, Audience {
|
|||||||
* @see #isPlayer()
|
* @see #isPlayer()
|
||||||
*/
|
*/
|
||||||
default Player asPlayer() {
|
default Player asPlayer() {
|
||||||
return (Player) this;
|
throw new ClassCastException("CommandSender is not a Player");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,6 +84,6 @@ public interface CommandSender extends PermissionHandler, Audience {
|
|||||||
* @see #isConsole()
|
* @see #isConsole()
|
||||||
*/
|
*/
|
||||||
default ConsoleSender asConsole() {
|
default ConsoleSender asConsole() {
|
||||||
return (ConsoleSender) this;
|
throw new ClassCastException("CommandSender is not the ConsoleSender");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,20 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
* Represents the console when sending a command to the server.
|
* Represents the console when sending a command to the server.
|
||||||
*/
|
*/
|
||||||
public class ConsoleSender implements CommandSender {
|
public class ConsoleSender implements CommandSender {
|
||||||
|
private static final PlainComponentSerializer PLAIN_SERIALIZER = PlainComponentSerializer.plain();
|
||||||
private final static Logger LOGGER = LoggerFactory.getLogger(ConsoleSender.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleSender.class);
|
||||||
|
|
||||||
private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
|
private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(@NotNull String message) {
|
||||||
|
LOGGER.info(message);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||||
// we don't use the serializer here as we just need the plain text of the message
|
// we don't use the serializer here as we just need the plain text of the message
|
||||||
LOGGER.info(PlainComponentSerializer.plain().serialize(message));
|
this.sendMessage(PLAIN_SERIALIZER.serialize(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -32,4 +37,14 @@ public class ConsoleSender implements CommandSender {
|
|||||||
public Set<Permission> getAllPermissions() {
|
public Set<Permission> getAllPermissions() {
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConsole() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsoleSender asConsole() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ import net.minestom.server.utils.chunk.ChunkCallback;
|
|||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.utils.entity.EntityUtils;
|
import net.minestom.server.utils.entity.EntityUtils;
|
||||||
import net.minestom.server.utils.player.PlayerUtils;
|
import net.minestom.server.utils.player.PlayerUtils;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
@ -684,7 +684,7 @@ public class Entity implements Viewable, EventHandler, DataContainer, Permission
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scheduled synchronization
|
// Scheduled synchronization
|
||||||
if (!CooldownUtils.hasCooldown(time, lastAbsoluteSynchronizationTime, getSynchronizationCooldown())) {
|
if (!Cooldown.hasCooldown(time, lastAbsoluteSynchronizationTime, getSynchronizationCooldown())) {
|
||||||
this.lastAbsoluteSynchronizationTime = time;
|
this.lastAbsoluteSynchronizationTime = time;
|
||||||
sendSynchronization();
|
sendSynchronization();
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import net.minestom.server.instance.Instance;
|
|||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.StackingRule;
|
import net.minestom.server.item.StackingRule;
|
||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -75,7 +75,7 @@ public class ItemEntity extends ObjectEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void update(long time) {
|
public void update(long time) {
|
||||||
if (isMergeable() && isPickable() &&
|
if (isMergeable() && isPickable() &&
|
||||||
(mergeUpdateOption == null || !CooldownUtils.hasCooldown(time, lastMergeCheck, mergeUpdateOption))) {
|
(mergeUpdateOption == null || !Cooldown.hasCooldown(time, lastMergeCheck, mergeUpdateOption))) {
|
||||||
this.lastMergeCheck = time;
|
this.lastMergeCheck = time;
|
||||||
|
|
||||||
final Chunk chunk = instance.getChunkAt(getPosition());
|
final Chunk chunk = instance.getChunkAt(getPosition());
|
||||||
|
@ -25,7 +25,7 @@ import net.minestom.server.utils.BlockPosition;
|
|||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
import net.minestom.server.utils.Vector;
|
import net.minestom.server.utils.Vector;
|
||||||
import net.minestom.server.utils.block.BlockIterator;
|
import net.minestom.server.utils.block.BlockIterator;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -39,8 +39,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
|||||||
|
|
||||||
// ItemStack pickup
|
// ItemStack pickup
|
||||||
protected boolean canPickupItem;
|
protected boolean canPickupItem;
|
||||||
protected UpdateOption itemPickupCooldown = new UpdateOption(5, TimeUnit.TICK);
|
protected Cooldown itemPickupCooldown = new Cooldown(new UpdateOption(5, TimeUnit.TICK));
|
||||||
private long lastItemPickupCheckTime;
|
|
||||||
|
|
||||||
protected boolean isDead;
|
protected boolean isDead;
|
||||||
|
|
||||||
@ -213,8 +212,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Items picking
|
// Items picking
|
||||||
if (canPickupItem() && !CooldownUtils.hasCooldown(time, lastItemPickupCheckTime, itemPickupCooldown)) {
|
if (canPickupItem() && itemPickupCooldown.isReady(time)) {
|
||||||
this.lastItemPickupCheckTime = time;
|
itemPickupCooldown.refreshLastUpdate(time);
|
||||||
|
|
||||||
final Chunk chunk = getChunk(); // TODO check surrounding chunks
|
final Chunk chunk = getChunk(); // TODO check surrounding chunks
|
||||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||||
|
@ -12,6 +12,7 @@ import net.kyori.adventure.text.Component;
|
|||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEvent.ShowEntity;
|
import net.kyori.adventure.text.event.HoverEvent.ShowEntity;
|
||||||
import net.kyori.adventure.text.event.HoverEventSource;
|
import net.kyori.adventure.text.event.HoverEventSource;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.kyori.adventure.title.Title;
|
import net.kyori.adventure.title.Title;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.advancements.AdvancementTab;
|
import net.minestom.server.advancements.AdvancementTab;
|
||||||
@ -67,7 +68,7 @@ import net.minestom.server.utils.chunk.ChunkCallback;
|
|||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.utils.entity.EntityUtils;
|
import net.minestom.server.utils.entity.EntityUtils;
|
||||||
import net.minestom.server.utils.instance.InstanceUtils;
|
import net.minestom.server.utils.instance.InstanceUtils;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
@ -151,8 +152,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
private float lastPlayerSyncYaw, lastPlayerSyncPitch;
|
private float lastPlayerSyncYaw, lastPlayerSyncPitch;
|
||||||
|
|
||||||
// Experience orb pickup
|
// Experience orb pickup
|
||||||
protected UpdateOption experiencePickupCooldown = new UpdateOption(10, TimeUnit.TICK);
|
protected Cooldown experiencePickupCooldown = new Cooldown(new UpdateOption(10, TimeUnit.TICK));
|
||||||
private long lastExperiencePickupCheckTime;
|
|
||||||
|
|
||||||
private BelowNameTag belowNameTag;
|
private BelowNameTag belowNameTag;
|
||||||
|
|
||||||
@ -373,9 +373,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Experience orb pickup
|
// Experience orb pickup
|
||||||
if (!CooldownUtils.hasCooldown(time, lastExperiencePickupCheckTime, experiencePickupCooldown)) {
|
if (experiencePickupCooldown.isReady(time)) {
|
||||||
this.lastExperiencePickupCheckTime = time;
|
experiencePickupCooldown.refreshLastUpdate(time);
|
||||||
|
|
||||||
final Chunk chunk = getChunk(); // TODO check surrounding chunks
|
final Chunk chunk = getChunk(); // TODO check surrounding chunks
|
||||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
@ -806,7 +805,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void sendJsonMessage(@NotNull String json) {
|
public void sendJsonMessage(@NotNull String json) {
|
||||||
this.sendMessage(json);
|
this.sendMessage(GsonComponentSerializer.gson().deserialize(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2644,6 +2643,16 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
this.identity = Identity.identity(uuid);
|
this.identity = Identity.identity(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayer() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Player asPlayer() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the main or off hand of the player.
|
* Represents the main or off hand of the player.
|
||||||
*/
|
*/
|
||||||
|
@ -7,8 +7,9 @@ import net.minestom.server.entity.ai.GoalSelector;
|
|||||||
import net.minestom.server.entity.pathfinding.Navigator;
|
import net.minestom.server.entity.pathfinding.Navigator;
|
||||||
import net.minestom.server.entity.type.projectile.EntityProjectile;
|
import net.minestom.server.entity.type.projectile.EntityProjectile;
|
||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -19,6 +20,8 @@ import java.util.function.Function;
|
|||||||
*/
|
*/
|
||||||
public class CombinedAttackGoal extends GoalSelector {
|
public class CombinedAttackGoal extends GoalSelector {
|
||||||
|
|
||||||
|
private final Cooldown cooldown = new Cooldown(new UpdateOption(5, TimeUnit.TICK));
|
||||||
|
|
||||||
private final int meleeRangeSquared;
|
private final int meleeRangeSquared;
|
||||||
private final int meleeDelay;
|
private final int meleeDelay;
|
||||||
private final TimeUnit meleeTimeUnit;
|
private final TimeUnit meleeTimeUnit;
|
||||||
@ -90,6 +93,10 @@ public class CombinedAttackGoal extends GoalSelector {
|
|||||||
Check.argCondition(desirableRange > rangedRange, "Desirable range can not exceed ranged range!");
|
Check.argCondition(desirableRange > rangedRange, "Desirable range can not exceed ranged range!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cooldown getCooldown() {
|
||||||
|
return this.cooldown;
|
||||||
|
}
|
||||||
|
|
||||||
public void setProjectileGenerator(Function<Entity, EntityProjectile> projectileGenerator) {
|
public void setProjectileGenerator(Function<Entity, EntityProjectile> projectileGenerator) {
|
||||||
this.projectileGenerator = projectileGenerator;
|
this.projectileGenerator = projectileGenerator;
|
||||||
}
|
}
|
||||||
@ -122,12 +129,12 @@ public class CombinedAttackGoal extends GoalSelector {
|
|||||||
boolean comeClose = false;
|
boolean comeClose = false;
|
||||||
// First of all, checking if to perform melee or ranged attack depending on the distance to target.
|
// First of all, checking if to perform melee or ranged attack depending on the distance to target.
|
||||||
if (distanceSquared <= this.meleeRangeSquared) {
|
if (distanceSquared <= this.meleeRangeSquared) {
|
||||||
if (!CooldownUtils.hasCooldown(time, this.lastAttack, this.meleeTimeUnit, this.meleeDelay)) {
|
if (!Cooldown.hasCooldown(time, this.lastAttack, this.meleeTimeUnit, this.meleeDelay)) {
|
||||||
this.entityCreature.attack(target, true);
|
this.entityCreature.attack(target, true);
|
||||||
this.lastAttack = time;
|
this.lastAttack = time;
|
||||||
}
|
}
|
||||||
} else if (distanceSquared <= this.rangedRangeSquared) {
|
} else if (distanceSquared <= this.rangedRangeSquared) {
|
||||||
if (!CooldownUtils.hasCooldown(time, this.lastAttack, this.rangedTimeUnit, this.rangedDelay)) {
|
if (!Cooldown.hasCooldown(time, this.lastAttack, this.rangedTimeUnit, this.rangedDelay)) {
|
||||||
if (this.entityCreature.hasLineOfSight(target)) {
|
if (this.entityCreature.hasLineOfSight(target)) {
|
||||||
// If target is on line of entity sight, ranged attack can be performed
|
// If target is on line of entity sight, ranged attack can be performed
|
||||||
Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D);
|
Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D);
|
||||||
@ -159,9 +166,12 @@ public class CombinedAttackGoal extends GoalSelector {
|
|||||||
// Otherwise going to the target.
|
// Otherwise going to the target.
|
||||||
Position targetPosition = target.getPosition();
|
Position targetPosition = target.getPosition();
|
||||||
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
|
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
|
||||||
|
if (this.cooldown.isReady(time)) {
|
||||||
|
this.cooldown.refreshLastUpdate(time);
|
||||||
navigator.setPathTo(targetPosition);
|
navigator.setPathTo(targetPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldEnd() {
|
public boolean shouldEnd() {
|
||||||
|
@ -6,11 +6,10 @@ import net.minestom.server.entity.ai.GoalSelector;
|
|||||||
import net.minestom.server.entity.ai.TargetSelector;
|
import net.minestom.server.entity.ai.TargetSelector;
|
||||||
import net.minestom.server.entity.pathfinding.Navigator;
|
import net.minestom.server.entity.pathfinding.Navigator;
|
||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attacks the entity's target ({@link EntityCreature#getTarget()}) OR the closest entity
|
* Attacks the entity's target ({@link EntityCreature#getTarget()}) OR the closest entity
|
||||||
@ -18,6 +17,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class MeleeAttackGoal extends GoalSelector {
|
public class MeleeAttackGoal extends GoalSelector {
|
||||||
|
|
||||||
|
private final Cooldown cooldown = new Cooldown(new UpdateOption(5, TimeUnit.TICK));
|
||||||
|
|
||||||
private long lastHit;
|
private long lastHit;
|
||||||
private final int delay;
|
private final int delay;
|
||||||
private final TimeUnit timeUnit;
|
private final TimeUnit timeUnit;
|
||||||
@ -39,6 +40,10 @@ public class MeleeAttackGoal extends GoalSelector {
|
|||||||
this.timeUnit = timeUnit;
|
this.timeUnit = timeUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cooldown getCooldown() {
|
||||||
|
return this.cooldown;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldStart() {
|
public boolean shouldStart() {
|
||||||
this.cachedTarget = findTarget();
|
this.cachedTarget = findTarget();
|
||||||
@ -67,7 +72,7 @@ public class MeleeAttackGoal extends GoalSelector {
|
|||||||
|
|
||||||
// Attack the target entity
|
// Attack the target entity
|
||||||
if (entityCreature.getDistance(target) <= range) {
|
if (entityCreature.getDistance(target) <= range) {
|
||||||
if (!CooldownUtils.hasCooldown(time, lastHit, timeUnit, delay)) {
|
if (!Cooldown.hasCooldown(time, lastHit, timeUnit, delay)) {
|
||||||
entityCreature.attack(target, true);
|
entityCreature.attack(target, true);
|
||||||
this.lastHit = time;
|
this.lastHit = time;
|
||||||
}
|
}
|
||||||
@ -79,10 +84,13 @@ public class MeleeAttackGoal extends GoalSelector {
|
|||||||
final Position pathPosition = navigator.getPathPosition();
|
final Position pathPosition = navigator.getPathPosition();
|
||||||
final Position targetPosition = target.getPosition();
|
final Position targetPosition = target.getPosition();
|
||||||
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
|
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
|
||||||
|
if (this.cooldown.isReady(time)) {
|
||||||
|
this.cooldown.refreshLastUpdate(time);
|
||||||
navigator.setPathTo(targetPosition);
|
navigator.setPathTo(targetPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldEnd() {
|
public boolean shouldEnd() {
|
||||||
|
@ -7,8 +7,9 @@ import net.minestom.server.entity.ai.GoalSelector;
|
|||||||
import net.minestom.server.entity.pathfinding.Navigator;
|
import net.minestom.server.entity.pathfinding.Navigator;
|
||||||
import net.minestom.server.entity.type.projectile.EntityProjectile;
|
import net.minestom.server.entity.type.projectile.EntityProjectile;
|
||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -16,6 +17,8 @@ import java.util.function.Function;
|
|||||||
|
|
||||||
public class RangedAttackGoal extends GoalSelector {
|
public class RangedAttackGoal extends GoalSelector {
|
||||||
|
|
||||||
|
private final Cooldown cooldown = new Cooldown(new UpdateOption(5, TimeUnit.TICK));
|
||||||
|
|
||||||
private long lastShot;
|
private long lastShot;
|
||||||
private final int delay;
|
private final int delay;
|
||||||
private final TimeUnit timeUnit;
|
private final TimeUnit timeUnit;
|
||||||
@ -52,6 +55,10 @@ public class RangedAttackGoal extends GoalSelector {
|
|||||||
Check.argCondition(desirableRange > attackRange, "Desirable range can not exceed attack range!");
|
Check.argCondition(desirableRange > attackRange, "Desirable range can not exceed attack range!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cooldown getCooldown() {
|
||||||
|
return this.cooldown;
|
||||||
|
}
|
||||||
|
|
||||||
public void setProjectileGenerator(Function<Entity, EntityProjectile> projectileGenerator) {
|
public void setProjectileGenerator(Function<Entity, EntityProjectile> projectileGenerator) {
|
||||||
this.projectileGenerator = projectileGenerator;
|
this.projectileGenerator = projectileGenerator;
|
||||||
}
|
}
|
||||||
@ -83,7 +90,7 @@ public class RangedAttackGoal extends GoalSelector {
|
|||||||
double distanceSquared = this.entityCreature.getDistanceSquared(target);
|
double distanceSquared = this.entityCreature.getDistanceSquared(target);
|
||||||
boolean comeClose = false;
|
boolean comeClose = false;
|
||||||
if (distanceSquared <= this.attackRangeSquared) {
|
if (distanceSquared <= this.attackRangeSquared) {
|
||||||
if (!CooldownUtils.hasCooldown(time, this.lastShot, this.timeUnit, this.delay)) {
|
if (!Cooldown.hasCooldown(time, this.lastShot, this.timeUnit, this.delay)) {
|
||||||
if (this.entityCreature.hasLineOfSight(target)) {
|
if (this.entityCreature.hasLineOfSight(target)) {
|
||||||
Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D);
|
Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D);
|
||||||
|
|
||||||
@ -111,9 +118,12 @@ public class RangedAttackGoal extends GoalSelector {
|
|||||||
}
|
}
|
||||||
Position targetPosition = target.getPosition();
|
Position targetPosition = target.getPosition();
|
||||||
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
|
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
|
||||||
|
if (this.cooldown.isReady(time)) {
|
||||||
|
this.cooldown.refreshLastUpdate(time);
|
||||||
navigator.setPathTo(targetPosition);
|
navigator.setPathTo(targetPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldEnd() {
|
public boolean shouldEnd() {
|
||||||
|
@ -3,12 +3,14 @@ package net.minestom.server.entity.metadata.other;
|
|||||||
import net.minestom.server.entity.Entity;
|
import net.minestom.server.entity.Entity;
|
||||||
import net.minestom.server.entity.Metadata;
|
import net.minestom.server.entity.Metadata;
|
||||||
import net.minestom.server.entity.metadata.EntityMeta;
|
import net.minestom.server.entity.metadata.EntityMeta;
|
||||||
|
import net.minestom.server.entity.metadata.ObjectDataProvider;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class FishingHookMeta extends EntityMeta {
|
public class FishingHookMeta extends EntityMeta implements ObjectDataProvider {
|
||||||
|
|
||||||
private Entity hooked;
|
private Entity hooked;
|
||||||
|
private Entity owner;
|
||||||
|
|
||||||
public FishingHookMeta(@NotNull Entity entity, @NotNull Metadata metadata) {
|
public FishingHookMeta(@NotNull Entity entity, @NotNull Metadata metadata) {
|
||||||
super(entity, metadata);
|
super(entity, metadata);
|
||||||
@ -33,4 +35,22 @@ public class FishingHookMeta extends EntityMeta {
|
|||||||
super.metadata.setIndex((byte) 8, Metadata.Boolean(value));
|
super.metadata.setIndex((byte) 8, Metadata.Boolean(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Entity getOwnerEntity() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwnerEntity(@Nullable Entity value) {
|
||||||
|
this.owner = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getObjectData() {
|
||||||
|
return owner != null ? owner.getEntityId() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresVelocityPacketAtSpawn() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ public class ExtensionManager {
|
|||||||
/**
|
/**
|
||||||
* Loads all extensions in the extension folder into this server.
|
* Loads all extensions in the extension folder into this server.
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* Pipeline:
|
* Pipeline:
|
||||||
* <br>
|
* <br>
|
||||||
* Finds all .jar files in the extensions folder.
|
* Finds all .jar files in the extensions folder.
|
||||||
@ -88,32 +88,32 @@ public class ExtensionManager {
|
|||||||
* <br>
|
* <br>
|
||||||
* Verifies that all properties of extension.json are correctly set.
|
* Verifies that all properties of extension.json are correctly set.
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* It then sorts all those jars by their load order (making sure that an extension's dependencies load before it)
|
* It then sorts all those jars by their load order (making sure that an extension's dependencies load before it)
|
||||||
* <br>
|
* <br>
|
||||||
* Note: Cyclic dependencies will stop both extensions from being loaded.
|
* Note: Cyclic dependencies will stop both extensions from being loaded.
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* Afterwards, it loads all external dependencies and adds them to the extension's files
|
* Afterwards, it loads all external dependencies and adds them to the extension's files
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* Then removes any invalid extensions (Invalid being its Load Status isn't SUCCESS)
|
* Then removes any invalid extensions (Invalid being its Load Status isn't SUCCESS)
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* After that, it set its classloaders so each extension is self-contained,
|
* After that, it set its classloaders so each extension is self-contained,
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* Removes invalid extensions again,
|
* Removes invalid extensions again,
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* and loads all of those extensions into Minestom
|
* and loads all of those extensions into Minestom
|
||||||
* <br>
|
* <br>
|
||||||
* (Extension fields are set via reflection after each extension is verified, then loaded.)
|
* (Extension fields are set via reflection after each extension is verified, then loaded.)
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* If the extension successfully loads, add it to the global extension Map (Name to Extension)
|
* If the extension successfully loads, add it to the global extension Map (Name to Extension)
|
||||||
* <br><br>
|
* <br><br>
|
||||||
*
|
* <p>
|
||||||
* And finally make a scheduler to clean observers per extension.
|
* And finally make a scheduler to clean observers per extension.
|
||||||
*/
|
*/
|
||||||
public void loadExtensions() {
|
public void loadExtensions() {
|
||||||
@ -193,7 +193,6 @@ public class ExtensionManager {
|
|||||||
* Loads an extension into Minestom.
|
* Loads an extension into Minestom.
|
||||||
*
|
*
|
||||||
* @param discoveredExtension The extension. Make sure to verify its integrity, set its class loader, and its files.
|
* @param discoveredExtension The extension. Make sure to verify its integrity, set its class loader, and its files.
|
||||||
*
|
|
||||||
* @return An extension object made from this DiscoveredExtension
|
* @return An extension object made from this DiscoveredExtension
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -213,7 +212,8 @@ public class ExtensionManager {
|
|||||||
try {
|
try {
|
||||||
jarClass = Class.forName(mainClass, true, loader);
|
jarClass = Class.forName(mainClass, true, loader);
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
LOGGER.error("Could not find main class '{}' in extension '{}'.", mainClass, extensionName, e);
|
LOGGER.error("Could not find main class '{}' in extension '{}'. If it is, be sure to run your server using Bootstrap#bootstrap",
|
||||||
|
mainClass, extensionName, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ public class ExtensionManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all extensions from the extensions folder and make them discovered.
|
* Get all extensions from the extensions folder and make them discovered.
|
||||||
*
|
* <p>
|
||||||
* It skims the extension folder, discovers and verifies each extension, and returns those created DiscoveredExtensions.
|
* It skims the extension folder, discovers and verifies each extension, and returns those created DiscoveredExtensions.
|
||||||
*
|
*
|
||||||
* @return A list of discovered extensions from this folder.
|
* @return A list of discovered extensions from this folder.
|
||||||
@ -354,7 +354,6 @@ public class ExtensionManager {
|
|||||||
* Grabs a discovered extension from a jar.
|
* Grabs a discovered extension from a jar.
|
||||||
*
|
*
|
||||||
* @param file The jar to grab it from (a .jar is a formatted .zip file)
|
* @param file The jar to grab it from (a .jar is a formatted .zip file)
|
||||||
*
|
|
||||||
* @return The created DiscoveredExtension.
|
* @return The created DiscoveredExtension.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -391,7 +390,8 @@ public class ExtensionManager {
|
|||||||
extensionMap.put(discoveredExtension.getName().toLowerCase(), discoveredExtension);
|
extensionMap.put(discoveredExtension.getName().toLowerCase(), discoveredExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
allExtensions: // go through all the discovered extensions and get their dependencies as extensions
|
allExtensions:
|
||||||
|
// go through all the discovered extensions and get their dependencies as extensions
|
||||||
for (DiscoveredExtension discoveredExtension : discoveredExtensions) {
|
for (DiscoveredExtension discoveredExtension : discoveredExtensions) {
|
||||||
|
|
||||||
List<DiscoveredExtension> dependencies = new ArrayList<>(discoveredExtension.getDependencies().length);
|
List<DiscoveredExtension> dependencies = new ArrayList<>(discoveredExtension.getDependencies().length);
|
||||||
@ -481,6 +481,7 @@ public class ExtensionManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this list of extensions are loaded
|
* Checks if this list of extensions are loaded
|
||||||
|
*
|
||||||
* @param extensions The list of extensions to check against.
|
* @param extensions The list of extensions to check against.
|
||||||
* @return If all of these extensions are loaded.
|
* @return If all of these extensions are loaded.
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +19,7 @@ import net.minestom.server.utils.block.CustomBlockUtils;
|
|||||||
import net.minestom.server.utils.callback.OptionalCallback;
|
import net.minestom.server.utils.callback.OptionalCallback;
|
||||||
import net.minestom.server.utils.chunk.ChunkCallback;
|
import net.minestom.server.utils.chunk.ChunkCallback;
|
||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
import net.minestom.server.world.biomes.Biome;
|
import net.minestom.server.world.biomes.Biome;
|
||||||
@ -145,7 +145,7 @@ public class DynamicChunk extends Chunk {
|
|||||||
final UpdateOption updateOption = customBlock.getUpdateOption();
|
final UpdateOption updateOption = customBlock.getUpdateOption();
|
||||||
if (updateOption != null) {
|
if (updateOption != null) {
|
||||||
final long lastUpdate = updatableBlocksLastUpdate.get(index);
|
final long lastUpdate = updatableBlocksLastUpdate.get(index);
|
||||||
final boolean hasCooldown = CooldownUtils.hasCooldown(time, lastUpdate, updateOption);
|
final boolean hasCooldown = Cooldown.hasCooldown(time, lastUpdate, updateOption);
|
||||||
if (hasCooldown)
|
if (hasCooldown)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import net.minestom.server.utils.Position;
|
|||||||
import net.minestom.server.utils.chunk.ChunkCallback;
|
import net.minestom.server.utils.chunk.ChunkCallback;
|
||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.utils.entity.EntityUtils;
|
import net.minestom.server.utils.entity.EntityUtils;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.Cooldown;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
import net.minestom.server.utils.validate.Check;
|
import net.minestom.server.utils.validate.Check;
|
||||||
@ -1026,7 +1026,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
|||||||
this.time += timeRate;
|
this.time += timeRate;
|
||||||
|
|
||||||
// time needs to be send to players
|
// time needs to be send to players
|
||||||
if (timeUpdate != null && !CooldownUtils.hasCooldown(time, lastTimeUpdate, timeUpdate)) {
|
if (timeUpdate != null && !Cooldown.hasCooldown(time, lastTimeUpdate, timeUpdate)) {
|
||||||
PacketUtils.sendGroupedPacket(getPlayers(), createTimePacket());
|
PacketUtils.sendGroupedPacket(getPlayers(), createTimePacket());
|
||||||
this.lastTimeUpdate = time;
|
this.lastTimeUpdate = time;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
package net.minestom.server.instance.block.rule.vanilla;
|
||||||
|
|
||||||
|
import net.minestom.server.entity.Player;
|
||||||
|
import net.minestom.server.instance.Instance;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
import net.minestom.server.instance.block.BlockAlternative;
|
||||||
|
import net.minestom.server.instance.block.BlockFace;
|
||||||
|
import net.minestom.server.instance.block.rule.BlockPlacementRule;
|
||||||
|
import net.minestom.server.utils.BlockPosition;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class StairsPlacementRule extends BlockPlacementRule {
|
||||||
|
|
||||||
|
public StairsPlacementRule(@NotNull Block block) {
|
||||||
|
super(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short blockUpdate(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentStateID) {
|
||||||
|
return currentStateID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short blockPlace(@NotNull Instance instance, @NotNull Block block, @NotNull BlockFace blockFace, @NotNull BlockPosition blockPosition, @NotNull Player player) {
|
||||||
|
Facing facing = this.getFacing(player);
|
||||||
|
Shape shape = this.getShape(instance, blockPosition, facing);
|
||||||
|
BlockFace half = BlockFace.BOTTOM; // waiting for new block faces to be implemented
|
||||||
|
boolean waterlogged = false; // waiting for water to be implemented
|
||||||
|
return block.withProperties(
|
||||||
|
"facing=" + facing.toString().toLowerCase(),
|
||||||
|
"half=" + half.toString().toLowerCase(),
|
||||||
|
"shape=" + shape.toString().toLowerCase(),
|
||||||
|
"waterlogged=" + waterlogged
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Shape {
|
||||||
|
|
||||||
|
STRAIGHT,
|
||||||
|
OUTER_LEFT,
|
||||||
|
OUTER_RIGHT,
|
||||||
|
INNER_LEFT,
|
||||||
|
INNER_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Facing {
|
||||||
|
|
||||||
|
NORTH(
|
||||||
|
new BlockPosition(0, 0, 1),
|
||||||
|
new BlockPosition(0, 0, -1)
|
||||||
|
),
|
||||||
|
EAST(
|
||||||
|
new BlockPosition(-1, 0, 0),
|
||||||
|
new BlockPosition(1, 0, 0)
|
||||||
|
),
|
||||||
|
SOUTH(
|
||||||
|
new BlockPosition(0, 0, -1),
|
||||||
|
new BlockPosition(0, 0, 1)
|
||||||
|
),
|
||||||
|
WEST(
|
||||||
|
new BlockPosition(1, 0, 0),
|
||||||
|
new BlockPosition(-1, 0, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
private final BlockPosition front;
|
||||||
|
private final BlockPosition back;
|
||||||
|
|
||||||
|
Facing(@NotNull BlockPosition front, @NotNull BlockPosition back) {
|
||||||
|
this.front = front;
|
||||||
|
this.back = back;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Pair<@Nullable Shape, @Nullable Facing> getFront(@NotNull Instance instance, @NotNull BlockPosition blockPosition) {
|
||||||
|
return this.getProperties(instance, blockPosition.clone().add(this.front));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Pair<@Nullable Shape, @Nullable Facing> getBack(@NotNull Instance instance, @NotNull BlockPosition blockPosition) {
|
||||||
|
return this.getProperties(instance, blockPosition.clone().add(this.back));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Pair<@Nullable Shape, @Nullable Facing> getProperties(@NotNull Instance instance, @NotNull BlockPosition blockPosition) {
|
||||||
|
Block block = instance.getBlock(blockPosition);
|
||||||
|
if (block == null) {
|
||||||
|
return Pair.of(null, null);
|
||||||
|
}
|
||||||
|
short stateId = instance.getBlockStateId(blockPosition);
|
||||||
|
BlockAlternative alternative = block.getAlternative(stateId);
|
||||||
|
try {
|
||||||
|
Shape shape = Shape.valueOf(alternative.getProperty("shape").toUpperCase());
|
||||||
|
Facing facing = Facing.valueOf(alternative.getProperty("facing").toUpperCase());
|
||||||
|
return Pair.of(shape, facing);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return Pair.of(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Shape getShape(@NotNull Instance instance, @NotNull BlockPosition blockPosition, @NotNull Facing facing) {
|
||||||
|
Pair<Shape, Facing> front = facing.getFront(instance, blockPosition);
|
||||||
|
Pair<Shape, Facing> back = facing.getBack(instance, blockPosition);
|
||||||
|
Shape shape = this.getShapeFromSide(front, facing, Shape.INNER_RIGHT, Shape.INNER_LEFT);
|
||||||
|
if (shape == null) {
|
||||||
|
shape = this.getShapeFromSide(back, facing, Shape.OUTER_RIGHT, Shape.OUTER_LEFT);
|
||||||
|
}
|
||||||
|
return shape == null ? Shape.STRAIGHT : shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Shape getShapeFromSide(@NotNull Pair<Shape, Facing> side, @NotNull Facing facing, @NotNull Shape right, @NotNull Shape left) {
|
||||||
|
if (side.getLeft() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Facing sideFacing = side.getRight();
|
||||||
|
if (facing.equals(Facing.NORTH)) {
|
||||||
|
if (sideFacing.equals(Facing.EAST)) {
|
||||||
|
return right;
|
||||||
|
} else if (sideFacing.equals(Facing.WEST)) {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
} else if (facing.equals(Facing.SOUTH)) {
|
||||||
|
if (sideFacing.equals(Facing.EAST)) {
|
||||||
|
return left;
|
||||||
|
} else if (sideFacing.equals(Facing.WEST)) {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
} else if (facing.equals(Facing.EAST)) {
|
||||||
|
if (sideFacing.equals(Facing.SOUTH)) {
|
||||||
|
return right;
|
||||||
|
} else if (sideFacing.equals(Facing.NORTH)) {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
} else if (facing.equals(Facing.WEST)) {
|
||||||
|
if (sideFacing.equals(Facing.SOUTH)) {
|
||||||
|
return left;
|
||||||
|
} else if (sideFacing.equals(Facing.NORTH)) {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Facing getFacing(@NotNull Player player) {
|
||||||
|
float degrees = (player.getPosition().getYaw() - 90) % 360;
|
||||||
|
if (degrees < 0) {
|
||||||
|
degrees += 360;
|
||||||
|
}
|
||||||
|
if (0 <= degrees && degrees < 45) {
|
||||||
|
return Facing.WEST;
|
||||||
|
} else if (45 <= degrees && degrees < 135) {
|
||||||
|
return Facing.NORTH;
|
||||||
|
} else if (135 <= degrees && degrees < 225) {
|
||||||
|
return Facing.EAST;
|
||||||
|
} else if (225 <= degrees && degrees < 315) {
|
||||||
|
return Facing.SOUTH;
|
||||||
|
} else { // 315 <= degrees && degrees < 360
|
||||||
|
return Facing.WEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,8 +35,8 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler {
|
|||||||
register(0x1B, ClientPlayerDiggingPacket::new);
|
register(0x1B, ClientPlayerDiggingPacket::new);
|
||||||
register(0x1C, ClientEntityActionPacket::new);
|
register(0x1C, ClientEntityActionPacket::new);
|
||||||
register(0x1D, ClientSteerVehiclePacket::new);
|
register(0x1D, ClientSteerVehiclePacket::new);
|
||||||
register(0x1E, ClientRecipeBookData::new);
|
register(0x1E, ClientSetRecipeBookStatePacket::new);
|
||||||
register(0x1F, ClientRecipeBookData::new);
|
register(0x1F, ClientSetDisplayedRecipePacket::new);
|
||||||
|
|
||||||
|
|
||||||
register(0x20, ClientNameItemPacket::new);
|
register(0x20, ClientNameItemPacket::new);
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
package net.minestom.server.network.packet.client.play;
|
|
||||||
|
|
||||||
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
|
||||||
import net.minestom.server.utils.binary.BinaryReader;
|
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class ClientRecipeBookData extends ClientPlayPacket {
|
|
||||||
|
|
||||||
public int type;
|
|
||||||
|
|
||||||
public String recipeId = "";
|
|
||||||
|
|
||||||
public boolean craftingRecipeBookOpen;
|
|
||||||
public boolean craftingRecipeFilterActive;
|
|
||||||
public boolean smeltingRecipeBookOpen;
|
|
||||||
public boolean smeltingRecipeFilterActive;
|
|
||||||
public boolean blastingRecipeBookOpen;
|
|
||||||
public boolean blastingRecipeFilterActive;
|
|
||||||
public boolean smokingRecipeBookOpen;
|
|
||||||
public boolean smokingRecipeFilterActive;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void read(@NotNull BinaryReader reader) {
|
|
||||||
this.type = reader.readVarInt();
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 0:
|
|
||||||
this.recipeId = reader.readSizedString(256);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this.craftingRecipeBookOpen = reader.readBoolean();
|
|
||||||
this.craftingRecipeFilterActive = reader.readBoolean();
|
|
||||||
this.smeltingRecipeBookOpen = reader.readBoolean();
|
|
||||||
this.smeltingRecipeFilterActive = reader.readBoolean();
|
|
||||||
this.blastingRecipeBookOpen = reader.readBoolean();
|
|
||||||
this.blastingRecipeFilterActive = reader.readBoolean();
|
|
||||||
this.smokingRecipeBookOpen = reader.readBoolean();
|
|
||||||
this.smokingRecipeFilterActive = reader.readBoolean();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull BinaryWriter writer) {
|
|
||||||
writer.writeVarInt(type);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 0:
|
|
||||||
if(recipeId.length() > 256)
|
|
||||||
throw new IllegalArgumentException("recipeId must be less than 256 bytes");
|
|
||||||
writer.writeSizedString(recipeId);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
writer.writeBoolean(this.craftingRecipeBookOpen);
|
|
||||||
writer.writeBoolean(this.craftingRecipeFilterActive);
|
|
||||||
writer.writeBoolean(this.smeltingRecipeBookOpen);
|
|
||||||
writer.writeBoolean(this.smeltingRecipeFilterActive);
|
|
||||||
writer.writeBoolean(this.blastingRecipeBookOpen);
|
|
||||||
writer.writeBoolean(this.blastingRecipeFilterActive);
|
|
||||||
writer.writeBoolean(this.smokingRecipeBookOpen);
|
|
||||||
writer.writeBoolean(this.smokingRecipeFilterActive);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,21 @@
|
|||||||
|
package net.minestom.server.network.packet.client.play;
|
||||||
|
|
||||||
|
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
||||||
|
import net.minestom.server.utils.binary.BinaryReader;
|
||||||
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ClientSetDisplayedRecipePacket extends ClientPlayPacket {
|
||||||
|
|
||||||
|
public String recipeId = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(@NotNull BinaryReader reader) {
|
||||||
|
this.recipeId = reader.readSizedString(256);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull BinaryWriter writer) {
|
||||||
|
writer.writeSizedString(recipeId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.minestom.server.network.packet.client.play;
|
||||||
|
|
||||||
|
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
||||||
|
import net.minestom.server.utils.binary.BinaryReader;
|
||||||
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ClientSetRecipeBookStatePacket extends ClientPlayPacket {
|
||||||
|
|
||||||
|
public BookType type = BookType.CRAFTING;
|
||||||
|
public boolean bookOpen;
|
||||||
|
public boolean filterActive;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(@NotNull BinaryReader reader) {
|
||||||
|
this.type = BookType.values()[reader.readVarInt()];
|
||||||
|
this.bookOpen = reader.readBoolean();
|
||||||
|
this.filterActive = reader.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(@NotNull BinaryWriter writer) {
|
||||||
|
writer.writeVarInt(type.ordinal());
|
||||||
|
writer.writeBoolean(bookOpen);
|
||||||
|
writer.writeBoolean(filterActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BookType {
|
||||||
|
CRAFTING, FURNACE, BLAST_FURNACE, SMOKER
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package net.minestom.server.network.packet.client.status;
|
package net.minestom.server.network.packet.client.status;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.network.packet.client.ClientPreplayPacket;
|
import net.minestom.server.network.packet.client.ClientPreplayPacket;
|
||||||
import net.minestom.server.network.packet.server.handshake.ResponsePacket;
|
import net.minestom.server.network.packet.server.handshake.ResponsePacket;
|
||||||
@ -18,11 +19,11 @@ public class StatusRequestPacket implements ClientPreplayPacket {
|
|||||||
ResponseData responseData = new ResponseData();
|
ResponseData responseData = new ResponseData();
|
||||||
|
|
||||||
// Fill default params
|
// Fill default params
|
||||||
responseData.setName(MinecraftServer.VERSION_NAME);
|
responseData.setVersion(MinecraftServer.VERSION_NAME);
|
||||||
responseData.setProtocol(MinecraftServer.PROTOCOL_VERSION);
|
responseData.setProtocol(MinecraftServer.PROTOCOL_VERSION);
|
||||||
responseData.setMaxPlayer(0);
|
responseData.setMaxPlayer(0);
|
||||||
responseData.setOnline(0);
|
responseData.setOnline(0);
|
||||||
responseData.setDescription("Minestom Server");
|
responseData.setDescription(Component.text("Minestom Server"));
|
||||||
responseData.setFavicon("");
|
responseData.setFavicon("");
|
||||||
|
|
||||||
if (consumer != null)
|
if (consumer != null)
|
||||||
|
@ -2,6 +2,10 @@ package net.minestom.server.ping;
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
|
import net.minestom.server.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -15,19 +19,12 @@ import java.util.UUID;
|
|||||||
* net.minestom.server.MinecraftServer#start(String, int, ResponseDataConsumer)}.
|
* net.minestom.server.MinecraftServer#start(String, int, ResponseDataConsumer)}.
|
||||||
*/
|
*/
|
||||||
public class ResponseData {
|
public class ResponseData {
|
||||||
|
|
||||||
private final JsonObject jsonObject;
|
|
||||||
|
|
||||||
private final JsonObject versionObject;
|
|
||||||
private final JsonObject playersObject;
|
|
||||||
private final JsonArray sampleArray;
|
|
||||||
private final JsonObject descriptionObject;
|
|
||||||
private final List<PingPlayer> pingPlayers;
|
private final List<PingPlayer> pingPlayers;
|
||||||
private String name;
|
private String version;
|
||||||
private int protocol;
|
private int protocol;
|
||||||
private int maxPlayer;
|
private int maxPlayer;
|
||||||
private int online;
|
private int online;
|
||||||
private String description;
|
private Component description;
|
||||||
|
|
||||||
private String favicon;
|
private String favicon;
|
||||||
|
|
||||||
@ -35,11 +32,6 @@ public class ResponseData {
|
|||||||
* Constructs a new {@link ResponseData}.
|
* Constructs a new {@link ResponseData}.
|
||||||
*/
|
*/
|
||||||
public ResponseData() {
|
public ResponseData() {
|
||||||
this.jsonObject = new JsonObject();
|
|
||||||
this.versionObject = new JsonObject();
|
|
||||||
this.playersObject = new JsonObject();
|
|
||||||
this.sampleArray = new JsonArray();
|
|
||||||
this.descriptionObject = new JsonObject();
|
|
||||||
this.pingPlayers = new ArrayList<>();
|
this.pingPlayers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +39,20 @@ public class ResponseData {
|
|||||||
* Sets the name for the response.
|
* Sets the name for the response.
|
||||||
*
|
*
|
||||||
* @param name The name for the response data.
|
* @param name The name for the response data.
|
||||||
|
* @deprecated Use {@link #setVersion(String)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.setVersion(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the version name for the response.
|
||||||
|
*
|
||||||
|
* @param version The version name for the response data.
|
||||||
|
*/
|
||||||
|
public void setVersion(String version) {
|
||||||
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,6 +82,26 @@ public class ResponseData {
|
|||||||
this.online = online;
|
this.online = online;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds some players to the response.
|
||||||
|
*
|
||||||
|
* @param players the players
|
||||||
|
*/
|
||||||
|
public void addPlayer(Iterable<Player> players) {
|
||||||
|
for (Player player : players) {
|
||||||
|
this.addPlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a player to the response.
|
||||||
|
*
|
||||||
|
* @param player the player
|
||||||
|
*/
|
||||||
|
public void addPlayer(Player player) {
|
||||||
|
this.addPlayer(player.getUsername(), player.getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a player to the response.
|
* Adds a player to the response.
|
||||||
*
|
*
|
||||||
@ -104,8 +127,19 @@ public class ResponseData {
|
|||||||
* Sets the response description.
|
* Sets the response description.
|
||||||
*
|
*
|
||||||
* @param description The description for the response data.
|
* @param description The description for the response data.
|
||||||
|
* @deprecated Use {@link #setDescription(Component)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setDescription(String description) {
|
public void setDescription(String description) {
|
||||||
|
this.description = LegacyComponentSerializer.legacySection().deserialize(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the response description.
|
||||||
|
*
|
||||||
|
* @param description The description for the response data.
|
||||||
|
*/
|
||||||
|
public void setDescription(Component description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,13 +159,19 @@ public class ResponseData {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsonObject build() {
|
public JsonObject build() {
|
||||||
versionObject.addProperty("name", name);
|
// version
|
||||||
versionObject.addProperty("protocol", protocol);
|
final JsonObject versionObject = new JsonObject();
|
||||||
|
versionObject.addProperty("name", this.version);
|
||||||
|
versionObject.addProperty("protocol", this.protocol);
|
||||||
|
|
||||||
playersObject.addProperty("max", maxPlayer);
|
// players info
|
||||||
playersObject.addProperty("online", online);
|
final JsonObject playersObject = new JsonObject();
|
||||||
|
playersObject.addProperty("max", this.maxPlayer);
|
||||||
|
playersObject.addProperty("online", this.online);
|
||||||
|
|
||||||
for (PingPlayer pingPlayer : pingPlayers) {
|
// individual players
|
||||||
|
final JsonArray sampleArray = new JsonArray();
|
||||||
|
for (PingPlayer pingPlayer : this.pingPlayers) {
|
||||||
JsonObject pingPlayerObject = new JsonObject();
|
JsonObject pingPlayerObject = new JsonObject();
|
||||||
pingPlayerObject.addProperty("name", pingPlayer.name);
|
pingPlayerObject.addProperty("name", pingPlayer.name);
|
||||||
pingPlayerObject.addProperty("id", pingPlayer.uuid.toString());
|
pingPlayerObject.addProperty("id", pingPlayer.uuid.toString());
|
||||||
@ -139,12 +179,14 @@ public class ResponseData {
|
|||||||
}
|
}
|
||||||
playersObject.add("sample", sampleArray);
|
playersObject.add("sample", sampleArray);
|
||||||
|
|
||||||
descriptionObject.addProperty("text", description);
|
final JsonObject descriptionObject = GsonComponentSerializer.gson().serializer()
|
||||||
|
.toJsonTree(this.description).getAsJsonObject();
|
||||||
|
|
||||||
|
final JsonObject jsonObject = new JsonObject();
|
||||||
jsonObject.add("version", versionObject);
|
jsonObject.add("version", versionObject);
|
||||||
jsonObject.add("players", playersObject);
|
jsonObject.add("players", playersObject);
|
||||||
jsonObject.add("description", descriptionObject);
|
jsonObject.add("description", descriptionObject);
|
||||||
jsonObject.addProperty("favicon", favicon);
|
jsonObject.addProperty("favicon", this.favicon);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,18 +212,6 @@ public class BlockPosition implements PublicCloneable<BlockPosition> {
|
|||||||
MathUtils.square(getZ() - blockPosition.getZ());
|
MathUtils.square(getZ() - blockPosition.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies this block position.
|
|
||||||
*
|
|
||||||
* @return the cloned block position
|
|
||||||
* @deprecated use {@link #clone()}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@NotNull
|
|
||||||
public BlockPosition copy() {
|
|
||||||
return clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public BlockPosition clone() {
|
public BlockPosition clone() {
|
||||||
|
@ -212,14 +212,6 @@ public class Position implements PublicCloneable<Position> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use {@link #clone()}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Position copy() {
|
|
||||||
return clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets if the two objects are position and have the same values.
|
* Gets if the two objects are position and have the same values.
|
||||||
*
|
*
|
||||||
|
@ -476,15 +476,6 @@ public class Vector implements PublicCloneable<Vector> {
|
|||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated use {@link #clone()}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@NotNull
|
|
||||||
public Vector copy() {
|
|
||||||
return clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Vector clone() {
|
public Vector clone() {
|
||||||
|
@ -2,10 +2,26 @@ package net.minestom.server.utils.time;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public final class CooldownUtils {
|
public final class Cooldown {
|
||||||
|
|
||||||
private CooldownUtils() {
|
private UpdateOption updateOption;
|
||||||
|
private long lastUpdate;
|
||||||
|
|
||||||
|
public Cooldown(@NotNull UpdateOption updateOption) {
|
||||||
|
this.updateOption = updateOption;
|
||||||
|
this.lastUpdate = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateOption getUpdateOption() {
|
||||||
|
return this.updateOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshLastUpdate(long lastUpdate) {
|
||||||
|
this.lastUpdate = lastUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReady(long time) {
|
||||||
|
return !hasCooldown(time, lastUpdate, updateOption.getTimeUnit(), updateOption.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -1,6 +1,8 @@
|
|||||||
package net.minestom.server.world;
|
package net.minestom.server.world;
|
||||||
|
|
||||||
|
import net.minestom.server.utils.NamespaceID;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
|
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
|
||||||
@ -43,6 +45,33 @@ public final class DimensionTypeManager {
|
|||||||
return dimensionTypes.remove(dimensionType);
|
return dimensionTypes.remove(dimensionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param namespaceID The dimension name
|
||||||
|
* @return true if the dimension is registered
|
||||||
|
*/
|
||||||
|
public boolean isRegistered(@NotNull NamespaceID namespaceID) {
|
||||||
|
return isRegistered(getDimension(namespaceID));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dimensionType dimension to check if is registered
|
||||||
|
* @return true if the dimension is registered
|
||||||
|
*/
|
||||||
|
public boolean isRegistered(@Nullable DimensionType dimensionType) {
|
||||||
|
return dimensionType != null && dimensionTypes.contains(dimensionType) && dimensionType.isRegistered();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return to a @{@link DimensionType} only if present and registered
|
||||||
|
*
|
||||||
|
* @param namespaceID The Dimension Name
|
||||||
|
* @return an a DimensionType if it present and registered
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public DimensionType getDimension(@NotNull NamespaceID namespaceID) {
|
||||||
|
return unmodifiableList().stream().filter(dimensionType -> dimensionType.getName().equals(namespaceID)).filter(DimensionType::isRegistered).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an immutable copy of the dimension types already registered.
|
* Returns an immutable copy of the dimension types already registered.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user