mirror of
https://github.com/Minestom/Minestom.git
synced 2024-11-17 08:05:25 +01:00
Merge branch 'master' of https://github.com/Minestom/Minestom
Conflicts: src/main/java/fr/themode/demo/PlayerInit.java src/main/java/fr/themode/demo/generator/NoiseTestGenerator.java src/main/java/net/minestom/server/utils/chunk/ChunkUtils.java
This commit is contained in:
commit
c16b716350
3
.gitignore
vendored
3
.gitignore
vendored
@ -50,3 +50,6 @@ gradle-app.setting
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
/src/main/java/com/mcecraft/
|
||||
|
||||
# When running the demo we generate the extensions folder
|
||||
extensions/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
package fr.themode.demo;
|
||||
|
||||
import fr.themode.demo.entity.ChickenCreature;
|
||||
import fr.themode.demo.blocks.StoneBlock;
|
||||
import fr.themode.demo.generator.ChunkGeneratorDemo;
|
||||
import fr.themode.demo.generator.NoiseTestGenerator;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
@ -8,6 +8,7 @@ import net.minestom.server.benchmark.BenchmarkManager;
|
||||
import net.minestom.server.benchmark.ThreadResult;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.entity.*;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.event.entity.EntityAttackEvent;
|
||||
@ -20,6 +21,7 @@ import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
import net.minestom.server.instance.WorldBorder;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.inventory.InventoryType;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
@ -28,6 +30,7 @@ import net.minestom.server.item.metadata.MapMeta;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.ping.ResponseDataConsumer;
|
||||
import net.minestom.server.scoreboard.Sidebar;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.Vector;
|
||||
@ -35,19 +38,16 @@ import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerInit {
|
||||
private static volatile InstanceContainer instanceContainer;
|
||||
//private static volatile InstanceContainer netherTest;
|
||||
|
||||
private static Random r = new Random();
|
||||
|
||||
private static volatile Inventory inventory;
|
||||
|
||||
static {
|
||||
//StorageFolder storageFolder = MinecraftServer.getStorageManager().getFolder("instance_data", new StorageOption().setCompression(true));
|
||||
//StorageFolder storageFolder = MinecraftServer.getStorageManager().getFolder("instance_data", new StorageOptions().setCompression(true));
|
||||
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
|
||||
NoiseTestGenerator noiseTestGenerator = new NoiseTestGenerator();
|
||||
//instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(storageFolder);
|
||||
@ -156,10 +156,10 @@ public class PlayerInit {
|
||||
p.teleport(player.getPosition());
|
||||
}*/
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
/*for (int i = 0; i < 100; i++) {
|
||||
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
|
||||
chickenCreature.setInstance(player.getInstance());
|
||||
}
|
||||
}*/
|
||||
|
||||
/*EntityZombie zombie = new EntityZombie(player.getPosition());
|
||||
zombie.setAttribute(Attribute.MOVEMENT_SPEED, 0.25f);
|
||||
@ -186,6 +186,17 @@ public class PlayerInit {
|
||||
if (event.getHand() != Player.Hand.MAIN)
|
||||
return;
|
||||
|
||||
final Instance instance = player.getInstance();
|
||||
final BlockPosition blockPosition = event.getBlockPosition();
|
||||
|
||||
final CustomBlock customBlock = instance.getCustomBlock(blockPosition);
|
||||
if (customBlock instanceof StoneBlock) {
|
||||
final Data data = instance.getBlockData(blockPosition);
|
||||
if (data != null) {
|
||||
player.sendMessage("test: " + data.get("test"));
|
||||
}
|
||||
}
|
||||
|
||||
final short blockStateId = player.getInstance().getBlockStateId(event.getBlockPosition());
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
player.sendMessage("You clicked at the block " + block);
|
||||
@ -260,8 +271,8 @@ public class PlayerInit {
|
||||
});
|
||||
|
||||
player.addEventCallback(PlayerSpawnEvent.class, event -> {
|
||||
player.setGameMode(GameMode.CREATIVE);
|
||||
player.teleport(new Position(r.nextInt(200)-100, 73, r.nextInt(200)-100));
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
player.teleport(new Position(0, 41f, 0));
|
||||
|
||||
//player.setHeldItemSlot((byte) 5);
|
||||
|
||||
@ -378,7 +389,7 @@ public class PlayerInit {
|
||||
|
||||
// Unload the chunk (save memory) if it has no remaining viewer
|
||||
if (chunk.getViewers().isEmpty()) {
|
||||
player.getInstance().unloadChunk(chunk);
|
||||
//player.getInstance().unloadChunk(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -20,8 +20,8 @@ public class BurningTorchBlock extends CustomBlock {
|
||||
|
||||
@Override
|
||||
public void handleContact(Instance instance, BlockPosition position, Entity touching) {
|
||||
System.out.println("touching "+touching);
|
||||
if(touching instanceof LivingEntity) {
|
||||
System.out.println("touching " + touching);
|
||||
if (touching instanceof LivingEntity) {
|
||||
((LivingEntity) touching).damage(DamageType.GRAVITY, 0.1f);
|
||||
}
|
||||
}
|
||||
@ -45,9 +45,4 @@ public class BurningTorchBlock extends CustomBlock {
|
||||
public short getCustomBlockId() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBreakDelay(Player player, BlockPosition position) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class StoneBlock extends CustomBlock {
|
||||
|
||||
public StoneBlock() {
|
||||
@ -39,8 +41,18 @@ public class StoneBlock extends CustomBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBreakDelay(Player player, BlockPosition position) {
|
||||
return 750;
|
||||
public int getBreakDelay(Player player, BlockPosition position, byte stage, Set<Player> breakers) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableCustomBreakDelay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableMultiPlayerBreaking() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,6 +9,8 @@ import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class UpdatableBlockDemo extends CustomBlock {
|
||||
|
||||
private static final UpdateOption UPDATE_OPTION = new UpdateOption(20, TimeUnit.TICK);
|
||||
@ -43,8 +45,13 @@ public class UpdatableBlockDemo extends CustomBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBreakDelay(Player player, BlockPosition position) {
|
||||
return 500;
|
||||
public int getBreakDelay(Player player, BlockPosition position, byte stage, Set<Player> breakers) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableCustomBreakDelay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,6 +67,10 @@ public class SimpleCommand implements CommandProcessor {
|
||||
NotificationCenter.send(notification, player);
|
||||
NotificationCenter.send(notification, player);
|
||||
|
||||
System.gc();
|
||||
|
||||
//player.getInstance().saveChunksToStorageFolder(() -> System.out.println("end save"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@ import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.data.SerializableData;
|
||||
import net.minestom.server.entity.EntityManager;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.extensions.Extension;
|
||||
import net.minestom.server.extensions.ExtensionManager;
|
||||
import net.minestom.server.extras.mojangAuth.MojangCrypt;
|
||||
import net.minestom.server.fluids.Fluid;
|
||||
import net.minestom.server.gamedata.loottables.LootTableManager;
|
||||
@ -33,7 +35,6 @@ import net.minestom.server.network.packet.server.play.PluginMessagePacket;
|
||||
import net.minestom.server.network.packet.server.play.ServerDifficultyPacket;
|
||||
import net.minestom.server.particle.Particle;
|
||||
import net.minestom.server.ping.ResponseDataConsumer;
|
||||
import net.minestom.server.plugins.PluginManager;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.registry.ResourceGatherer;
|
||||
@ -102,8 +103,6 @@ public class MinecraftServer {
|
||||
//Rate Limiting
|
||||
private static int rateLimit = 0;
|
||||
|
||||
// Networking
|
||||
private static PacketProcessor packetProcessor;
|
||||
private static PacketListenerManager packetListenerManager;
|
||||
private static NettyServer nettyServer;
|
||||
|
||||
@ -123,7 +122,7 @@ public class MinecraftServer {
|
||||
private static BiomeManager biomeManager;
|
||||
private static AdvancementManager advancementManager;
|
||||
|
||||
private static PluginManager pluginManager;
|
||||
private static ExtensionManager extensionManager;
|
||||
|
||||
private static UpdateManager updateManager;
|
||||
private static MinecraftServer minecraftServer;
|
||||
@ -161,7 +160,8 @@ public class MinecraftServer {
|
||||
Fluid.values();
|
||||
|
||||
connectionManager = new ConnectionManager();
|
||||
packetProcessor = new PacketProcessor();
|
||||
// Networking
|
||||
final PacketProcessor packetProcessor = new PacketProcessor();
|
||||
packetListenerManager = new PacketListenerManager();
|
||||
|
||||
instanceManager = new InstanceManager();
|
||||
@ -180,7 +180,7 @@ public class MinecraftServer {
|
||||
|
||||
updateManager = new UpdateManager();
|
||||
|
||||
pluginManager = PluginManager.getInstance();
|
||||
extensionManager = new ExtensionManager();
|
||||
|
||||
lootTableManager = new LootTableManager();
|
||||
tagManager = new TagManager();
|
||||
@ -452,8 +452,14 @@ public class MinecraftServer {
|
||||
updateManager.start();
|
||||
nettyServer.start(address, port);
|
||||
long t1 = -System.nanoTime();
|
||||
pluginManager.loadPlugins();
|
||||
LOGGER.info("Plugins loaded in " + (t1 + System.nanoTime()) / 1_000_000D + "ms");
|
||||
extensionManager.loadExtensionJARs();
|
||||
// Init extensions
|
||||
// TODO: Extensions should handle depending on each other and have a load-order.
|
||||
extensionManager.getExtensions().forEach(Extension::preInitialize);
|
||||
extensionManager.getExtensions().forEach(Extension::initialize);
|
||||
extensionManager.getExtensions().forEach(Extension::postInitialize);
|
||||
|
||||
LOGGER.info("Extensions loaded in " + (t1 + System.nanoTime()) / 1_000_000D + "ms");
|
||||
LOGGER.info("Minestom server started successfully.");
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import net.minestom.server.utils.thread.MinestomThread;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
@ -61,7 +62,7 @@ public final class UpdateManager {
|
||||
//Tick Callbacks
|
||||
tickStartCallbacks.forEach(Runnable::run);
|
||||
|
||||
ArrayList<Future<?>> futures;
|
||||
List<Future<?>> futures;
|
||||
|
||||
// Server tick (instance/chunk/entity)
|
||||
// Synchronize with the update manager instance, like the signal for chunk load/unload
|
||||
|
@ -11,7 +11,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class AdvancementManager {
|
||||
|
||||
private Map<String, AdvancementTab> advancementTabMap = new HashMap<>();
|
||||
private final Map<String, AdvancementTab> advancementTabMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new tab with a single advancement
|
||||
|
@ -16,14 +16,14 @@ import java.util.*;
|
||||
*/
|
||||
public class AdvancementTab implements Viewable {
|
||||
|
||||
private static Map<Player, Set<AdvancementTab>> playerTabMap = new HashMap<>();
|
||||
private static final Map<Player, Set<AdvancementTab>> PLAYER_TAB_MAP = new HashMap<>();
|
||||
|
||||
private Set<Player> viewers = new HashSet<>();
|
||||
private final Set<Player> viewers = new HashSet<>();
|
||||
|
||||
private AdvancementRoot root;
|
||||
private final AdvancementRoot root;
|
||||
|
||||
// Advancement -> its parent
|
||||
private Map<Advancement, Advancement> advancementMap = new HashMap<>();
|
||||
private final Map<Advancement, Advancement> advancementMap = new HashMap<>();
|
||||
|
||||
// Packet cache, updated every time the tab changes
|
||||
protected ByteBuf createBuffer;
|
||||
@ -47,7 +47,7 @@ public class AdvancementTab implements Viewable {
|
||||
* @return all the advancement tabs that the player sees
|
||||
*/
|
||||
public static Set<AdvancementTab> getTabs(Player player) {
|
||||
return playerTabMap.getOrDefault(player, null);
|
||||
return PLAYER_TAB_MAP.getOrDefault(player, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,7 +171,7 @@ public class AdvancementTab implements Viewable {
|
||||
* @param player the player
|
||||
*/
|
||||
private void addPlayer(Player player) {
|
||||
Set<AdvancementTab> tabs = playerTabMap.computeIfAbsent(player, p -> new HashSet<>());
|
||||
Set<AdvancementTab> tabs = PLAYER_TAB_MAP.computeIfAbsent(player, p -> new HashSet<>());
|
||||
tabs.add(this);
|
||||
}
|
||||
|
||||
@ -181,13 +181,13 @@ public class AdvancementTab implements Viewable {
|
||||
* @param player the player
|
||||
*/
|
||||
private void removePlayer(Player player) {
|
||||
if (!playerTabMap.containsKey(player)) {
|
||||
if (!PLAYER_TAB_MAP.containsKey(player)) {
|
||||
return;
|
||||
}
|
||||
Set<AdvancementTab> tabs = playerTabMap.get(player);
|
||||
Set<AdvancementTab> tabs = PLAYER_TAB_MAP.get(player);
|
||||
tabs.remove(this);
|
||||
if (tabs.isEmpty()) {
|
||||
playerTabMap.remove(player);
|
||||
PLAYER_TAB_MAP.remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ public class BenchmarkManager {
|
||||
|
||||
private boolean enabled = false;
|
||||
private volatile boolean stop = false;
|
||||
private Thread thread;
|
||||
|
||||
private long time;
|
||||
|
||||
@ -51,7 +50,7 @@ public class BenchmarkManager {
|
||||
|
||||
time = updateOption.getTimeUnit().toMilliseconds(updateOption.getValue());
|
||||
|
||||
this.thread = new Thread(null, () -> {
|
||||
final Thread thread = new Thread(null, () -> {
|
||||
|
||||
while (!stop) {
|
||||
refreshData();
|
||||
@ -67,7 +66,7 @@ public class BenchmarkManager {
|
||||
|
||||
}, MinecraftServer.THREAD_NAME_BENCHMARK, 0L);
|
||||
|
||||
this.thread.start();
|
||||
thread.start();
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class ColoredText {
|
||||
}
|
||||
|
||||
private static String toLegacy(String message, char colorChar) {
|
||||
String result = "";
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < message.length(); i++) {
|
||||
final char c = message.charAt(i);
|
||||
@ -71,19 +71,19 @@ public class ColoredText {
|
||||
final char nextChar = message.charAt(i + 1);
|
||||
final ChatColor color = ChatColor.fromLegacyColorCodes(nextChar);
|
||||
if (color != ChatColor.NO_COLOR) {
|
||||
String replacement = color.toString();
|
||||
result += replacement;
|
||||
final String replacement = color.toString();
|
||||
result.append(replacement);
|
||||
i++; // Increment to ignore the color code
|
||||
} else {
|
||||
result += c;
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result += c;
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public ColoredText appendLegacy(String message, char colorChar) {
|
||||
|
@ -39,11 +39,11 @@ public class TranslatableText {
|
||||
final String prefix = "{@";
|
||||
final String suffix = "}";
|
||||
|
||||
String content = code;
|
||||
StringBuilder content = new StringBuilder(code);
|
||||
|
||||
if (arguments != null && arguments.length > 0) {
|
||||
for (String arg : arguments) {
|
||||
content += "," + arg;
|
||||
content.append("," + arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ public class CollisionUtils {
|
||||
// find the corner which moved the least
|
||||
float smallestDisplacement = Float.POSITIVE_INFINITY;
|
||||
for (int i = 0; i < corners.length; i++) {
|
||||
float displacement = (float) corners[i].distance(cornersCopy[i]);
|
||||
final float displacement = (float) corners[i].distance(cornersCopy[i]);
|
||||
if (displacement < smallestDisplacement) {
|
||||
smallestDisplacement = displacement;
|
||||
}
|
||||
|
@ -104,37 +104,41 @@ public class CommandDispatcher {
|
||||
// true if the arg is valid, false otherwise
|
||||
boolean correct = false;
|
||||
// the raw string representing the correct argument syntax
|
||||
String argValue = "";
|
||||
StringBuilder argValue = new StringBuilder();
|
||||
|
||||
if (useRemaining) {
|
||||
for (int i = argIndex; i < args.length; i++) {
|
||||
final String arg = args[i];
|
||||
if (argValue.length() > 0)
|
||||
argValue += " ";
|
||||
argValue += arg;
|
||||
argValue.append(" ");
|
||||
argValue.append(arg);
|
||||
}
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValue);
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValueString);
|
||||
if (correctionResult == Argument.SUCCESS) {
|
||||
correct = true;
|
||||
argsValues[argIndex] = argValue;
|
||||
argsValues[argIndex] = argValueString;
|
||||
}
|
||||
} else {
|
||||
for (int i = argIndex; i < args.length; i++) {
|
||||
final String arg = args[i];
|
||||
|
||||
argValue += arg;
|
||||
argValue.append(arg);
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValue);
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
correctionResult = argument.getCorrectionResult(argValueString);
|
||||
if (correctionResult == Argument.SUCCESS) {
|
||||
correct = true;
|
||||
argsValues[argIndex] = argValue;
|
||||
argsValues[argIndex] = argValueString;
|
||||
argIndex = i + 1;
|
||||
break;
|
||||
} else {
|
||||
if (!argument.allowSpace())
|
||||
break;
|
||||
argValue += " ";
|
||||
argValue.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,7 +149,7 @@ public class CommandDispatcher {
|
||||
syntaxCorrect = false;
|
||||
CommandSuggestionHolder suggestionHolder = new CommandSuggestionHolder();
|
||||
suggestionHolder.syntax = syntax;
|
||||
suggestionHolder.argValue = argValue;
|
||||
suggestionHolder.argValue = argValue.toString();
|
||||
suggestionHolder.correctionResult = correctionResult;
|
||||
suggestionHolder.argIndex = argCount;
|
||||
syntaxesSuggestions.put(argCount, suggestionHolder);
|
||||
@ -222,7 +226,7 @@ public class CommandDispatcher {
|
||||
return result;
|
||||
}
|
||||
|
||||
private class CommandSuggestionHolder {
|
||||
private static class CommandSuggestionHolder {
|
||||
private CommandSyntax syntax;
|
||||
private String argValue;
|
||||
private int correctionResult;
|
||||
@ -230,7 +234,7 @@ public class CommandDispatcher {
|
||||
|
||||
}
|
||||
|
||||
private class CommandResult {
|
||||
private static class CommandResult {
|
||||
|
||||
// Command
|
||||
private Command command;
|
||||
|
@ -27,7 +27,7 @@ public class Data {
|
||||
}
|
||||
};
|
||||
|
||||
protected ConcurrentHashMap<String, Object> data = new ConcurrentHashMap();
|
||||
protected final ConcurrentHashMap<String, Object> data = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Set a value to a specific key
|
||||
|
@ -79,7 +79,8 @@ public final class DataManager {
|
||||
* @throws NullPointerException if none is found
|
||||
*/
|
||||
public <T> DataType<T> getDataType(Class<T> clazz) {
|
||||
return dataTypeMap.get(PrimitiveConversion.getObjectClass(clazz));
|
||||
clazz = PrimitiveConversion.getObjectClass(clazz);
|
||||
return dataTypeMap.get(clazz);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data;
|
||||
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public abstract class DataType<T> {
|
||||
|
||||
/**
|
||||
* Encode the data type
|
||||
*
|
||||
* @param packetWriter the data writer
|
||||
* @param value the value to encode
|
||||
* @param writer the data writer
|
||||
* @param value the value to encode
|
||||
*/
|
||||
public abstract void encode(PacketWriter packetWriter, T value);
|
||||
public abstract void encode(BinaryWriter writer, T value);
|
||||
|
||||
/**
|
||||
* Decode the data type
|
||||
*
|
||||
* @param packetReader the data reader
|
||||
* @param reader the data reader
|
||||
* @return the decoded value
|
||||
*/
|
||||
public abstract T decode(PacketReader packetReader);
|
||||
public abstract T decode(BinaryReader reader);
|
||||
|
||||
}
|
@ -1,13 +1,9 @@
|
||||
package net.minestom.server.data;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.PrimitiveConversion;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SerializableData extends Data {
|
||||
@ -52,36 +48,28 @@ public class SerializableData extends Data {
|
||||
* to convert it back
|
||||
*
|
||||
* @return the array representation of this data object
|
||||
* @throws IOException if an error occur when serializing the data
|
||||
*/
|
||||
public byte[] getSerializedData() throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(output);
|
||||
public byte[] getSerializedData() {
|
||||
BinaryWriter binaryWriter = new BinaryWriter();
|
||||
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
data.forEach((key, value) -> {
|
||||
final Class type = dataType.get(key);
|
||||
final Object value = entry.getValue();
|
||||
final DataType dataType = DATA_MANAGER.getDataType(type);
|
||||
|
||||
final byte[] encodedType = PrimitiveConversion.getObjectClassString(type.getName()).getBytes(); // Data type (fix for primitives)
|
||||
dos.writeShort(encodedType.length);
|
||||
dos.write(encodedType);
|
||||
// Write the data type
|
||||
final String encodedType = PrimitiveConversion.getObjectClassString(type.getName()); // Data type (fix for primitives)
|
||||
binaryWriter.writeSizedString(encodedType);
|
||||
|
||||
final byte[] encodedName = key.getBytes(); // Data name
|
||||
dos.writeShort(encodedName.length);
|
||||
dos.write(encodedName);
|
||||
// Write the data key
|
||||
binaryWriter.writeSizedString(key);
|
||||
|
||||
PacketWriter packetWriter = new PacketWriter();
|
||||
dataType.encode(packetWriter, value); // Encode
|
||||
final byte[] encodedValue = packetWriter.toByteArray(); // Retrieve bytes
|
||||
dos.writeInt(encodedValue.length);
|
||||
dos.write(encodedValue);
|
||||
}
|
||||
// Write the data (no length)
|
||||
dataType.encode(binaryWriter, value);
|
||||
});
|
||||
|
||||
dos.writeShort(0xff); // End of data object
|
||||
binaryWriter.writeVarInt(0); // End of data object
|
||||
|
||||
return output.toByteArray();
|
||||
return binaryWriter.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class BooleanData extends DataType<Boolean> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Boolean value) {
|
||||
packetWriter.writeBoolean(value);
|
||||
public void encode(BinaryWriter writer, Boolean value) {
|
||||
writer.writeBoolean(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean decode(PacketReader packetReader) {
|
||||
return packetReader.readBoolean();
|
||||
public Boolean decode(BinaryReader reader) {
|
||||
return reader.readBoolean();
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class ByteData extends DataType<Byte> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Byte value) {
|
||||
packetWriter.writeByte(value);
|
||||
public void encode(BinaryWriter writer, Byte value) {
|
||||
writer.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte decode(PacketReader packetReader) {
|
||||
return packetReader.readByte();
|
||||
public Byte decode(BinaryReader reader) {
|
||||
return reader.readByte();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class CharacterData extends DataType<Character> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Character value) {
|
||||
packetWriter.writeChar(value);
|
||||
public void encode(BinaryWriter writer, Character value) {
|
||||
writer.writeChar(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character decode(PacketReader packetReader) {
|
||||
return packetReader.readChar();
|
||||
public Character decode(BinaryReader reader) {
|
||||
return reader.readChar();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class DoubleData extends DataType<Double> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Double value) {
|
||||
packetWriter.writeDouble(value);
|
||||
public void encode(BinaryWriter writer, Double value) {
|
||||
writer.writeDouble(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double decode(PacketReader packetReader) {
|
||||
return packetReader.readDouble();
|
||||
public Double decode(BinaryReader reader) {
|
||||
return reader.readDouble();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class FloatData extends DataType<Float> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Float value) {
|
||||
packetWriter.writeFloat(value);
|
||||
public void encode(BinaryWriter writer, Float value) {
|
||||
writer.writeFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float decode(PacketReader packetReader) {
|
||||
return packetReader.readFloat();
|
||||
public Float decode(BinaryReader reader) {
|
||||
return reader.readFloat();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class IntegerData extends DataType<Integer> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Integer value) {
|
||||
packetWriter.writeVarInt(value);
|
||||
public void encode(BinaryWriter writer, Integer value) {
|
||||
writer.writeVarInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer decode(PacketReader packetReader) {
|
||||
return packetReader.readVarInt();
|
||||
public Integer decode(BinaryReader reader) {
|
||||
return reader.readVarInt();
|
||||
}
|
||||
}
|
@ -3,37 +3,37 @@ package net.minestom.server.data.type;
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.inventory.InventoryType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class InventoryData extends DataType<Inventory> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Inventory value) {
|
||||
public void encode(BinaryWriter writer, Inventory value) {
|
||||
final InventoryType inventoryType = value.getInventoryType();
|
||||
final int size = inventoryType.getAdditionalSlot();
|
||||
|
||||
// Inventory title & type
|
||||
packetWriter.writeSizedString(value.getTitle());
|
||||
packetWriter.writeSizedString(inventoryType.name());
|
||||
writer.writeSizedString(value.getTitle());
|
||||
writer.writeSizedString(inventoryType.name());
|
||||
|
||||
// Write all item stacks
|
||||
for (int i = 0; i < size; i++) {
|
||||
packetWriter.writeItemStack(value.getItemStack(i));
|
||||
writer.writeItemStack(value.getItemStack(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory decode(PacketReader packetReader) {
|
||||
final String title = packetReader.readSizedString();
|
||||
final InventoryType inventoryType = InventoryType.valueOf(packetReader.readSizedString());
|
||||
public Inventory decode(BinaryReader reader) {
|
||||
final String title = reader.readSizedString();
|
||||
final InventoryType inventoryType = InventoryType.valueOf(reader.readSizedString());
|
||||
final int size = inventoryType.getAdditionalSlot();
|
||||
|
||||
Inventory inventory = new Inventory(inventoryType, title);
|
||||
|
||||
// Read all item stacks
|
||||
for (int i = 0; i < size; i++) {
|
||||
inventory.setItemStack(i, packetReader.readSlot());
|
||||
inventory.setItemStack(i, reader.readSlot());
|
||||
}
|
||||
|
||||
return inventory;
|
||||
|
@ -2,17 +2,17 @@ package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class ItemStackData extends DataType<ItemStack> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, ItemStack value) {
|
||||
packetWriter.writeItemStack(value);
|
||||
public void encode(BinaryWriter writer, ItemStack value) {
|
||||
writer.writeItemStack(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack decode(PacketReader packetReader) {
|
||||
return packetReader.readSlot();
|
||||
public ItemStack decode(BinaryReader reader) {
|
||||
return reader.readSlot();
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class LongData extends DataType<Long> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Long value) {
|
||||
packetWriter.writeLong(value);
|
||||
public void encode(BinaryWriter writer, Long value) {
|
||||
writer.writeLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decode(PacketReader packetReader) {
|
||||
return packetReader.readLong();
|
||||
public Long decode(BinaryReader reader) {
|
||||
return reader.readLong();
|
||||
}
|
||||
}
|
||||
|
@ -2,27 +2,20 @@ package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.data.SerializableData;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.reader.DataReader;
|
||||
|
||||
import java.io.IOException;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
// Pretty weird name huh?
|
||||
public class SerializableDataData extends DataType<SerializableData> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, SerializableData value) {
|
||||
try {
|
||||
packetWriter.writeBytes(value.getSerializedData());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalArgumentException("error while writing the data");
|
||||
}
|
||||
public void encode(BinaryWriter writer, SerializableData value) {
|
||||
writer.writeBytes(value.getSerializedData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SerializableData decode(PacketReader packetReader) {
|
||||
return DataReader.readData(packetReader.getBuffer());
|
||||
public SerializableData decode(BinaryReader reader) {
|
||||
return DataReader.readData(reader);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class ShortData extends DataType<Short> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, Short value) {
|
||||
packetWriter.writeShort(value);
|
||||
public void encode(BinaryWriter writer, Short value) {
|
||||
writer.writeShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short decode(PacketReader packetReader) {
|
||||
return packetReader.readShort();
|
||||
public Short decode(BinaryReader reader) {
|
||||
return reader.readShort();
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class StringData extends DataType<String> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, String value) {
|
||||
packetWriter.writeSizedString(value);
|
||||
public void encode(BinaryWriter writer, String value) {
|
||||
writer.writeSizedString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decode(PacketReader packetReader) {
|
||||
return packetReader.readSizedString();
|
||||
public String decode(BinaryReader reader) {
|
||||
return reader.readSizedString();
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
package net.minestom.server.data.type;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class UuidType extends DataType<UUID> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, UUID value) {
|
||||
packetWriter.writeUuid(value);
|
||||
public void encode(BinaryWriter writer, UUID value) {
|
||||
writer.writeUuid(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID decode(PacketReader packetReader) {
|
||||
return packetReader.readUuid();
|
||||
public UUID decode(BinaryReader reader) {
|
||||
return reader.readUuid();
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class BooleanArrayData extends DataType<boolean[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, boolean[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, boolean[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (boolean val : value) {
|
||||
packetWriter.writeBoolean(val);
|
||||
writer.writeBoolean(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] decode(PacketReader packetReader) {
|
||||
boolean[] array = new boolean[packetReader.readVarInt()];
|
||||
public boolean[] decode(BinaryReader reader) {
|
||||
boolean[] array = new boolean[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readBoolean();
|
||||
array[i] = reader.readBoolean();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class ByteArrayData extends DataType<byte[]> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, byte[] value) {
|
||||
encodeByteArray(packetWriter, value);
|
||||
public void encode(BinaryWriter writer, byte[] value) {
|
||||
encodeByteArray(writer, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decode(PacketReader packetReader) {
|
||||
return decodeByteArray(packetReader);
|
||||
public byte[] decode(BinaryReader reader) {
|
||||
return decodeByteArray(reader);
|
||||
}
|
||||
|
||||
public static void encodeByteArray(PacketWriter packetWriter, byte[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public static void encodeByteArray(BinaryWriter binaryWriter, byte[] value) {
|
||||
binaryWriter.writeVarInt(value.length);
|
||||
for (byte val : value) {
|
||||
packetWriter.writeByte(val);
|
||||
binaryWriter.writeByte(val);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] decodeByteArray(PacketReader packetReader) {
|
||||
byte[] array = new byte[packetReader.readVarInt()];
|
||||
public static byte[] decodeByteArray(BinaryReader binaryReader) {
|
||||
byte[] array = new byte[binaryReader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readByte();
|
||||
array[i] = binaryReader.readByte();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class CharacterArrayData extends DataType<char[]> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, char[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, char[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (char val : value) {
|
||||
packetWriter.writeChar(val);
|
||||
writer.writeChar(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] decode(PacketReader packetReader) {
|
||||
char[] array = new char[packetReader.readVarInt()];
|
||||
public char[] decode(BinaryReader reader) {
|
||||
char[] array = new char[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readChar();
|
||||
array[i] = reader.readChar();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class DoubleArrayData extends DataType<double[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, double[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, double[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (double val : value) {
|
||||
packetWriter.writeDouble(val);
|
||||
writer.writeDouble(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] decode(PacketReader packetReader) {
|
||||
double[] array = new double[packetReader.readVarInt()];
|
||||
public double[] decode(BinaryReader reader) {
|
||||
double[] array = new double[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readDouble();
|
||||
array[i] = reader.readDouble();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class FloatArrayData extends DataType<float[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, float[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, float[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (float val : value) {
|
||||
packetWriter.writeFloat(val);
|
||||
writer.writeFloat(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] decode(PacketReader packetReader) {
|
||||
float[] array = new float[packetReader.readVarInt()];
|
||||
public float[] decode(BinaryReader reader) {
|
||||
float[] array = new float[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readFloat();
|
||||
array[i] = reader.readFloat();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class IntegerArrayData extends DataType<int[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, int[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, int[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (int val : value) {
|
||||
packetWriter.writeInt(val);
|
||||
writer.writeInt(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] decode(PacketReader packetReader) {
|
||||
int[] array = new int[packetReader.readVarInt()];
|
||||
public int[] decode(BinaryReader reader) {
|
||||
int[] array = new int[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readInteger();
|
||||
array[i] = reader.readInteger();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -2,23 +2,23 @@ package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class ItemStackArrayData extends DataType<ItemStack[]> {
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, ItemStack[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, ItemStack[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (ItemStack itemStack : value) {
|
||||
packetWriter.writeItemStack(itemStack);
|
||||
writer.writeItemStack(itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] decode(PacketReader packetReader) {
|
||||
ItemStack[] items = new ItemStack[packetReader.readVarInt()];
|
||||
public ItemStack[] decode(BinaryReader reader) {
|
||||
ItemStack[] items = new ItemStack[reader.readVarInt()];
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
items[i] = packetReader.readSlot();
|
||||
items[i] = reader.readSlot();
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class LongArrayData extends DataType<long[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, long[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, long[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (long val : value) {
|
||||
packetWriter.writeLong(val);
|
||||
writer.writeLong(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] decode(PacketReader packetReader) {
|
||||
long[] array = new long[packetReader.readVarInt()];
|
||||
public long[] decode(BinaryReader reader) {
|
||||
long[] array = new long[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readLong();
|
||||
array[i] = reader.readLong();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class ShortArrayData extends DataType<short[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, short[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, short[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (short val : value) {
|
||||
packetWriter.writeShort(val);
|
||||
writer.writeShort(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public short[] decode(PacketReader packetReader) {
|
||||
short[] array = new short[packetReader.readVarInt()];
|
||||
public short[] decode(BinaryReader reader) {
|
||||
short[] array = new short[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readShort();
|
||||
array[i] = reader.readShort();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
package net.minestom.server.data.type.array;
|
||||
|
||||
import net.minestom.server.data.DataType;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
public class StringArrayData extends DataType<String[]> {
|
||||
|
||||
@Override
|
||||
public void encode(PacketWriter packetWriter, String[] value) {
|
||||
packetWriter.writeVarInt(value.length);
|
||||
public void encode(BinaryWriter writer, String[] value) {
|
||||
writer.writeVarInt(value.length);
|
||||
for (String val : value) {
|
||||
packetWriter.writeSizedString(val);
|
||||
writer.writeSizedString(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] decode(PacketReader packetReader) {
|
||||
String[] array = new String[packetReader.readVarInt()];
|
||||
public String[] decode(BinaryReader reader) {
|
||||
String[] array = new String[reader.readVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = packetReader.readSizedString();
|
||||
array[i] = reader.readSizedString();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.WorldBorder;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.Vector;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.entity.EntityUtils;
|
||||
import net.minestom.server.utils.player.PlayerUtils;
|
||||
@ -1195,7 +1195,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
*
|
||||
* @return The consumer used to write {@link EntityMetaDataPacket} in {@link #getMetadataPacket()}
|
||||
*/
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
fillMetadataIndex(packet, 0);
|
||||
fillMetadataIndex(packet, 1);
|
||||
@ -1209,7 +1209,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
|
||||
/**
|
||||
* Send a {@link EntityMetaDataPacket} containing only the specified index
|
||||
* The index is wrote using {@link #fillMetadataIndex(PacketWriter, int)}
|
||||
* The index is wrote using {@link #fillMetadataIndex(BinaryWriter, int)}
|
||||
*
|
||||
* @param index the metadata index
|
||||
*/
|
||||
@ -1229,7 +1229,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
* @param packet the packet writer
|
||||
* @param index the index to fill/write
|
||||
*/
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
fillStateMetadata(packet);
|
||||
@ -1255,7 +1255,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
}
|
||||
}
|
||||
|
||||
private void fillStateMetadata(PacketWriter packet) {
|
||||
private void fillStateMetadata(BinaryWriter packet) {
|
||||
packet.writeByte((byte) 0);
|
||||
packet.writeByte(METADATA_BYTE);
|
||||
byte index0 = 0;
|
||||
@ -1278,13 +1278,13 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
packet.writeByte(index0);
|
||||
}
|
||||
|
||||
private void fillAirTickMetaData(PacketWriter packet) {
|
||||
private void fillAirTickMetaData(BinaryWriter packet) {
|
||||
packet.writeByte((byte) 1);
|
||||
packet.writeByte(METADATA_VARINT);
|
||||
packet.writeVarInt(air);
|
||||
}
|
||||
|
||||
private void fillCustomNameMetaData(PacketWriter packet) {
|
||||
private void fillCustomNameMetaData(BinaryWriter packet) {
|
||||
boolean hasCustomName = customName != null;
|
||||
|
||||
packet.writeByte((byte) 2);
|
||||
@ -1295,25 +1295,25 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
}
|
||||
}
|
||||
|
||||
private void fillCustomNameVisibleMetaData(PacketWriter packet) {
|
||||
private void fillCustomNameVisibleMetaData(BinaryWriter packet) {
|
||||
packet.writeByte((byte) 3);
|
||||
packet.writeByte(METADATA_BOOLEAN);
|
||||
packet.writeBoolean(customNameVisible);
|
||||
}
|
||||
|
||||
private void fillSilentMetaData(PacketWriter packet) {
|
||||
private void fillSilentMetaData(BinaryWriter packet) {
|
||||
packet.writeByte((byte) 4);
|
||||
packet.writeByte(METADATA_BOOLEAN);
|
||||
packet.writeBoolean(silent);
|
||||
}
|
||||
|
||||
private void fillNoGravityMetaData(PacketWriter packet) {
|
||||
private void fillNoGravityMetaData(BinaryWriter packet) {
|
||||
packet.writeByte((byte) 5);
|
||||
packet.writeByte(METADATA_BOOLEAN);
|
||||
packet.writeBoolean(noGravity);
|
||||
}
|
||||
|
||||
private void fillPoseMetaData(PacketWriter packet) {
|
||||
private void fillPoseMetaData(BinaryWriter packet) {
|
||||
packet.writeByte((byte) 6);
|
||||
packet.writeByte(METADATA_POSE);
|
||||
packet.writeVarInt(pose.ordinal());
|
||||
|
@ -28,16 +28,15 @@ public final class EntityManager {
|
||||
private void waitingPlayersTick() {
|
||||
Player waitingPlayer;
|
||||
while ((waitingPlayer = waitingPlayers.poll()) != null) {
|
||||
final Player playerCache = waitingPlayer;
|
||||
playerCache.init();
|
||||
waitingPlayer.init();
|
||||
|
||||
PlayerLoginEvent loginEvent = new PlayerLoginEvent(playerCache);
|
||||
playerCache.callEvent(PlayerLoginEvent.class, loginEvent);
|
||||
PlayerLoginEvent loginEvent = new PlayerLoginEvent(waitingPlayer);
|
||||
waitingPlayer.callEvent(PlayerLoginEvent.class, loginEvent);
|
||||
final Instance spawningInstance = loginEvent.getSpawningInstance();
|
||||
|
||||
Check.notNull(spawningInstance, "You need to specify a spawning instance in the PlayerLoginEvent");
|
||||
|
||||
playerCache.setInstance(spawningInstance);
|
||||
waitingPlayer.setInstance(spawningInstance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ import net.minestom.server.event.entity.EntityItemMergeEvent;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.StackingRule;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.time.CooldownUtils;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
@ -118,7 +118,7 @@ public class ItemEntity extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 7);
|
||||
@ -126,7 +126,7 @@ public class ItemEntity extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 7) {
|
||||
packet.writeByte((byte) 7);
|
||||
|
@ -10,7 +10,6 @@ import net.minestom.server.event.item.PickupItemEvent;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.inventory.EquipmentHandler;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.play.CollectItemPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityAnimationPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityPropertiesPacket;
|
||||
@ -19,6 +18,7 @@ import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
|
||||
import java.util.Set;
|
||||
@ -35,7 +35,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
// Bounding box used for items' pickup (see LivingEntity#setBoundingBox)
|
||||
protected BoundingBox expandedBoundingBox;
|
||||
|
||||
private float[] attributeValues = new float[Attribute.values().length];
|
||||
private final float[] attributeValues = new float[Attribute.values().length];
|
||||
|
||||
private boolean isHandActive;
|
||||
private boolean offHand;
|
||||
@ -119,7 +119,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 7);
|
||||
@ -129,7 +129,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 7) {
|
||||
packet.writeByte((byte) 7);
|
||||
|
@ -24,13 +24,13 @@ import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.inventory.PlayerInventory;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.login.JoinGamePacket;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.permission.Permission;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.recipe.Recipe;
|
||||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.resourcepack.ResourcePack;
|
||||
@ -43,6 +43,7 @@ import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
@ -102,9 +103,10 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
// CustomBlock break delay
|
||||
private CustomBlock targetCustomBlock;
|
||||
private BlockPosition targetBlockPosition;
|
||||
private long targetBlockTime;
|
||||
private byte targetLastStage;
|
||||
private int blockBreakTime;
|
||||
private long targetBreakDelay; // The last break delay requested
|
||||
private long targetBlockBreakCount; // Number of tick since the last stage change
|
||||
private byte targetStage; // The current stage of the target block, only if multi player breaking is disabled
|
||||
private final Set<Player> targetBreakers = new HashSet<>(1); // Only used if multi player breaking is disabled, contains only this player
|
||||
|
||||
private BelowNameTag belowNameTag;
|
||||
|
||||
@ -159,6 +161,9 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
this.levelType = LevelType.FLAT;
|
||||
refreshPosition(0, 0, 0);
|
||||
|
||||
// Used to cache the breaker for single custom block breaking
|
||||
this.targetBreakers.add(this);
|
||||
|
||||
// FakePlayer init its connection there
|
||||
playerConnectionInit();
|
||||
|
||||
@ -300,17 +305,38 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
|
||||
// Target block stage
|
||||
if (targetCustomBlock != null) {
|
||||
final byte animationCount = 10;
|
||||
final long since = time - targetBlockTime;
|
||||
byte stage = (byte) (since / (blockBreakTime / animationCount));
|
||||
stage = MathUtils.setBetween(stage, (byte) -1, animationCount);
|
||||
if (stage != targetLastStage) {
|
||||
sendBlockBreakAnimation(targetBlockPosition, stage);
|
||||
}
|
||||
this.targetLastStage = stage;
|
||||
if (stage > 9) {
|
||||
instance.breakBlock(this, targetBlockPosition);
|
||||
resetTargetBlock();
|
||||
this.targetBlockBreakCount++;
|
||||
final boolean processStage = targetBlockBreakCount >= targetBreakDelay;
|
||||
if (processStage) {
|
||||
// Should increment the target block stage
|
||||
if (targetCustomBlock.enableMultiPlayerBreaking()) {
|
||||
// Let the custom block object manages the breaking
|
||||
final boolean canContinue = this.targetCustomBlock.processStage(instance, targetBlockPosition, this);
|
||||
if (canContinue) {
|
||||
final Set<Player> breakers = targetCustomBlock.getBreakers(instance, targetBlockPosition);
|
||||
refreshBreakDelay(breakers);
|
||||
} else {
|
||||
resetTargetBlock();
|
||||
}
|
||||
} else {
|
||||
// Let the player object manages the breaking
|
||||
// The custom block doesn't support multi player breaking
|
||||
if (targetStage + 1 >= CustomBlock.MAX_STAGE) {
|
||||
// Break the block
|
||||
instance.breakBlock(this, targetBlockPosition);
|
||||
resetTargetBlock();
|
||||
} else {
|
||||
// Send the new block break animation packet and refresh data
|
||||
|
||||
final Chunk chunk = instance.getChunkAt(targetBlockPosition);
|
||||
final int entityId = targetCustomBlock.getBreakEntityId(this);
|
||||
final BlockBreakAnimationPacket blockBreakAnimationPacket = new BlockBreakAnimationPacket(entityId, targetBlockPosition, targetStage);
|
||||
chunk.sendPacketToViewers(blockBreakAnimationPacket);
|
||||
|
||||
refreshBreakDelay(targetBreakers);
|
||||
this.targetStage++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,7 +605,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 14);
|
||||
@ -588,7 +614,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 14) {
|
||||
packet.writeByte((byte) 14);
|
||||
@ -622,7 +648,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
*/
|
||||
public void sendPluginMessage(String channel, String message) {
|
||||
// Write the data
|
||||
PacketWriter writer = new PacketWriter();
|
||||
BinaryWriter writer = new BinaryWriter();
|
||||
writer.writeSizedString(message);
|
||||
// Retrieve the data
|
||||
final byte[] data = writer.toByteArray();
|
||||
@ -630,24 +656,6 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
sendPluginMessage(channel, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link BlockBreakAnimationPacket} packet to the player and his viewers
|
||||
* Setting {@code destroyStage} to -1 resets the break animation
|
||||
*
|
||||
* @param blockPosition the position of the block
|
||||
* @param destroyStage the destroy stage
|
||||
* @throws IllegalArgumentException if {@code destroyStage} is not between -1 and 10
|
||||
*/
|
||||
public void sendBlockBreakAnimation(BlockPosition blockPosition, byte destroyStage) {
|
||||
Check.argCondition(!MathUtils.isBetween(destroyStage, -1, 10),
|
||||
"The destroy stage has to be between -1 and 10");
|
||||
BlockBreakAnimationPacket breakAnimationPacket = new BlockBreakAnimationPacket();
|
||||
breakAnimationPacket.entityId = getEntityId() + 1;
|
||||
breakAnimationPacket.blockPosition = blockPosition;
|
||||
breakAnimationPacket.destroyStage = destroyStage;
|
||||
sendPacketToViewersAndSelf(breakAnimationPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
sendMessage(ColoredText.of(message));
|
||||
@ -1690,7 +1698,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
* Change the player ability "Creative Mode"
|
||||
* <a href="https://wiki.vg/Protocol#Player_Abilities_.28clientbound.29">see</a>
|
||||
* <p>
|
||||
* WARNING: this has nothing to do with {@link CustomBlock#getBreakDelay(Player, BlockPosition)}
|
||||
* WARNING: this has nothing to do with {@link CustomBlock#getBreakDelay(Player, BlockPosition, byte, Set)}
|
||||
*
|
||||
* @param instantBreak true to allow instant break
|
||||
*/
|
||||
@ -1858,8 +1866,8 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
if (isFood && !allowFood)
|
||||
return null;
|
||||
|
||||
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(updatedItem,
|
||||
isOffhand ? Hand.OFF : Hand.MAIN);
|
||||
final Hand hand = isOffhand ? Hand.OFF : Hand.MAIN;
|
||||
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(this, hand, updatedItem);
|
||||
callEvent(ItemUpdateStateEvent.class, itemUpdateStateEvent);
|
||||
|
||||
return itemUpdateStateEvent;
|
||||
@ -1870,13 +1878,33 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
*
|
||||
* @param targetCustomBlock the custom block to dig
|
||||
* @param targetBlockPosition the custom block position
|
||||
* @param breakTime the time it will take to break the block in milliseconds
|
||||
* @param breakers the breakers of the block, can be null if {@code this} is the only breaker
|
||||
*/
|
||||
public void setTargetBlock(CustomBlock targetCustomBlock, BlockPosition targetBlockPosition, int breakTime) {
|
||||
public void setTargetBlock(CustomBlock targetCustomBlock, BlockPosition targetBlockPosition, Set<Player> breakers) {
|
||||
this.targetCustomBlock = targetCustomBlock;
|
||||
this.targetBlockPosition = targetBlockPosition;
|
||||
this.targetBlockTime = targetBlockPosition == null ? 0 : System.currentTimeMillis();
|
||||
this.blockBreakTime = breakTime;
|
||||
|
||||
refreshBreakDelay(breakers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the break delay for the next block break stage
|
||||
*
|
||||
* @param breakers the list of breakers, can be null if {@code this} is the only breaker
|
||||
*/
|
||||
private void refreshBreakDelay(Set<Player> breakers) {
|
||||
breakers = breakers == null ? targetBreakers : breakers;
|
||||
|
||||
// Refresh the last tick update
|
||||
this.targetBlockBreakCount = 0;
|
||||
|
||||
// Get if multi player breaking is enabled
|
||||
final boolean multiPlayerBreaking = targetCustomBlock.enableMultiPlayerBreaking();
|
||||
// Get the stage from the custom block object if it is, otherwise use the local fieldl
|
||||
final byte stage = multiPlayerBreaking ? targetCustomBlock.getBreakStage(instance, targetBlockPosition) : targetStage;
|
||||
// Retrieve the break delay for the current stage
|
||||
final int breakDelay = targetCustomBlock.getBreakDelay(this, targetBlockPosition, stage, breakers);
|
||||
this.targetBreakDelay = breakDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1884,17 +1912,19 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
* If the currently mined block (or if there isn't any) is not a CustomBlock, nothing append
|
||||
*/
|
||||
public void resetTargetBlock() {
|
||||
if (targetBlockPosition != null) {
|
||||
sendBlockBreakAnimation(targetBlockPosition, (byte) -1); // Clear the break animation
|
||||
if (targetCustomBlock != null) {
|
||||
targetCustomBlock.stopDigging(instance, targetBlockPosition, this);
|
||||
this.targetCustomBlock = null;
|
||||
this.targetBlockPosition = null;
|
||||
this.targetBlockTime = 0;
|
||||
this.targetBreakDelay = 0;
|
||||
this.targetBlockBreakCount = 0;
|
||||
this.targetStage = 0;
|
||||
|
||||
// Remove effect
|
||||
RemoveEntityEffectPacket removeEntityEffectPacket = new RemoveEntityEffectPacket();
|
||||
removeEntityEffectPacket.entityId = getEntityId();
|
||||
removeEntityEffectPacket.effectId = 4;
|
||||
getPlayerConnection().sendPacket(removeEntityEffectPacket);
|
||||
removeEntityEffectPacket.effect = PotionType.AWKWARD;
|
||||
playerConnection.sendPacket(removeEntityEffectPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1927,7 +1957,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the packet to add the player from tab-list
|
||||
* Get the packet to add the player from the tab-list
|
||||
*
|
||||
* @return a {@link PlayerInfoPacket} to add the player
|
||||
*/
|
||||
@ -1950,9 +1980,9 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the packet to remove the player from tab-list
|
||||
* Get the packet to remove the player from the tab-list
|
||||
*
|
||||
* @return a {@link PlayerInfoPacket} to add the player
|
||||
* @return a {@link PlayerInfoPacket} to remove the player
|
||||
*/
|
||||
protected PlayerInfoPacket getRemovePlayerToList() {
|
||||
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
|
||||
@ -1968,7 +1998,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
* Send all the related packet to have the player sent to another with related data
|
||||
* (create player, spawn position, velocity, metadata, equipments, passengers, team)
|
||||
* <p>
|
||||
* WARNING: this does not sync the player, please use {@link #addViewer(Player)}
|
||||
* WARNING: this alone does not sync the player, please use {@link #addViewer(Player)}
|
||||
*
|
||||
* @param connection the connection to show the player to
|
||||
*/
|
||||
|
@ -17,7 +17,7 @@ public class Hologram implements Viewable {
|
||||
|
||||
private static final float OFFSET_Y = -0.9875f;
|
||||
|
||||
private HologramEntity entity;
|
||||
private final HologramEntity entity;
|
||||
|
||||
private Position position;
|
||||
private ColoredText text;
|
||||
@ -124,7 +124,7 @@ public class Hologram implements Viewable {
|
||||
}
|
||||
|
||||
|
||||
private class HologramEntity extends EntityArmorStand {
|
||||
private static class HologramEntity extends EntityArmorStand {
|
||||
|
||||
public HologramEntity(Position spawnPosition) {
|
||||
super(spawnPosition);
|
||||
|
@ -1,11 +1,36 @@
|
||||
package net.minestom.server.entity.pathfinding;
|
||||
|
||||
import com.extollit.gaming.ai.path.model.IBlockDescription;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
public class PFBlockDescription implements IBlockDescription {
|
||||
|
||||
private Block block;
|
||||
private static final Short2ObjectMap<PFBlockDescription> BLOCK_DESCRITION_MAP = new Short2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the {@link PFBlockDescription} linked to the block state id
|
||||
* <p>
|
||||
* Cache the result if it is not already
|
||||
*
|
||||
* @param blockStateId the block state id
|
||||
* @return the {@link PFBlockDescription} linked to {@code blockStateId}
|
||||
*/
|
||||
public static PFBlockDescription getBlockDescription(short blockStateId) {
|
||||
if (!BLOCK_DESCRITION_MAP.containsKey(blockStateId)) {
|
||||
synchronized (BLOCK_DESCRITION_MAP) {
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
final PFBlockDescription blockDescription = new PFBlockDescription(block);
|
||||
BLOCK_DESCRITION_MAP.put(blockStateId, blockDescription);
|
||||
return blockDescription;
|
||||
}
|
||||
}
|
||||
|
||||
return BLOCK_DESCRITION_MAP.get(blockStateId);
|
||||
}
|
||||
|
||||
private final Block block;
|
||||
|
||||
public PFBlockDescription(Block block) {
|
||||
this.block = block;
|
||||
|
@ -2,11 +2,36 @@ package net.minestom.server.entity.pathfinding;
|
||||
|
||||
import com.extollit.gaming.ai.path.model.IBlockObject;
|
||||
import com.extollit.linalg.immutable.AxisAlignedBBox;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
public class PFBlockObject implements IBlockObject {
|
||||
|
||||
private Block block;
|
||||
private static final Short2ObjectMap<PFBlockObject> BLOCK_OBJECT_MAP = new Short2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the {@link PFBlockObject} linked to the block state id
|
||||
* <p>
|
||||
* Cache the result if it is not already
|
||||
*
|
||||
* @param blockStateId the block state id
|
||||
* @return the {@link PFBlockObject} linked to {@code blockStateId}
|
||||
*/
|
||||
public static PFBlockObject getBlockObject(short blockStateId) {
|
||||
if (!BLOCK_OBJECT_MAP.containsKey(blockStateId)) {
|
||||
synchronized (BLOCK_OBJECT_MAP) {
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
final PFBlockObject blockObject = new PFBlockObject(block);
|
||||
BLOCK_OBJECT_MAP.put(blockStateId, blockObject);
|
||||
return blockObject;
|
||||
}
|
||||
}
|
||||
|
||||
return BLOCK_OBJECT_MAP.get(blockStateId);
|
||||
}
|
||||
|
||||
private final Block block;
|
||||
|
||||
public PFBlockObject(Block block) {
|
||||
this.block = block;
|
||||
|
@ -5,7 +5,6 @@ import com.extollit.gaming.ai.path.model.IBlockDescription;
|
||||
import com.extollit.gaming.ai.path.model.IColumnarSpace;
|
||||
import com.extollit.gaming.ai.path.model.IInstanceSpace;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
public class PFColumnarSpace implements IColumnarSpace {
|
||||
|
||||
@ -22,8 +21,7 @@ public class PFColumnarSpace implements IColumnarSpace {
|
||||
@Override
|
||||
public IBlockDescription blockAt(int x, int y, int z) {
|
||||
final short blockStateId = chunk.getBlockStateId(x, y, z);
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
return new PFBlockDescription(block);
|
||||
return PFBlockDescription.getBlockDescription(blockStateId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5,7 +5,6 @@ import com.extollit.gaming.ai.path.model.IColumnarSpace;
|
||||
import com.extollit.gaming.ai.path.model.IInstanceSpace;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -22,8 +21,7 @@ public class PFInstanceSpace implements IInstanceSpace {
|
||||
@Override
|
||||
public IBlockObject blockObjectAt(int x, int y, int z) {
|
||||
final short blockStateId = instance.getBlockStateId(x, y, z);
|
||||
final Block block = Block.fromStateId(blockStateId);
|
||||
return new PFBlockObject(block);
|
||||
return PFBlockObject.getBlockObject(blockStateId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -33,14 +31,11 @@ public class PFInstanceSpace implements IInstanceSpace {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PFColumnarSpace columnarSpace =
|
||||
chunkSpaceMap.computeIfAbsent(chunk, c -> {
|
||||
final PFColumnarSpace cs = new PFColumnarSpace(this, c);
|
||||
c.setColumnarSpace(cs);
|
||||
return cs;
|
||||
});
|
||||
|
||||
return columnarSpace;
|
||||
return chunkSpaceMap.computeIfAbsent(chunk, c -> {
|
||||
final PFColumnarSpace cs = new PFColumnarSpace(this, c);
|
||||
c.setColumnarSpace(cs);
|
||||
return cs;
|
||||
});
|
||||
}
|
||||
|
||||
public Instance getInstance() {
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.ambient;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Animal;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntityBat extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -26,7 +26,7 @@ public class EntityBat extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.animal;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Animal;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntityMooshroom extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 16);
|
||||
@ -27,7 +27,7 @@ public class EntityMooshroom extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 16) {
|
||||
packet.writeByte((byte) 16);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.animal;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Animal;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntityPig extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 16);
|
||||
@ -26,7 +26,7 @@ public class EntityPig extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 16) {
|
||||
packet.writeByte((byte) 16);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.animal;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Animal;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntityPolarBear extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 16);
|
||||
@ -26,7 +26,7 @@ public class EntityPolarBear extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 16) {
|
||||
packet.writeByte((byte) 16);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.animal;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Animal;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntityRabbit extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 16);
|
||||
@ -26,7 +26,7 @@ public class EntityRabbit extends EntityCreature implements Animal {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 16) {
|
||||
packet.writeByte((byte) 16);
|
||||
|
@ -6,10 +6,10 @@ import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.item.ArmorEquipEvent;
|
||||
import net.minestom.server.inventory.EquipmentHandler;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.play.EntityEquipmentPacket;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.Vector;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.item.ItemStackUtils;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@ -73,7 +73,7 @@ public class EntityArmorStand extends ObjectEntity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 14);
|
||||
@ -87,7 +87,7 @@ public class EntityArmorStand extends ObjectEntity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 14) {
|
||||
packet.writeByte((byte) 14);
|
||||
|
@ -3,9 +3,9 @@ package net.minestom.server.entity.type.decoration;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.ObjectEntity;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.Rotation;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.item.ItemStackUtils;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@ -27,7 +27,7 @@ public class EntityItemFrame extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 7);
|
||||
@ -36,7 +36,7 @@ public class EntityItemFrame extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 7) {
|
||||
packet.writeByte((byte) 7);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -16,7 +16,7 @@ public class EntityBlaze extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -24,7 +24,7 @@ public class EntityBlaze extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -20,7 +20,7 @@ public class EntityCreeper extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -28,7 +28,7 @@ public class EntityCreeper extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntityGhast extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -27,7 +27,7 @@ public class EntityGhast extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -4,8 +4,8 @@ import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -20,7 +20,7 @@ public class EntityGuardian extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -29,7 +29,7 @@ public class EntityGuardian extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntityPhantom extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -26,7 +26,7 @@ public class EntityPhantom extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntitySlime extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -26,7 +26,7 @@ public class EntitySlime extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntitySpider extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -27,7 +27,7 @@ public class EntitySpider extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntityWitch extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 16);
|
||||
@ -27,7 +27,7 @@ public class EntityWitch extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 16) {
|
||||
packet.writeByte((byte) 16);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntityZombie extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -28,7 +28,7 @@ public class EntityZombie extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.monster;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Monster;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntityZombifiedPiglin extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -28,7 +28,7 @@ public class EntityZombifiedPiglin extends EntityCreature implements Monster {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -2,15 +2,15 @@ package net.minestom.server.entity.type.other;
|
||||
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.ObjectEntity;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.particle.Particle;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EntityAreaEffectCloud extends ObjectEntity {
|
||||
|
||||
public Consumer<PacketWriter> particleDataConsumer;
|
||||
public Consumer<BinaryWriter> particleDataConsumer;
|
||||
private float radius;
|
||||
private int color;
|
||||
private boolean ignoreRadius;
|
||||
@ -27,7 +27,7 @@ public class EntityAreaEffectCloud extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 7);
|
||||
@ -38,7 +38,7 @@ public class EntityAreaEffectCloud extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 7) {
|
||||
packet.writeByte((byte) 7);
|
||||
@ -102,7 +102,7 @@ public class EntityAreaEffectCloud extends ObjectEntity {
|
||||
sendMetadataIndex(10);
|
||||
}
|
||||
|
||||
public Consumer<PacketWriter> getParticleDataConsumer() {
|
||||
public Consumer<BinaryWriter> getParticleDataConsumer() {
|
||||
return particleDataConsumer;
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ public class EntityAreaEffectCloud extends ObjectEntity {
|
||||
* @param particleDataConsumer the particle data consumer
|
||||
* @see @see <a href="https://wiki.vg/Data_types#Particle">Particle data</a>
|
||||
*/
|
||||
public void setParticleDataConsumer(Consumer<PacketWriter> particleDataConsumer) {
|
||||
public void setParticleDataConsumer(Consumer<BinaryWriter> particleDataConsumer) {
|
||||
this.particleDataConsumer = particleDataConsumer;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.other;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Constructable;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntityIronGolem extends EntityCreature implements Constructable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -26,7 +26,7 @@ public class EntityIronGolem extends EntityCreature implements Constructable {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.other;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.type.Constructable;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class EntitySnowman extends EntityCreature implements Constructable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 15);
|
||||
@ -26,7 +26,7 @@ public class EntitySnowman extends EntityCreature implements Constructable {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 15) {
|
||||
packet.writeByte((byte) 15);
|
||||
|
@ -5,8 +5,8 @@ import net.minestom.server.entity.ObjectEntity;
|
||||
import net.minestom.server.entity.type.Projectile;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -19,7 +19,7 @@ public class EntityEyeOfEnder extends ObjectEntity implements Projectile {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 7);
|
||||
@ -27,7 +27,7 @@ public class EntityEyeOfEnder extends ObjectEntity implements Projectile {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 7) {
|
||||
packet.writeByte((byte) 7);
|
||||
|
@ -4,8 +4,8 @@ import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.ObjectEntity;
|
||||
import net.minestom.server.entity.type.Projectile;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -20,7 +20,7 @@ public class EntityPotion extends ObjectEntity implements Projectile {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 7);
|
||||
@ -28,7 +28,7 @@ public class EntityPotion extends ObjectEntity implements Projectile {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 7) {
|
||||
packet.writeByte((byte) 7);
|
||||
|
@ -3,8 +3,8 @@ package net.minestom.server.entity.type.vehicle;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.ObjectEntity;
|
||||
import net.minestom.server.entity.type.Vehicle;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@ -27,7 +27,7 @@ public class EntityBoat extends ObjectEntity implements Vehicle {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<PacketWriter> getMetadataConsumer() {
|
||||
public Consumer<BinaryWriter> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
fillMetadataIndex(packet, 10);
|
||||
@ -39,7 +39,7 @@ public class EntityBoat extends ObjectEntity implements Vehicle {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillMetadataIndex(PacketWriter packet, int index) {
|
||||
protected void fillMetadataIndex(BinaryWriter packet, int index) {
|
||||
super.fillMetadataIndex(packet, index);
|
||||
if (index == 10) {
|
||||
packet.writeByte((byte) 10);
|
||||
|
@ -23,6 +23,14 @@ public class PlayerVehicleInformation {
|
||||
return unmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh internal data
|
||||
*
|
||||
* @param sideways the new sideways value
|
||||
* @param forward the new forward value
|
||||
* @param jump the new jump value
|
||||
* @param unmount the new unmount value
|
||||
*/
|
||||
public void refresh(float sideways, float forward, boolean jump, boolean unmount) {
|
||||
this.sideways = sideways;
|
||||
this.forward = forward;
|
||||
|
@ -43,7 +43,7 @@ public interface EventHandler {
|
||||
* @param <E> the event type
|
||||
*/
|
||||
default <E extends Event> void callEvent(Class<E> eventClass, E event) {
|
||||
List<EventCallback> eventCallbacks = getEventCallbacks(eventClass);
|
||||
final List<EventCallback> eventCallbacks = getEventCallbacks(eventClass);
|
||||
for (EventCallback<E> eventCallback : eventCallbacks) {
|
||||
eventCallback.run(event);
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import net.minestom.server.instance.Instance;
|
||||
*/
|
||||
public class InstanceChunkLoadEvent extends Event {
|
||||
|
||||
private Instance instance;
|
||||
private int chunkX, chunkZ;
|
||||
private final Instance instance;
|
||||
private final int chunkX, chunkZ;
|
||||
|
||||
public InstanceChunkLoadEvent(Instance instance, int chunkX, int chunkZ) {
|
||||
this.instance = instance;
|
||||
|
@ -8,8 +8,8 @@ import net.minestom.server.instance.Instance;
|
||||
*/
|
||||
public class InstanceChunkUnloadEvent extends Event {
|
||||
|
||||
private Instance instance;
|
||||
private int chunkX, chunkZ;
|
||||
private final Instance instance;
|
||||
private final int chunkX, chunkZ;
|
||||
|
||||
public InstanceChunkUnloadEvent(Instance instance, int chunkX, int chunkZ) {
|
||||
this.instance = instance;
|
||||
|
@ -8,14 +8,15 @@ import net.minestom.server.item.ItemStack;
|
||||
|
||||
public class InventoryClickEvent extends Event {
|
||||
|
||||
private Player player;
|
||||
private Inventory inventory;
|
||||
private int slot;
|
||||
private ClickType clickType;
|
||||
private ItemStack clickedItem;
|
||||
private ItemStack cursorItem;
|
||||
private final Player player;
|
||||
private final Inventory inventory;
|
||||
private final int slot;
|
||||
private final ClickType clickType;
|
||||
private final ItemStack clickedItem;
|
||||
private final ItemStack cursorItem;
|
||||
|
||||
public InventoryClickEvent(Player player, Inventory inventory, int slot, ClickType clickType, ItemStack clicked, ItemStack cursor) {
|
||||
this.player = player;
|
||||
this.inventory = inventory;
|
||||
this.slot = slot;
|
||||
this.clickType = clickType;
|
||||
|
@ -6,8 +6,8 @@ import net.minestom.server.inventory.Inventory;
|
||||
|
||||
public class InventoryCloseEvent extends Event {
|
||||
|
||||
private Player player;
|
||||
private Inventory inventory;
|
||||
private final Player player;
|
||||
private final Inventory inventory;
|
||||
private Inventory newInventory;
|
||||
|
||||
public InventoryCloseEvent(Player player, Inventory inventory) {
|
||||
|
@ -6,7 +6,7 @@ import net.minestom.server.inventory.Inventory;
|
||||
|
||||
public class InventoryOpenEvent extends CancellableEvent {
|
||||
|
||||
private Player player;
|
||||
private final Player player;
|
||||
private Inventory inventory;
|
||||
|
||||
public InventoryOpenEvent(Player player, Inventory inventory) {
|
||||
|
@ -9,10 +9,10 @@ import net.minestom.server.utils.item.ItemStackUtils;
|
||||
|
||||
public class InventoryPreClickEvent extends CancellableEvent {
|
||||
|
||||
private Player player;
|
||||
private Inventory inventory;
|
||||
private int slot;
|
||||
private ClickType clickType;
|
||||
private final Player player;
|
||||
private final Inventory inventory;
|
||||
private final int slot;
|
||||
private final ClickType clickType;
|
||||
private ItemStack clickedItem;
|
||||
private ItemStack cursorItem;
|
||||
|
||||
|
@ -6,23 +6,29 @@ import net.minestom.server.item.ItemStack;
|
||||
|
||||
public class ItemUpdateStateEvent extends Event {
|
||||
|
||||
private ItemStack itemStack;
|
||||
private Player.Hand hand;
|
||||
private Player player;
|
||||
private final Player.Hand hand;
|
||||
private final ItemStack itemStack;
|
||||
private boolean handAnimation;
|
||||
|
||||
public ItemUpdateStateEvent(ItemStack itemStack, Player.Hand hand) {
|
||||
this.itemStack = itemStack;
|
||||
public ItemUpdateStateEvent(Player player, Player.Hand hand, ItemStack itemStack) {
|
||||
this.player = player;
|
||||
this.hand = hand;
|
||||
this.itemStack = itemStack;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Player.Hand getHand() {
|
||||
return hand;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public void setHandAnimation(boolean handAnimation) {
|
||||
this.handAnimation = handAnimation;
|
||||
}
|
||||
|
41
src/main/java/net/minestom/server/extensions/Extension.java
Normal file
41
src/main/java/net/minestom/server/extensions/Extension.java
Normal file
@ -0,0 +1,41 @@
|
||||
package net.minestom.server.extensions;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public abstract class Extension {
|
||||
private JsonObject description;
|
||||
private Logger logger;
|
||||
|
||||
protected Extension() {
|
||||
|
||||
}
|
||||
|
||||
public void preInitialize() {
|
||||
|
||||
}
|
||||
|
||||
public abstract void initialize();
|
||||
|
||||
public void postInitialize() {
|
||||
|
||||
}
|
||||
|
||||
public void preTerminate() {
|
||||
|
||||
}
|
||||
|
||||
public abstract void terminate();
|
||||
|
||||
public void postTerminate() {
|
||||
|
||||
}
|
||||
|
||||
public JsonObject getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
protected Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
package net.minestom.server.extensions;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class ExtensionManager {
|
||||
private final Map<URL, URLClassLoader> extensionLoaders = new HashMap<>();
|
||||
private final Map<String, Extension> extensions = new HashMap<>();
|
||||
private final File extensionFolder = new File("extensions");
|
||||
|
||||
public ExtensionManager() {
|
||||
}
|
||||
|
||||
public void loadExtensionJARs() {
|
||||
if (!extensionFolder.exists()) {
|
||||
if (!extensionFolder.mkdirs()) {
|
||||
log.error("Could not find or create the extension folder, extensions will not be loaded!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (File file : extensionFolder.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
if (!file.getName().endsWith(".jar")) {
|
||||
continue;
|
||||
}
|
||||
URLClassLoader loader;
|
||||
try {
|
||||
URL url = file.toURI().toURL();
|
||||
loader = loadJar(url);
|
||||
extensionLoaders.put(url, loader);
|
||||
} catch (MalformedURLException e) {
|
||||
log.error(String.format("Failed to get URL for file %s.", file.getPath()));
|
||||
return;
|
||||
}
|
||||
InputStream extensionInputStream = loader.getResourceAsStream("extension.json");
|
||||
if (extensionInputStream == null) {
|
||||
log.error(String.format("Failed to find extension.json in the file '%s'.", file.getPath()));
|
||||
return;
|
||||
}
|
||||
JsonObject extensionDescription = JsonParser.parseReader(new InputStreamReader(extensionInputStream)).getAsJsonObject();
|
||||
|
||||
String mainClass = extensionDescription.get("entrypoint").getAsString();
|
||||
String extensionName = extensionDescription.get("name").getAsString();
|
||||
|
||||
if (extensions.containsKey(extensionName.toLowerCase())) {
|
||||
log.error(String.format("An extension called '%s' has already been registered.", extensionName));
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> jarClass;
|
||||
try {
|
||||
jarClass = Class.forName(mainClass, true, loader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error(String.format("Could not find main class '%s' in extension '%s'.", mainClass, extensionName), e);
|
||||
return;
|
||||
}
|
||||
|
||||
Class<? extends Extension> extensionClass;
|
||||
try {
|
||||
extensionClass = jarClass.asSubclass(Extension.class);
|
||||
} catch (ClassCastException e) {
|
||||
log.error(String.format("Main class '%s' in '%s' does not extend the 'extension superclass'.", mainClass, extensionName), e);
|
||||
return;
|
||||
}
|
||||
|
||||
Constructor<? extends Extension> constructor;
|
||||
try {
|
||||
constructor = extensionClass.getDeclaredConstructor();
|
||||
// Let's just make it accessible, plugin creators don't have to make this public.
|
||||
constructor.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
log.error(String.format("Main class '%s' in '%s' does not define a no-args constructor.", mainClass, extensionName), e);
|
||||
return;
|
||||
}
|
||||
Extension extension = null;
|
||||
try {
|
||||
// Is annotated with NotNull
|
||||
extension = constructor.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
log.error(String.format("Main class '%s' in '%s' cannot be an abstract class.", mainClass, extensionName), e);
|
||||
return;
|
||||
} catch (IllegalAccessException ignored) {
|
||||
// We made it accessible, should not occur
|
||||
} catch (InvocationTargetException e) {
|
||||
log.error(
|
||||
String.format(
|
||||
"While instantiating the main class '%s' in '%s' an exception was thrown.", mainClass, extensionName
|
||||
), e.getTargetException()
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Set description
|
||||
try {
|
||||
Field descriptionField = extensionClass.getSuperclass().getDeclaredField("description");
|
||||
descriptionField.setAccessible(true);
|
||||
descriptionField.set(extension, extensionDescription);
|
||||
} catch (IllegalAccessException e) {
|
||||
// We made it accessible, should not occur
|
||||
} catch (NoSuchFieldException e) {
|
||||
log.error(String.format("Main class '%s' in '%s' has no description field.", mainClass, extensionName), e);
|
||||
return;
|
||||
}
|
||||
// Set Logger
|
||||
try {
|
||||
Field descriptionField = extensionClass.getSuperclass().getDeclaredField("logger");
|
||||
descriptionField.setAccessible(true);
|
||||
descriptionField.set(extension, LoggerFactory.getLogger(extensionClass));
|
||||
} catch (IllegalAccessException e) {
|
||||
// We made it accessible, should not occur
|
||||
} catch (NoSuchFieldException e) {
|
||||
log.error(String.format("Main class '%s' in '%s' has no logger field.", mainClass, extensionName), e);
|
||||
}
|
||||
|
||||
extensions.put(extensionName.toLowerCase(), extension);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a URL into the classpath.
|
||||
*
|
||||
* @param url {@link URL} (usually a JAR) that should be loaded.
|
||||
*/
|
||||
@NotNull
|
||||
public URLClassLoader loadJar(@NotNull URL url) {
|
||||
return URLClassLoader.newInstance(new URL[]{url}, ExtensionManager.class.getClassLoader());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public File getExtensionFolder() {
|
||||
return extensionFolder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Extension> getExtensions() {
|
||||
return new ArrayList<>(extensions.values());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Extension getExtension(@NotNull String name) {
|
||||
return extensions.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<URL, URLClassLoader> getExtensionLoaders() {
|
||||
return new HashMap<>(extensionLoaders);
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
||||
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.player.PlayerUtils;
|
||||
import net.minestom.server.utils.time.CooldownUtils;
|
||||
@ -25,10 +26,8 @@ import net.minestom.server.utils.time.UpdateOption;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
// TODO light data & API
|
||||
@ -41,15 +40,13 @@ public abstract class Chunk implements Viewable {
|
||||
public static final int CHUNK_SIZE_Z = 16;
|
||||
public static final int CHUNK_SECTION_SIZE = 16;
|
||||
|
||||
public static final int CHUNK_SECTION_COUNT = CHUNK_SIZE_Y / CHUNK_SECTION_SIZE;
|
||||
|
||||
public static final int BIOME_COUNT = 1024; // 4x4x4 blocks
|
||||
|
||||
protected Biome[] biomes;
|
||||
protected int chunkX, chunkZ;
|
||||
|
||||
// blocks id based on coord, see Chunk#getBlockIndex
|
||||
//public short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
//protected short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
|
||||
// Used to get all blocks with data (no null)
|
||||
// Key is still chunk coord
|
||||
protected Int2ObjectMap<Data> blocksData = new Int2ObjectOpenHashMap<>(16 * 16); // Start with the size of a single row
|
||||
@ -59,7 +56,7 @@ public abstract class Chunk implements Viewable {
|
||||
// (block index)/(last update in ms)
|
||||
protected Int2LongMap updatableBlocksLastUpdate = new Int2LongOpenHashMap();
|
||||
|
||||
protected AtomicBoolean packetUpdated = new AtomicBoolean(false);
|
||||
protected volatile boolean packetUpdated;
|
||||
|
||||
// Block entities
|
||||
protected Set<Integer> blockEntities = new CopyOnWriteArraySet<>();
|
||||
@ -114,8 +111,10 @@ public abstract class Chunk implements Viewable {
|
||||
public abstract CustomBlock getCustomBlock(int x, int y, int z);
|
||||
|
||||
protected CustomBlock getCustomBlock(int index) {
|
||||
final int[] pos = ChunkUtils.indexToChunkPosition(index);
|
||||
return getCustomBlock(pos[0], pos[1], pos[2]);
|
||||
final int x = ChunkUtils.blockIndexToChunkPositionX(index);
|
||||
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
|
||||
final int z = ChunkUtils.blockIndexToChunkPositionZ(index);
|
||||
return getCustomBlock(x, y, z);
|
||||
}
|
||||
|
||||
protected abstract void refreshBlockValue(int x, int y, int z, short blockStateId, short customId);
|
||||
@ -142,7 +141,7 @@ public abstract class Chunk implements Viewable {
|
||||
return;
|
||||
|
||||
// Block all chunk operation during the update
|
||||
IntIterator iterator = new IntOpenHashSet(updatableBlocks).iterator();
|
||||
final IntIterator iterator = new IntOpenHashSet(updatableBlocks).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final int index = iterator.nextInt();
|
||||
final CustomBlock customBlock = getCustomBlock(index);
|
||||
@ -156,12 +155,7 @@ public abstract class Chunk implements Viewable {
|
||||
|
||||
this.updatableBlocksLastUpdate.put(index, time); // Refresh last update time
|
||||
|
||||
final int[] blockPos = ChunkUtils.indexToPosition(index, chunkX, chunkZ);
|
||||
final int x = blockPos[0];
|
||||
final int y = blockPos[1];
|
||||
final int z = blockPos[2];
|
||||
|
||||
final BlockPosition blockPosition = new BlockPosition(x, y, z);
|
||||
final BlockPosition blockPosition = ChunkUtils.getBlockPosition(index, chunkX, chunkZ);
|
||||
final Data data = getData(index);
|
||||
customBlock.update(instance, blockPosition, data);
|
||||
}
|
||||
@ -184,7 +178,7 @@ public abstract class Chunk implements Viewable {
|
||||
* <p>
|
||||
* Use {@link #retrieveDataBuffer(Consumer)} to be sure to get the updated version
|
||||
*
|
||||
* @return the current cached data packet, can be null or outdated
|
||||
* @return the last cached data packet, can be null or outdated
|
||||
*/
|
||||
public ByteBuf getFullDataPacket() {
|
||||
return fullDataPacket;
|
||||
@ -192,7 +186,7 @@ public abstract class Chunk implements Viewable {
|
||||
|
||||
public void setFullDataPacket(ByteBuf fullDataPacket) {
|
||||
this.fullDataPacket = fullDataPacket;
|
||||
this.packetUpdated.set(true);
|
||||
this.packetUpdated = true;
|
||||
}
|
||||
|
||||
protected boolean isBlockEntity(short blockStateId) {
|
||||
@ -214,13 +208,13 @@ public abstract class Chunk implements Viewable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the updated data packet
|
||||
* Retrieve (and save if needed) the updated data packet
|
||||
*
|
||||
* @param consumer the consumer called once the packet is sure to be up-to-date
|
||||
*/
|
||||
public void retrieveDataBuffer(Consumer<ByteBuf> consumer) {
|
||||
final ByteBuf data = getFullDataPacket();
|
||||
if (data == null || !packetUpdated.get()) {
|
||||
if (data == null || !packetUpdated) {
|
||||
PacketWriterUtils.writeCallbackPacket(getFreshFullDataPacket(), packet -> {
|
||||
setFullDataPacket(packet);
|
||||
consumer.accept(packet);
|
||||
@ -234,9 +228,8 @@ public abstract class Chunk implements Viewable {
|
||||
* Serialize the chunk
|
||||
*
|
||||
* @return the serialized chunk
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract byte[] getSerializedData() throws IOException;
|
||||
protected abstract byte[] getSerializedData();
|
||||
|
||||
/**
|
||||
* Get a {@link ChunkDataPacket} which should contain the full chunk
|
||||
@ -279,7 +272,13 @@ public abstract class Chunk implements Viewable {
|
||||
return "Chunk[" + chunkX + ":" + chunkZ + "]";
|
||||
}
|
||||
|
||||
// UNSAFE
|
||||
/**
|
||||
* Send the chunk to {@code player} and add it to the player viewing chunks collection
|
||||
* and send a {@link PlayerChunkLoadEvent}
|
||||
*
|
||||
* @param player the viewer to add
|
||||
* @return true if the player has just been added to the viewer collection
|
||||
*/
|
||||
@Override
|
||||
public boolean addViewer(Player player) {
|
||||
final boolean result = this.viewers.add(player);
|
||||
@ -294,7 +293,13 @@ public abstract class Chunk implements Viewable {
|
||||
return result;
|
||||
}
|
||||
|
||||
// UNSAFE
|
||||
/**
|
||||
* Remove the chunk to the player viewing chunks collection
|
||||
* and send a {@link PlayerChunkUnloadEvent}
|
||||
*
|
||||
* @param player the viewer to remove
|
||||
* @return true if the player has just been removed to the viewer collection
|
||||
*/
|
||||
@Override
|
||||
public boolean removeViewer(Player player) {
|
||||
final boolean result = this.viewers.remove(player);
|
||||
@ -325,9 +330,7 @@ public abstract class Chunk implements Viewable {
|
||||
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
|
||||
retrieveDataBuffer(buf -> {
|
||||
playerConnection.sendPacket(buf, true);
|
||||
});
|
||||
retrieveDataBuffer(buf -> playerConnection.sendPacket(buf, true));
|
||||
|
||||
// TODO do not hardcode
|
||||
if (MinecraftServer.isFixLighting()) {
|
||||
@ -372,15 +375,13 @@ public abstract class Chunk implements Viewable {
|
||||
public void sendChunkUpdate() {
|
||||
final Set<Player> chunkViewers = getViewers();
|
||||
if (!chunkViewers.isEmpty()) {
|
||||
retrieveDataBuffer(buf -> {
|
||||
chunkViewers.forEach(player -> {
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
if (!PlayerUtils.isNettyClient(playerConnection))
|
||||
return;
|
||||
retrieveDataBuffer(buf -> chunkViewers.forEach(player -> {
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
if (!PlayerUtils.isNettyClient(playerConnection))
|
||||
return;
|
||||
|
||||
playerConnection.sendPacket(buf, true);
|
||||
});
|
||||
});
|
||||
playerConnection.sendPacket(buf, true);
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
@ -394,14 +395,22 @@ public abstract class Chunk implements Viewable {
|
||||
public void sendChunkSectionUpdate(int section, Player player) {
|
||||
if (!PlayerUtils.isNettyClient(player))
|
||||
return;
|
||||
Check.argCondition(!MathUtils.isBetween(section, 0, CHUNK_SECTION_COUNT),
|
||||
"The chunk section " + section + " does not exist");
|
||||
|
||||
PacketWriterUtils.writeAndSend(player, getChunkSectionUpdatePacket(section));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ChunkDataPacket} to update a single chunk section
|
||||
*
|
||||
* @param section the chunk section to update
|
||||
* @return the {@link ChunkDataPacket} to update a single chunk sectionl
|
||||
*/
|
||||
protected ChunkDataPacket getChunkSectionUpdatePacket(int section) {
|
||||
ChunkDataPacket chunkDataPacket = getFreshPartialDataPacket();
|
||||
chunkDataPacket.fullChunk = false;
|
||||
int[] sections = new int[16];
|
||||
int[] sections = new int[CHUNK_SECTION_COUNT];
|
||||
sections[section] = 1;
|
||||
chunkDataPacket.sections = sections;
|
||||
return chunkDataPacket;
|
||||
|
@ -5,22 +5,20 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.data.SerializableData;
|
||||
import net.minestom.server.entity.pathfinding.PFBlockDescription;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.instance.block.UpdateConsumer;
|
||||
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class DynamicChunk extends Chunk {
|
||||
|
||||
public short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
private short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
// blocks id based on coordinate, see Chunk#getBlockIndex
|
||||
private final short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
private final short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
|
||||
public DynamicChunk(Biome[] biomes, int chunkX, int chunkZ) {
|
||||
super(biomes, chunkX, chunkZ);
|
||||
@ -40,9 +38,18 @@ public class DynamicChunk extends Chunk {
|
||||
|
||||
@Override
|
||||
protected void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer) {
|
||||
|
||||
{
|
||||
// Update pathfinder
|
||||
if (columnarSpace != null) {
|
||||
final ColumnarOcclusionFieldList columnarOcclusionFieldList = columnarSpace.occlusionFields();
|
||||
final PFBlockDescription blockDescription = PFBlockDescription.getBlockDescription(blockStateId);
|
||||
columnarOcclusionFieldList.onBlockChanged(x, y, z, blockDescription, 0);
|
||||
}
|
||||
}
|
||||
|
||||
final int index = getBlockIndex(x, y, z);
|
||||
if (blockStateId != 0
|
||||
|| (blockStateId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
|
||||
if (blockStateId != 0 || customId != 0 && updateConsumer != null) { // Allow custom air block for update purpose, refused if no update consumer has been found
|
||||
this.blocksStateId[index] = blockStateId;
|
||||
this.customBlocksId[index] = customId;
|
||||
} else {
|
||||
@ -57,7 +64,7 @@ public class DynamicChunk extends Chunk {
|
||||
|
||||
this.blockEntities.remove(index);
|
||||
|
||||
this.packetUpdated.set(false);
|
||||
this.packetUpdated = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -84,13 +91,7 @@ public class DynamicChunk extends Chunk {
|
||||
this.blockEntities.remove(index);
|
||||
}
|
||||
|
||||
this.packetUpdated.set(false);
|
||||
|
||||
if (columnarSpace != null) {
|
||||
final ColumnarOcclusionFieldList columnarOcclusionFieldList = columnarSpace.occlusionFields();
|
||||
final PFBlockDescription blockDescription = new PFBlockDescription(Block.fromStateId(blockStateId));
|
||||
columnarOcclusionFieldList.onBlockChanged(x, y, z, blockDescription, 0);
|
||||
}
|
||||
this.packetUpdated = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,8 +100,7 @@ public class DynamicChunk extends Chunk {
|
||||
if (!MathUtils.isBetween(index, 0, blocksStateId.length)) {
|
||||
return 0; // TODO: custom invalid block
|
||||
}
|
||||
final short id = blocksStateId[index];
|
||||
return id;
|
||||
return blocksStateId[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -109,8 +109,7 @@ public class DynamicChunk extends Chunk {
|
||||
if (!MathUtils.isBetween(index, 0, blocksStateId.length)) {
|
||||
return 0; // TODO: custom invalid block
|
||||
}
|
||||
final short id = customBlocksId[index];
|
||||
return id;
|
||||
return customBlocksId[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -145,12 +144,13 @@ public class DynamicChunk extends Chunk {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getSerializedData() throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(output);
|
||||
protected byte[] getSerializedData() {
|
||||
BinaryWriter binaryWriter = new BinaryWriter();
|
||||
|
||||
// Write the biomes id
|
||||
for (int i = 0; i < BIOME_COUNT; i++) {
|
||||
dos.writeByte(biomes[i].getId());
|
||||
final byte id = (byte) biomes[i].getId();
|
||||
binaryWriter.writeByte(id);
|
||||
}
|
||||
|
||||
for (byte x = 0; x < CHUNK_SIZE_X; x++) {
|
||||
@ -161,34 +161,32 @@ public class DynamicChunk extends Chunk {
|
||||
final short blockStateId = blocksStateId[index];
|
||||
final short customBlockId = customBlocksId[index];
|
||||
|
||||
// No block at the position
|
||||
if (blockStateId == 0 && customBlockId == 0)
|
||||
continue;
|
||||
|
||||
final Data data = blocksData.get(index);
|
||||
|
||||
// Chunk coordinates
|
||||
dos.writeInt(x);
|
||||
dos.writeInt(y);
|
||||
dos.writeInt(z);
|
||||
binaryWriter.writeByte(x);
|
||||
binaryWriter.writeShort(y);
|
||||
binaryWriter.writeByte(z);
|
||||
|
||||
// Id
|
||||
dos.writeShort(blockStateId);
|
||||
dos.writeShort(customBlockId);
|
||||
// Block ids
|
||||
binaryWriter.writeShort(blockStateId);
|
||||
binaryWriter.writeShort(customBlockId);
|
||||
|
||||
// Data
|
||||
final boolean hasData = (data != null && (data instanceof SerializableData));
|
||||
dos.writeBoolean(hasData);
|
||||
final Data data = blocksData.get(index);
|
||||
final boolean hasData = data instanceof SerializableData;
|
||||
binaryWriter.writeBoolean(hasData);
|
||||
if (hasData) {
|
||||
final byte[] d = ((SerializableData) data).getSerializedData();
|
||||
dos.writeInt(d.length);
|
||||
dos.write(d);
|
||||
final byte[] serializedData = ((SerializableData) data).getSerializedData();
|
||||
binaryWriter.writeBytes(serializedData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final byte[] result = output.toByteArray();
|
||||
return result;
|
||||
return binaryWriter.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,9 +48,9 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
|
||||
private boolean registered;
|
||||
|
||||
private DimensionType dimensionType;
|
||||
private final DimensionType dimensionType;
|
||||
|
||||
private WorldBorder worldBorder;
|
||||
private final WorldBorder worldBorder;
|
||||
|
||||
// Tick since the creation of the instance
|
||||
private long worldAge;
|
||||
@ -61,24 +61,24 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
private UpdateOption timeUpdate = new UpdateOption(1, TimeUnit.TICK);
|
||||
private long lastTimeUpdate;
|
||||
|
||||
private Map<Class<? extends Event>, List<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
|
||||
private final Map<Class<? extends Event>, List<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
|
||||
|
||||
// Entities present in this instance
|
||||
protected Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
protected Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
||||
protected Set<ObjectEntity> objectEntities = new CopyOnWriteArraySet<>();
|
||||
protected Set<ExperienceOrb> experienceOrbs = new CopyOnWriteArraySet<>();
|
||||
protected final Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
protected final Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
||||
protected final Set<ObjectEntity> objectEntities = new CopyOnWriteArraySet<>();
|
||||
protected final Set<ExperienceOrb> experienceOrbs = new CopyOnWriteArraySet<>();
|
||||
// Entities per chunk
|
||||
protected Map<Long, Set<Entity>> chunkEntities = new ConcurrentHashMap<>();
|
||||
protected final Map<Long, Set<Entity>> chunkEntities = new ConcurrentHashMap<>();
|
||||
protected UUID uniqueId;
|
||||
|
||||
protected List<Consumer<Instance>> nextTick = Collections.synchronizedList(new ArrayList<>());
|
||||
protected final List<Consumer<Instance>> nextTick = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
private Data data;
|
||||
private ExplosionSupplier explosionSupplier;
|
||||
|
||||
// Pathfinder
|
||||
private PFInstanceSpace instanceSpace = new PFInstanceSpace(this);
|
||||
private final PFInstanceSpace instanceSpace = new PFInstanceSpace(this);
|
||||
|
||||
public Instance(UUID uniqueId, DimensionType dimensionType) {
|
||||
this.uniqueId = uniqueId;
|
||||
@ -754,13 +754,13 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
*/
|
||||
public void removeEntity(Entity entity) {
|
||||
final Instance entityInstance = entity.getInstance();
|
||||
if (entityInstance == null || entityInstance != this)
|
||||
if (entityInstance != this)
|
||||
return;
|
||||
|
||||
RemoveEntityFromInstanceEvent event = new RemoveEntityFromInstanceEvent(this, entity);
|
||||
callCancellableEvent(RemoveEntityFromInstanceEvent.class, event, () -> {
|
||||
// Remove this entity from players viewable list and send delete entities packet
|
||||
entity.getViewers().forEach(p -> entity.removeViewer(p));
|
||||
entity.getViewers().forEach(entity::removeViewer);
|
||||
|
||||
// Remove the entity from cache
|
||||
final Chunk chunk = getChunkAt(entity.getPosition());
|
||||
@ -832,8 +832,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
}
|
||||
|
||||
private Set<Entity> getEntitiesInChunk(long index) {
|
||||
final Set<Entity> entities = chunkEntities.computeIfAbsent(index, i -> new CopyOnWriteArraySet<>());
|
||||
return entities;
|
||||
return chunkEntities.computeIfAbsent(index, i -> new CopyOnWriteArraySet<>());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -864,7 +863,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
// time
|
||||
this.worldAge++;
|
||||
|
||||
this.time += 1 * timeRate;
|
||||
this.time += timeRate;
|
||||
|
||||
if (timeUpdate != null && !CooldownUtils.hasCooldown(time, lastTimeUpdate, timeUpdate)) {
|
||||
PacketWriterUtils.writeAndSend(getPlayers(), getTimePacket());
|
||||
|
@ -54,8 +54,8 @@ public class InstanceContainer extends Instance {
|
||||
|
||||
private ChunkGenerator chunkGenerator;
|
||||
// WARNING: need to be synchronized properly
|
||||
private Long2ObjectMap<Chunk> chunks = new Long2ObjectOpenHashMap();
|
||||
private Set<Chunk> scheduledChunksToRemove = new HashSet<>();
|
||||
private final Long2ObjectMap<Chunk> chunks = new Long2ObjectOpenHashMap<>();
|
||||
private final Set<Chunk> scheduledChunksToRemove = new HashSet<>();
|
||||
|
||||
private ReadWriteLock changingBlockLock = new ReentrantReadWriteLock();
|
||||
private Map<BlockPosition, Block> currentlyChangingBlocks = new HashMap<>();
|
||||
@ -116,8 +116,17 @@ public class InstanceContainer extends Instance {
|
||||
setAlreadyChanged(blockPosition, blockStateId);
|
||||
final int index = ChunkUtils.getBlockIndex(x, y, z);
|
||||
|
||||
// Call the destroy listener if previous block was a custom block
|
||||
callBlockDestroy(chunk, index, blockPosition);
|
||||
final CustomBlock previousBlock = chunk.getCustomBlock(index);
|
||||
if (previousBlock != null) {
|
||||
// Previous block was a custom block
|
||||
|
||||
// Call the destroy listener
|
||||
callBlockDestroy(chunk, index, previousBlock, blockPosition);
|
||||
|
||||
// Remove digging information for the previous custom block
|
||||
previousBlock.removeDiggingInformation(this, blockPosition);
|
||||
}
|
||||
|
||||
// Change id based on neighbors
|
||||
blockStateId = executeBlockPlacementRule(blockStateId, blockPosition);
|
||||
|
||||
@ -170,13 +179,10 @@ public class InstanceContainer extends Instance {
|
||||
}
|
||||
}
|
||||
|
||||
private void callBlockDestroy(Chunk chunk, int index, BlockPosition blockPosition) {
|
||||
final CustomBlock previousBlock = chunk.getCustomBlock(index);
|
||||
if (previousBlock != null) {
|
||||
final Data previousData = chunk.getData(index);
|
||||
previousBlock.onDestroy(this, blockPosition, previousData);
|
||||
chunk.UNSAFE_removeCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
}
|
||||
private void callBlockDestroy(Chunk chunk, int index, CustomBlock previousBlock, BlockPosition blockPosition) {
|
||||
final Data previousData = chunk.getData(index);
|
||||
previousBlock.onDestroy(this, blockPosition, previousData);
|
||||
chunk.UNSAFE_removeCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
}
|
||||
|
||||
private void callBlockPlace(Chunk chunk, int index, BlockPosition blockPosition) {
|
||||
@ -351,8 +357,9 @@ public class InstanceContainer extends Instance {
|
||||
Check.notNull(getStorageFolder(), "You cannot save the instance if no StorageFolder has been defined");
|
||||
|
||||
this.storageFolder.set(UUID_KEY, getUniqueId(), UUID.class);
|
||||
Data data = getData();
|
||||
final Data data = getData();
|
||||
if (data != null) {
|
||||
// Save the instance data
|
||||
Check.stateCondition(!(data instanceof SerializableData),
|
||||
"Instance#getData needs to be a SerializableData in order to be saved");
|
||||
this.storageFolder.set(DATA_KEY, (SerializableData) getData(), SerializableData.class);
|
||||
|
@ -5,13 +5,12 @@ import net.minestom.server.storage.StorageFolder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class MinestomBasicChunkLoader implements IChunkLoader {
|
||||
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(MinestomBasicChunkLoader.class);
|
||||
private StorageFolder storageFolder;
|
||||
private final StorageFolder storageFolder;
|
||||
|
||||
public MinestomBasicChunkLoader(StorageFolder storageFolder) {
|
||||
this.storageFolder = storageFolder;
|
||||
@ -24,21 +23,22 @@ public class MinestomBasicChunkLoader implements IChunkLoader {
|
||||
LOGGER.warn("No folder to save chunk!");
|
||||
return;
|
||||
}
|
||||
|
||||
final int chunkX = chunk.getChunkX();
|
||||
final int chunkZ = chunk.getChunkZ();
|
||||
|
||||
try {
|
||||
final String key = getChunkKey(chunkX, chunkZ);
|
||||
final byte[] data = chunk.getSerializedData();
|
||||
if (data == null)
|
||||
return;
|
||||
storageFolder.set(key, data);
|
||||
|
||||
final String key = getChunkKey(chunkX, chunkZ);
|
||||
final byte[] data = chunk.getSerializedData();
|
||||
if (data == null) {
|
||||
if (callback != null)
|
||||
callback.run();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
storageFolder.set(key, data);
|
||||
|
||||
if (callback != null)
|
||||
callback.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,7 +19,7 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class SharedInstance extends Instance {
|
||||
|
||||
private InstanceContainer instanceContainer;
|
||||
private final InstanceContainer instanceContainer;
|
||||
|
||||
public SharedInstance(UUID uniqueId, InstanceContainer instanceContainer) {
|
||||
super(uniqueId, instanceContainer.getDimensionType());
|
||||
|
@ -70,8 +70,10 @@ public class StaticChunk extends Chunk {
|
||||
fullDataPacket.chunkZ = chunkZ;
|
||||
short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z];
|
||||
for (int i = 0; i < blocksStateId.length; i++) {
|
||||
final int[] pos = ChunkUtils.indexToPosition(i, 0, 0);
|
||||
blocksStateId[i] = blockProvider.getBlockStateId(pos[0], pos[1], pos[2]);
|
||||
final int x = ChunkUtils.blockIndexToChunkPositionX(i);
|
||||
final int y = ChunkUtils.blockIndexToChunkPositionY(i);
|
||||
final int z = ChunkUtils.blockIndexToChunkPositionZ(i);
|
||||
blocksStateId[i] = blockProvider.getBlockStateId(x, y, z);
|
||||
}
|
||||
fullDataPacket.blocksStateId = blocksStateId;
|
||||
fullDataPacket.customBlocksId = new short[0];
|
||||
|
@ -11,7 +11,7 @@ import net.minestom.server.utils.Position;
|
||||
*/
|
||||
public class WorldBorder {
|
||||
|
||||
private Instance instance;
|
||||
private final Instance instance;
|
||||
|
||||
private float centerX, centerZ;
|
||||
|
||||
|
@ -87,7 +87,7 @@ public class BlockBatch implements InstanceBatch {
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockData {
|
||||
private static class BlockData {
|
||||
|
||||
private int x, y, z;
|
||||
private boolean hasCustomBlock;
|
||||
|
@ -18,8 +18,8 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class ChunkBatch implements InstanceBatch {
|
||||
|
||||
private InstanceContainer instance;
|
||||
private Chunk chunk;
|
||||
private final InstanceContainer instance;
|
||||
private final Chunk chunk;
|
||||
|
||||
// Give it the max capacity by default (avoid resizing)
|
||||
private List<BlockData> dataList =
|
||||
@ -109,7 +109,7 @@ public class ChunkBatch implements InstanceBatch {
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockData {
|
||||
private static class BlockData {
|
||||
|
||||
private int x, y, z;
|
||||
private boolean hasCustomBlock;
|
||||
|
@ -1,16 +1,28 @@
|
||||
package net.minestom.server.instance.block;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ByteMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.gamedata.loottables.LootTable;
|
||||
import net.minestom.server.gamedata.loottables.LootTableManager;
|
||||
import net.minestom.server.instance.BlockModifier;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.network.packet.server.play.BlockBreakAnimationPacket;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represent the handler of a custom block type.
|
||||
* <p>
|
||||
@ -20,10 +32,17 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
*/
|
||||
public abstract class CustomBlock {
|
||||
|
||||
public static final byte MAX_STAGE = 10;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* - option to set the global as "global breaking" meaning that multiple players mining the same block will break it faster (accumulation)
|
||||
* Instance -> break data
|
||||
* Used to store block break stage data when {@link #enableMultiPlayerBreaking()} is enabled
|
||||
*/
|
||||
private final Map<Instance, InstanceBreakData> instanceBreakDataMap = new HashMap<>();
|
||||
|
||||
public int getBreakEntityId(Player firstBreaker) {
|
||||
return firstBreaker.getEntityId() + 1;
|
||||
}
|
||||
|
||||
private final short blockStateId;
|
||||
private final String identifier;
|
||||
@ -106,17 +125,45 @@ public abstract class CustomBlock {
|
||||
public abstract short getCustomBlockId();
|
||||
|
||||
/**
|
||||
* Called at digging start to check for custom breaking time
|
||||
* Can be set to < 0 to be cancelled, in this case vanilla time will be used
|
||||
* Called when the player requests the next stage break delay
|
||||
*
|
||||
* @param player the player who is trying to break the block
|
||||
* @param position the block position
|
||||
* @return the time in ms to break it
|
||||
* @param stage the current break stage of the block (0-10)
|
||||
* @param breakers the list containing all the players currently digging this block
|
||||
* @return the time in tick to pass to the next state, 0 to instant break it.
|
||||
* @see #enableCustomBreakDelay() to enable/disable it
|
||||
*/
|
||||
public abstract int getBreakDelay(Player player, BlockPosition position);
|
||||
public int getBreakDelay(Player player, BlockPosition position, byte stage, Set<Player> breakers) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if {@link #getUpdateOption()} is not null, false otherwise
|
||||
* Used to enable the custom break delay from {@link #getBreakDelay(Player, BlockPosition, byte, Set)}
|
||||
* Disabling it would result in having vanilla time
|
||||
*
|
||||
* @return true to enable custom break delay
|
||||
*/
|
||||
public boolean enableCustomBreakDelay() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if this block breaking time can be reduced by having multiple players
|
||||
* digging it
|
||||
* <p>
|
||||
* WARNING: this should be constant, do not change this value halfway
|
||||
*
|
||||
* @return true to enable the multi-player breaking feature
|
||||
*/
|
||||
public boolean enableMultiPlayerBreaking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if this {@link CustomBlock} requires any tick update
|
||||
*
|
||||
* @return true if {@link #getUpdateOption()} is not null and the value is positive
|
||||
*/
|
||||
public boolean hasUpdate() {
|
||||
final UpdateOption updateOption = getUpdateOption();
|
||||
@ -239,4 +286,189 @@ public abstract class CustomBlock {
|
||||
public LootTable getLootTable(LootTableManager tableManager) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// BLOCK BREAK METHODS
|
||||
|
||||
/**
|
||||
* Called when a player start digging this custom block,
|
||||
* process all necessary data if {@link #enableMultiPlayerBreaking()} is enabled
|
||||
*
|
||||
* @param instance the instance of the block
|
||||
* @param blockPosition the position of the block
|
||||
* @param player the player who started digging
|
||||
*/
|
||||
public void startDigging(Instance instance, BlockPosition blockPosition, Player player) {
|
||||
// Stay null if multi player breaking is disabled
|
||||
Set<Player> breakers = null;
|
||||
|
||||
if (enableMultiPlayerBreaking()) {
|
||||
// Multi player breaking enabled, get the breakers and cache some values
|
||||
InstanceBreakData instanceBreakData = instanceBreakDataMap.computeIfAbsent(instance, i -> new InstanceBreakData());
|
||||
|
||||
Map<BlockPosition, Set<Player>> breakersMap = instanceBreakData.breakersMap;
|
||||
breakers = breakersMap.computeIfAbsent(blockPosition, pos -> new HashSet<>(1));
|
||||
breakers.add(player);
|
||||
|
||||
Object2ByteMap<BlockPosition> breakStageMap = instanceBreakData.breakStageMap;
|
||||
// Set the block stage to 0, use the previous one if any
|
||||
if (!breakStageMap.containsKey(blockPosition)) {
|
||||
breakStageMap.put(blockPosition, (byte) 0);
|
||||
}
|
||||
|
||||
Object2IntMap<BlockPosition> breakIdMap = instanceBreakData.breakIdMap;
|
||||
// Set the entity id used for the packet, otherwise use the previous one
|
||||
if (!breakIdMap.containsKey(blockPosition)) {
|
||||
breakIdMap.put(blockPosition, getBreakEntityId(player));
|
||||
}
|
||||
}
|
||||
|
||||
// Set the player target block
|
||||
player.setTargetBlock(this, blockPosition, breakers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player stop digging a block,
|
||||
* does remove the block break animation if he was the only breaker
|
||||
*
|
||||
* @param instance the instance of the block
|
||||
* @param blockPosition the position of the block
|
||||
* @param player the player who stopped digging
|
||||
*/
|
||||
public void stopDigging(Instance instance, BlockPosition blockPosition, Player player) {
|
||||
if (enableMultiPlayerBreaking()) {
|
||||
// Remove cache data
|
||||
if (instanceBreakDataMap.containsKey(instance)) {
|
||||
InstanceBreakData instanceBreakData = instanceBreakDataMap.get(instance);
|
||||
|
||||
Set<Player> breakers = instanceBreakData.breakersMap.get(blockPosition);
|
||||
if (breakers != null) {
|
||||
breakers.remove(player);
|
||||
if (breakers.isEmpty()) {
|
||||
// No remaining breakers
|
||||
|
||||
// Get the entity id assigned to the block break
|
||||
final int entityId = instanceBreakData.breakIdMap.getInt(blockPosition);
|
||||
|
||||
final Chunk chunk = instance.getChunkAt(blockPosition);
|
||||
chunk.sendPacketToViewers(new BlockBreakAnimationPacket(entityId, blockPosition, (byte) -1));
|
||||
|
||||
// Clear cache
|
||||
removeDiggingInformation(instance, blockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// Stop the breaking animation for the specific player id
|
||||
final Chunk chunk = instance.getChunkAt(blockPosition);
|
||||
final int entityId = getBreakEntityId(player);
|
||||
chunk.sendPacketToViewers(new BlockBreakAnimationPacket(entityId, blockPosition, (byte) -1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process one stage on the block, break it if it excess {@link #MAX_STAGE},
|
||||
* only if {@link #enableMultiPlayerBreaking()} is enabled
|
||||
*
|
||||
* @param instance the instance of the block
|
||||
* @param blockPosition the position of the block
|
||||
* @param player the player who processed one stage on the block
|
||||
* @return true if the block can continue being digged
|
||||
* @throws IllegalStateException if {@link #enableMultiPlayerBreaking()} is disabled
|
||||
*/
|
||||
public synchronized boolean processStage(Instance instance, BlockPosition blockPosition, Player player) {
|
||||
Check.stateCondition(!enableMultiPlayerBreaking(),
|
||||
"CustomBlock#processState requires having the multi player breaking feature enabled");
|
||||
|
||||
if (instanceBreakDataMap.containsKey(instance)) {
|
||||
InstanceBreakData instanceBreakData = instanceBreakDataMap.get(instance);
|
||||
Object2ByteMap<BlockPosition> breakStageMap = instanceBreakData.breakStageMap;
|
||||
byte stage = breakStageMap.getByte(blockPosition);
|
||||
if (stage + 1 >= MAX_STAGE) {
|
||||
instance.breakBlock(player, blockPosition);
|
||||
return false;
|
||||
} else {
|
||||
|
||||
// Get the entity id assigned to the block break
|
||||
final int entityId = instanceBreakData.breakIdMap.getInt(blockPosition);
|
||||
|
||||
// Send the block break animation
|
||||
final Chunk chunk = instance.getChunkAt(blockPosition);
|
||||
chunk.sendPacketToViewers(new BlockBreakAnimationPacket(entityId, blockPosition, stage));
|
||||
|
||||
// Refresh the stage
|
||||
breakStageMap.put(blockPosition, ++stage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeDiggingInformation(Instance instance, BlockPosition blockPosition) {
|
||||
if (!enableMultiPlayerBreaking()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (instanceBreakDataMap.containsKey(instance)) {
|
||||
InstanceBreakData instanceBreakData = instanceBreakDataMap.get(instance);
|
||||
// Remove the block position from all maps
|
||||
instanceBreakData.clear(blockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the breakers of a block, only if {@link #enableMultiPlayerBreaking()} is enabled
|
||||
*
|
||||
* @param instance the instance of the block
|
||||
* @param blockPosition the position of the block
|
||||
* @return the {@link Set} of breakers of a block
|
||||
* @throws IllegalStateException if {@link #enableMultiPlayerBreaking()} is disabled
|
||||
*/
|
||||
public Set<Player> getBreakers(Instance instance, BlockPosition blockPosition) {
|
||||
Check.stateCondition(!enableMultiPlayerBreaking(),
|
||||
"CustomBlock#getBreakers requires having the multi player breaking feature enabled");
|
||||
|
||||
if (instanceBreakDataMap.containsKey(instance)) {
|
||||
InstanceBreakData instanceBreakData = instanceBreakDataMap.get(instance);
|
||||
return instanceBreakData.breakersMap.get(blockPosition);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block break stage at a position, only work if {@link #enableMultiPlayerBreaking()} is enabled
|
||||
*
|
||||
* @param instance the instance of the custom block
|
||||
* @param blockPosition the position of the custom block
|
||||
* @return the break stage at the position. Can also be 0 when nonexistent
|
||||
*/
|
||||
public byte getBreakStage(Instance instance, BlockPosition blockPosition) {
|
||||
Check.stateCondition(!enableMultiPlayerBreaking(),
|
||||
"CustomBlock#getBreakStage requires having the multi player breaking feature enabled");
|
||||
|
||||
if (!instanceBreakDataMap.containsKey(instance))
|
||||
return 0;
|
||||
final InstanceBreakData instanceBreakData = instanceBreakDataMap.get(instance);
|
||||
return instanceBreakData.breakStageMap.getByte(blockPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class used to store block break stage
|
||||
* Only used if multi player breaking is enabled
|
||||
*/
|
||||
private class InstanceBreakData {
|
||||
// Contains all the breakers of a block
|
||||
private final Map<BlockPosition, Set<Player>> breakersMap = new HashMap<>();
|
||||
// Contains the current break stage of a block
|
||||
private final Object2ByteMap<BlockPosition> breakStageMap = new Object2ByteOpenHashMap<>();
|
||||
// Contains the entity id used by the block break packet
|
||||
private final Object2IntMap<BlockPosition> breakIdMap = new Object2IntOpenHashMap<>();
|
||||
|
||||
private void clear(BlockPosition blockPosition) {
|
||||
this.breakersMap.remove(blockPosition);
|
||||
this.breakStageMap.removeByte(blockPosition);
|
||||
this.breakIdMap.removeInt(blockPosition);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -27,25 +27,26 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class Inventory implements InventoryModifier, InventoryClickHandler, Viewable {
|
||||
|
||||
private static volatile byte lastInventoryId;
|
||||
private static AtomicInteger lastInventoryId = new AtomicInteger();
|
||||
|
||||
private byte id;
|
||||
private final byte id;
|
||||
private final InventoryType inventoryType;
|
||||
private String title;
|
||||
|
||||
private int size;
|
||||
private final int size;
|
||||
|
||||
private int offset;
|
||||
private final int offset;
|
||||
|
||||
private ItemStack[] itemStacks;
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
|
||||
private final ItemStack[] itemStacks;
|
||||
private final Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private final ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
|
||||
|
||||
private List<InventoryCondition> inventoryConditions = new CopyOnWriteArrayList<>();
|
||||
private InventoryClickProcessor clickProcessor = new InventoryClickProcessor();
|
||||
private final List<InventoryCondition> inventoryConditions = new CopyOnWriteArrayList<>();
|
||||
private final InventoryClickProcessor clickProcessor = new InventoryClickProcessor();
|
||||
|
||||
// Cached windows packet
|
||||
|
||||
@ -64,8 +65,8 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
||||
}
|
||||
|
||||
private static byte generateId() {
|
||||
byte newInventoryId = ++lastInventoryId;
|
||||
if (newInventoryId < 0)
|
||||
byte newInventoryId = (byte) lastInventoryId.incrementAndGet();
|
||||
if (newInventoryId == Byte.MAX_VALUE)
|
||||
newInventoryId = 1;
|
||||
return newInventoryId;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public enum InventoryProperty {
|
||||
BREWING_STAND_FUEL_TIME((short) 1);
|
||||
|
||||
|
||||
private short property;
|
||||
private final short property;
|
||||
|
||||
InventoryProperty(short property) {
|
||||
this.property = property;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user