mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 03:27:56 +01:00
General optimization
This commit is contained in:
parent
d833963414
commit
5c0056e183
@ -7,6 +7,7 @@ import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.InstanceManager;
|
||||
import fr.themode.minestom.instance.block.BlockManager;
|
||||
import fr.themode.minestom.instance.demo.StoneBlock;
|
||||
import fr.themode.minestom.instance.demo.UpdatableBlockDemo;
|
||||
import fr.themode.minestom.listener.PacketListenerManager;
|
||||
import fr.themode.minestom.net.ConnectionManager;
|
||||
import fr.themode.minestom.net.ConnectionUtils;
|
||||
@ -15,6 +16,7 @@ import fr.themode.minestom.net.packet.PacketReader;
|
||||
import fr.themode.minestom.net.packet.client.status.LegacyServerListPingPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.KeepAlivePacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
import fr.themode.minestom.scoreboard.TeamManager;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class Main {
|
||||
@ -23,6 +25,7 @@ public class Main {
|
||||
public static final int THREAD_COUNT_PACKET_WRITER = 2;
|
||||
public static final int THREAD_COUNT_IO = 2;
|
||||
public static final int THREAD_COUNT_BLOCK_BATCH = 2;
|
||||
public static final int THREAD_COUNT_BLOCK_UPDATE = 2;
|
||||
public static final int THREAD_COUNT_ENTITIES = 2;
|
||||
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 2;
|
||||
|
||||
@ -44,6 +47,7 @@ public class Main {
|
||||
private static BlockManager blockManager;
|
||||
private static EntityManager entityManager;
|
||||
private static DataManager dataManager;
|
||||
private static TeamManager teamManager;
|
||||
|
||||
public static void main(String[] args) {
|
||||
connectionManager = new ConnectionManager();
|
||||
@ -54,8 +58,10 @@ public class Main {
|
||||
blockManager = new BlockManager();
|
||||
entityManager = new EntityManager();
|
||||
dataManager = new DataManager();
|
||||
teamManager = new TeamManager();
|
||||
|
||||
blockManager.registerBlock(StoneBlock::new);
|
||||
blockManager.registerBlock(new StoneBlock());
|
||||
blockManager.registerBlock(new UpdatableBlockDemo());
|
||||
|
||||
server = new Server(136434);
|
||||
|
||||
@ -115,7 +121,7 @@ public class Main {
|
||||
entityManager.update();
|
||||
|
||||
// Blocks update
|
||||
blockManager.update();
|
||||
instanceManager.updateBlocks();
|
||||
|
||||
// TODO miscellaneous update (scoreboard)
|
||||
|
||||
@ -158,6 +164,10 @@ public class Main {
|
||||
return dataManager;
|
||||
}
|
||||
|
||||
public static TeamManager getTeamManager() {
|
||||
return teamManager;
|
||||
}
|
||||
|
||||
public static ConnectionManager getConnectionManager() {
|
||||
return connectionManager;
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ public enum ChatColor {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public byte getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Chat.COLOR_CHAR + String.valueOf(HexUtils.byteToHex(id));
|
||||
|
@ -5,8 +5,8 @@ import com.google.gson.JsonObject;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.bossbar.BossBar;
|
||||
import fr.themode.minestom.chat.Chat;
|
||||
import fr.themode.minestom.chat.ChatColor;
|
||||
import fr.themode.minestom.collision.BoundingBox;
|
||||
import fr.themode.minestom.data.Data;
|
||||
import fr.themode.minestom.entity.property.Attribute;
|
||||
import fr.themode.minestom.event.*;
|
||||
import fr.themode.minestom.instance.Chunk;
|
||||
@ -21,12 +21,14 @@ import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.*;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
import fr.themode.minestom.scoreboard.BelowNameScoreboard;
|
||||
import fr.themode.minestom.scoreboard.Team;
|
||||
import fr.themode.minestom.scoreboard.TeamManager;
|
||||
import fr.themode.minestom.utils.*;
|
||||
import fr.themode.minestom.world.Dimension;
|
||||
import fr.themode.minestom.world.LevelType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
@ -85,6 +87,8 @@ public class Player extends LivingEntity {
|
||||
private byte targetLastStage;
|
||||
|
||||
private Set<BossBar> bossBars = new CopyOnWriteArraySet<>();
|
||||
private Team team;
|
||||
private BelowNameScoreboard belowNameScoreboard;
|
||||
|
||||
// Vehicle
|
||||
private float sideways;
|
||||
@ -136,16 +140,6 @@ public class Player extends LivingEntity {
|
||||
}
|
||||
});
|
||||
|
||||
setEventCallback(PlayerStartDiggingEvent.class, event -> {
|
||||
BlockPosition blockPosition = event.getBlockPosition();
|
||||
Data data = getInstance().getBlockData(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
if (data == null) {
|
||||
sendMessage("DATA IS NULL");
|
||||
return;
|
||||
}
|
||||
sendMessage("BLOCK DATA: " + data.get("value"));
|
||||
});
|
||||
|
||||
setEventCallback(PickupItemEvent.class, event -> {
|
||||
event.setCancelled(!getInventory().addItemStack(event.getItemStack())); // Cancel event if player does not have enough inventory space
|
||||
});
|
||||
@ -178,17 +172,12 @@ public class Player extends LivingEntity {
|
||||
getInventory().addItemStack(new ItemStack(1, (byte) 75));
|
||||
//getInventory().addItemStack(new ItemStack(1, (byte) 100));
|
||||
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
|
||||
teamsPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
||||
teamsPacket.teamDisplayName = "WOWdisplay";
|
||||
teamsPacket.nameTagVisibility = "always";
|
||||
teamsPacket.teamColor = 2;
|
||||
teamsPacket.teamPrefix = "pre";
|
||||
teamsPacket.teamSuffix = "suf";
|
||||
teamsPacket.collisionRule = "never";
|
||||
teamsPacket.entities = new String[]{getUsername()};
|
||||
sendPacketToViewersAndSelf(teamsPacket);
|
||||
TeamManager teamManager = Main.getTeamManager();
|
||||
Team team = teamManager.createTeam(getUsername());
|
||||
team.setTeamDisplayName("display");
|
||||
team.setPrefix("[Test] ");
|
||||
team.setTeamColor(ChatColor.RED);
|
||||
setTeam(team);
|
||||
|
||||
setAttribute(Attribute.MAX_HEALTH, 10);
|
||||
heal();
|
||||
@ -199,6 +188,8 @@ public class Player extends LivingEntity {
|
||||
}
|
||||
scoreboard.addViewer(this);
|
||||
scoreboard.updateLineContent("id3", "I HAVE BEEN UPDATED &2TEST");*/
|
||||
|
||||
setBelowNameScoreboard(new BelowNameScoreboard());
|
||||
});
|
||||
}
|
||||
|
||||
@ -349,7 +340,7 @@ public class Player extends LivingEntity {
|
||||
if (player == this)
|
||||
return;
|
||||
super.addViewer(player);
|
||||
PlayerConnection connection = player.getPlayerConnection();
|
||||
PlayerConnection viewerConnection = player.getPlayerConnection();
|
||||
String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19";
|
||||
SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket();
|
||||
spawnPlayerPacket.entityId = getEntityId();
|
||||
@ -362,13 +353,17 @@ public class Player extends LivingEntity {
|
||||
addP.properties.add(p);
|
||||
pInfoPacket.playerInfos.add(addP);
|
||||
|
||||
connection.sendPacket(pInfoPacket);
|
||||
connection.sendPacket(spawnPlayerPacket);
|
||||
connection.sendPacket(getMetadataPacket());
|
||||
viewerConnection.sendPacket(pInfoPacket);
|
||||
viewerConnection.sendPacket(spawnPlayerPacket);
|
||||
viewerConnection.sendPacket(getMetadataPacket());
|
||||
|
||||
for (EntityEquipmentPacket.Slot slot : EntityEquipmentPacket.Slot.values()) {
|
||||
player.playerConnection.sendPacket(getEquipmentPacket(slot));
|
||||
viewerConnection.sendPacket(getEquipmentPacket(slot));
|
||||
}
|
||||
|
||||
// Team
|
||||
if (team != null)
|
||||
viewerConnection.sendPacket(team.getTeamsCreationPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -376,9 +371,14 @@ public class Player extends LivingEntity {
|
||||
if (player == this)
|
||||
return;
|
||||
super.removeViewer(player);
|
||||
PlayerConnection viewerConnection = player.getPlayerConnection();
|
||||
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
|
||||
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid()));
|
||||
player.playerConnection.sendPacket(playerInfoPacket);
|
||||
viewerConnection.sendPacket(playerInfoPacket);
|
||||
|
||||
// Team
|
||||
if (team != null && team.getPlayers().size() == 1) // If team only contains "this" player
|
||||
viewerConnection.sendPacket(team.createTeamDestructionPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -692,6 +692,36 @@ public class Player extends LivingEntity {
|
||||
refreshHeldSlot(slot);
|
||||
}
|
||||
|
||||
public void setTeam(Team team) {
|
||||
if (this.team == team)
|
||||
return;
|
||||
|
||||
if (this.team != null) {
|
||||
this.team.removePlayer(this);
|
||||
}
|
||||
|
||||
this.team = team;
|
||||
if (team != null) {
|
||||
team.addPlayer(this);
|
||||
sendPacketToViewers(team.getTeamsCreationPacket()); // FIXME: only if viewer hasn't already register this team
|
||||
}
|
||||
}
|
||||
|
||||
public void setBelowNameScoreboard(BelowNameScoreboard belowNameScoreboard) {
|
||||
if (this.belowNameScoreboard == belowNameScoreboard)
|
||||
return;
|
||||
|
||||
if (this.belowNameScoreboard != null) {
|
||||
this.belowNameScoreboard.removeViewer(this);
|
||||
}
|
||||
|
||||
this.belowNameScoreboard = belowNameScoreboard;
|
||||
if (belowNameScoreboard != null) {
|
||||
belowNameScoreboard.addViewer(this);
|
||||
getViewers().forEach(player -> belowNameScoreboard.addViewer(player));
|
||||
}
|
||||
}
|
||||
|
||||
public short getHeldSlot() {
|
||||
return heldSlot;
|
||||
}
|
||||
|
@ -8,10 +8,12 @@ import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.block.BlockManager;
|
||||
import fr.themode.minestom.instance.block.CustomBlock;
|
||||
import fr.themode.minestom.instance.block.UpdateConsumer;
|
||||
import fr.themode.minestom.instance.block.UpdateOption;
|
||||
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
||||
import fr.themode.minestom.utils.BlockPosition;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
import fr.themode.minestom.utils.SerializerUtils;
|
||||
import fr.themode.minestom.utils.time.CooldownUtils;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -43,6 +45,8 @@ public class Chunk implements Viewable {
|
||||
|
||||
// Contains CustomBlocks' index which are updatable
|
||||
private IntSet updatableBlocks = new IntOpenHashSet();
|
||||
// (block index)/(last update in ms)
|
||||
private Int2LongMap updatableBlocksLastUpdate = new Int2LongOpenHashMap();
|
||||
|
||||
protected volatile boolean packetUpdated;
|
||||
|
||||
@ -89,7 +93,7 @@ public class Chunk implements Viewable {
|
||||
private void setBlock(byte x, byte y, byte z, short blockType, short customId, Data data, UpdateConsumer updateConsumer) {
|
||||
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
|
||||
if (blockType != 0 || customId != 0) {
|
||||
int value = (blockType << 16 | customId & 0xFFFF);
|
||||
int value = (blockType << 16 | customId & 0xFFFF); // Merge blockType and customId to one unique Integer (16/16)
|
||||
this.blocks.put(index, value);
|
||||
} else {
|
||||
// Block has been deleted
|
||||
@ -106,8 +110,10 @@ public class Chunk implements Viewable {
|
||||
// Set update consumer
|
||||
if (updateConsumer != null) {
|
||||
this.updatableBlocks.add(index);
|
||||
this.updatableBlocksLastUpdate.put(index, System.currentTimeMillis());
|
||||
} else {
|
||||
this.updatableBlocks.rem(index);
|
||||
this.updatableBlocks.remove(index);
|
||||
this.updatableBlocksLastUpdate.remove(index);
|
||||
}
|
||||
|
||||
if (isBlockEntity(blockType)) {
|
||||
@ -159,8 +165,12 @@ public class Chunk implements Viewable {
|
||||
}
|
||||
|
||||
public void updateBlocks(long time, Instance instance) {
|
||||
if (updatableBlocks.isEmpty())
|
||||
return;
|
||||
|
||||
// Block all chunk operation during the update
|
||||
synchronized (this) {
|
||||
IntIterator iterator = updatableBlocks.iterator();
|
||||
IntIterator iterator = new IntOpenHashSet(updatableBlocks).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
int index = iterator.nextInt();
|
||||
byte[] blockPos = SerializerUtils.indexToChunkPosition(index);
|
||||
@ -168,9 +178,17 @@ public class Chunk implements Viewable {
|
||||
byte y = blockPos[1];
|
||||
byte z = blockPos[2];
|
||||
CustomBlock customBlock = getCustomBlock(x, y, z);
|
||||
BlockPosition blockPosition = new BlockPosition(x * chunkX, y, z * chunkZ);
|
||||
|
||||
// Update cooldown
|
||||
UpdateOption updateOption = customBlock.getUpdateOption();
|
||||
long lastUpdate = updatableBlocksLastUpdate.get(index);
|
||||
boolean shouldUpdate = !CooldownUtils.hasCooldown(time, lastUpdate, updateOption.getTimeUnit(), updateOption.getValue());
|
||||
if (!shouldUpdate)
|
||||
continue;
|
||||
|
||||
this.updatableBlocksLastUpdate.put(index, time); // Refresh last update time
|
||||
BlockPosition blockPosition = new BlockPosition(x + 16 * chunkX, y, z + 16 * chunkZ);
|
||||
Data data = getData(index);
|
||||
// TODO should customBlock be updated?
|
||||
customBlock.update(instance, blockPosition, data);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ public class InstanceContainer extends Instance {
|
||||
byte chunkY = (byte) y;
|
||||
byte chunkZ = (byte) (z % 16);
|
||||
chunk.UNSAFE_setBlock(chunkX, chunkY, chunkZ, blockId, data);
|
||||
|
||||
// TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket
|
||||
sendBlockChange(chunk, x, y, z, blockId);
|
||||
}
|
||||
}
|
||||
@ -58,6 +60,8 @@ public class InstanceContainer extends Instance {
|
||||
byte chunkZ = (byte) (z % 16);
|
||||
chunk.UNSAFE_setCustomBlock(chunkX, chunkY, chunkZ, blockId, data);
|
||||
short id = BLOCK_MANAGER.getBlock(blockId).getType();
|
||||
|
||||
// TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket
|
||||
sendBlockChange(chunk, x, y, z, id);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,19 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.utils.thread.MinestomThread;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class InstanceManager {
|
||||
|
||||
private ExecutorService blocksPool = new MinestomThread(Main.THREAD_COUNT_BLOCK_UPDATE, "Ms-BlockUpdatePool");
|
||||
|
||||
private Set<Instance> instances = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
public InstanceContainer createInstanceContainer(File folder) {
|
||||
@ -30,6 +36,22 @@ public class InstanceManager {
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
public void updateBlocks() {
|
||||
if (instances.isEmpty())
|
||||
return;
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
blocksPool.execute(() -> {
|
||||
for (Instance instance : instances) {
|
||||
if (instance instanceof InstanceContainer) { // SharedInstance should be updated at the same time (verify?)
|
||||
for (Chunk chunk : instance.getChunks()) {
|
||||
chunk.updateBlocks(time, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Set<Instance> getInstances() {
|
||||
return Collections.unmodifiableSet(instances);
|
||||
}
|
||||
|
@ -1,42 +1,24 @@
|
||||
package fr.themode.minestom.instance.block;
|
||||
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.instance.Chunk;
|
||||
import fr.themode.minestom.instance.Instance;
|
||||
import fr.themode.minestom.instance.InstanceManager;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BlockManager {
|
||||
|
||||
private static InstanceManager instanceManager = Main.getInstanceManager();
|
||||
|
||||
private Short2ObjectMap<CustomBlock> blocksInternalId = new Short2ObjectOpenHashMap<>();
|
||||
private Map<String, CustomBlock> blocksId = new HashMap<>();
|
||||
|
||||
public void registerBlock(Supplier<CustomBlock> blocks) {
|
||||
CustomBlock customBlock = blocks.get();
|
||||
public void registerBlock(CustomBlock block) {
|
||||
CustomBlock customBlock = block;
|
||||
String identifier = customBlock.getIdentifier();
|
||||
short id = customBlock.getId();
|
||||
this.blocksInternalId.put(id, customBlock);
|
||||
this.blocksId.put(identifier, customBlock);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
long time = System.currentTimeMillis();
|
||||
// TODO another thread pool
|
||||
for (Instance instance : instanceManager.getInstances()) {
|
||||
// FIXME: only InstanceContainer?
|
||||
for (Chunk chunk : instance.getChunks()) {
|
||||
chunk.updateBlocks(time, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CustomBlock getBlock(String identifier) {
|
||||
return blocksId.get(identifier);
|
||||
}
|
||||
|
@ -15,29 +15,42 @@ public abstract class CustomBlock {
|
||||
|
||||
private static final AtomicInteger idCounter = new AtomicInteger();
|
||||
|
||||
private short type;
|
||||
private String identifier;
|
||||
private short id;
|
||||
|
||||
public CustomBlock() {
|
||||
public CustomBlock(short type, String identifier) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.id = (short) idCounter.incrementAndGet();
|
||||
}
|
||||
|
||||
// TODO add another object parameter which will offer a lot of integrated features (like break animation, id change etc...)
|
||||
public void update(Instance instance, BlockPosition blockPosition, Data data) {
|
||||
throw new UnsupportedOperationException("Update method not overriden");
|
||||
}
|
||||
|
||||
public abstract UpdateOption getUpdateOption();
|
||||
|
||||
public abstract short getType();
|
||||
|
||||
public abstract String getIdentifier();
|
||||
|
||||
/*
|
||||
Time in ms
|
||||
*/
|
||||
public abstract int getBreakDelay(Player player);
|
||||
|
||||
public boolean hasUpdate() {
|
||||
return getUpdateOption().getValue() > 0;
|
||||
UpdateOption updateOption = getUpdateOption();
|
||||
if (updateOption == null)
|
||||
return false;
|
||||
|
||||
return updateOption.getValue() > 0;
|
||||
}
|
||||
|
||||
public short getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public short getId() {
|
||||
|
@ -6,7 +6,5 @@ import fr.themode.minestom.utils.BlockPosition;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface UpdateConsumer {
|
||||
|
||||
void update(Instance instance, BlockPosition blockPosition, Data data);
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package fr.themode.minestom.instance.block;
|
||||
|
||||
import fr.themode.minestom.timer.TimeUnit;
|
||||
import fr.themode.minestom.utils.time.TimeUnit;
|
||||
|
||||
public class UpdateOption {
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.themode.minestom.instance.demo;
|
||||
|
||||
import fr.themode.minestom.data.Data;
|
||||
import fr.themode.minestom.instance.Biome;
|
||||
import fr.themode.minestom.instance.ChunkGenerator;
|
||||
import fr.themode.minestom.instance.batch.ChunkBatch;
|
||||
@ -16,8 +15,8 @@ public class ChunkGeneratorDemo extends ChunkGenerator {
|
||||
for (byte x = 0; x < 16; x++)
|
||||
for (byte z = 0; z < 16; z++) {
|
||||
for (byte y = 0; y < 65; y++) {
|
||||
if (random.nextInt(100) > 90) {
|
||||
batch.setCustomBlock(x, y, z, "custom_block", new Data());
|
||||
if (random.nextInt(100) > 10) {
|
||||
batch.setCustomBlock(x, y, z, "custom_block");
|
||||
} else {
|
||||
batch.setBlock(x, y, z, (short) 10);
|
||||
}
|
||||
|
@ -1,42 +1,18 @@
|
||||
package fr.themode.minestom.instance.demo;
|
||||
|
||||
import fr.themode.minestom.data.Data;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.Instance;
|
||||
import fr.themode.minestom.instance.block.CustomBlock;
|
||||
import fr.themode.minestom.instance.block.UpdateOption;
|
||||
import fr.themode.minestom.timer.TimeUnit;
|
||||
import fr.themode.minestom.utils.BlockPosition;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class StoneBlock extends CustomBlock {
|
||||
|
||||
private static final UpdateOption UPDATE_OPTION = new UpdateOption(1, TimeUnit.TICK);
|
||||
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
public StoneBlock() {
|
||||
super((short) 1, "custom_block");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateOption getUpdateOption() {
|
||||
return UPDATE_OPTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Instance instance, BlockPosition blockPosition, Data data) {
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
data.set("value", counter.incrementAndGet(), int.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getType() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "custom_block";
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,33 @@
|
||||
package fr.themode.minestom.instance.demo;
|
||||
|
||||
import fr.themode.minestom.data.Data;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.Instance;
|
||||
import fr.themode.minestom.instance.block.CustomBlock;
|
||||
import fr.themode.minestom.instance.block.UpdateOption;
|
||||
import fr.themode.minestom.utils.BlockPosition;
|
||||
import fr.themode.minestom.utils.time.TimeUnit;
|
||||
|
||||
public class UpdatableBlockDemo extends CustomBlock {
|
||||
|
||||
private static final UpdateOption UPDATE_OPTION = new UpdateOption(20, TimeUnit.TICK);
|
||||
|
||||
public UpdatableBlockDemo() {
|
||||
super((short) 11, "updatable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Instance instance, BlockPosition blockPosition, Data data) {
|
||||
System.out.println("BLOCK UPDATE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateOption getUpdateOption() {
|
||||
return UPDATE_OPTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBreakDelay(Player player) {
|
||||
return 500;
|
||||
}
|
||||
}
|
@ -37,10 +37,7 @@ public class DataReader {
|
||||
}
|
||||
|
||||
int valueLength = stream.readInt();
|
||||
byte[] valueCache = new byte[valueLength];
|
||||
for (int i = 0; i < valueLength; i++) {
|
||||
valueCache[i] = stream.readByte();
|
||||
}
|
||||
byte[] valueCache = stream.readNBytes(valueLength);
|
||||
|
||||
Class type = Class.forName(new String(typeCache));
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class BlockPlacementListener {
|
||||
|
||||
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
|
||||
if (!playerBlockPlaceEvent.isCancelled()) {
|
||||
instance.setCustomBlock(blockPosition, "custom_block"); // TODO set useItem's block instead
|
||||
instance.setCustomBlock(blockPosition, "updatable"); // TODO set useItem's block instead
|
||||
if (playerBlockPlaceEvent.doesConsumeBlock()) {
|
||||
usedItem.setAmount((byte) (usedItem.getAmount() - 1));
|
||||
if (usedItem.getAmount() <= 0)
|
||||
|
@ -13,13 +13,13 @@ import fr.themode.minestom.net.packet.client.handshake.HandshakePacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class PacketProcessor {
|
||||
|
||||
private Map<Client, PlayerConnection> connectionPlayerConnectionMap = new HashMap<>();
|
||||
private Map<Client, PlayerConnection> connectionPlayerConnectionMap = new ConcurrentHashMap<>();
|
||||
|
||||
private ConnectionManager connectionManager;
|
||||
|
||||
|
@ -14,11 +14,7 @@ public class RespawnPacket implements ServerPacket {
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
int gameModeId = gameMode.getId();
|
||||
if (gameMode.isHardcore())
|
||||
gameModeId |= 8;
|
||||
|
||||
writer.writeByte((byte) gameModeId);
|
||||
writer.writeByte((byte) gameMode.getId()); // Hardcore flag not included
|
||||
writer.writeInt(dimension.getId());
|
||||
writer.writeSizedString(levelType.getType());
|
||||
}
|
||||
|
@ -11,12 +11,11 @@ public class TeamsPacket implements ServerPacket {
|
||||
|
||||
public String teamDisplayName;
|
||||
public byte friendlyFlags;
|
||||
public String nameTagVisibility;
|
||||
public String collisionRule;
|
||||
public NameTagVisibility nameTagVisibility;
|
||||
public CollisionRule collisionRule;
|
||||
public int teamColor;
|
||||
public String teamPrefix;
|
||||
public String teamSuffix;
|
||||
public int entityCount;
|
||||
public String[] entities;
|
||||
|
||||
@Override
|
||||
@ -29,8 +28,8 @@ public class TeamsPacket implements ServerPacket {
|
||||
case UPDATE_TEAM_INFO:
|
||||
writer.writeSizedString(Chat.legacyTextString(teamDisplayName));
|
||||
writer.writeByte(friendlyFlags);
|
||||
writer.writeSizedString(nameTagVisibility);
|
||||
writer.writeSizedString(collisionRule);
|
||||
writer.writeSizedString(nameTagVisibility.getIdentifier());
|
||||
writer.writeSizedString(collisionRule.getIdentifier());
|
||||
writer.writeVarInt(teamColor);
|
||||
writer.writeSizedString(Chat.legacyTextString(teamPrefix));
|
||||
writer.writeSizedString(Chat.legacyTextString(teamSuffix));
|
||||
@ -59,4 +58,38 @@ public class TeamsPacket implements ServerPacket {
|
||||
REMOVE_PLAYERS_TEAM;
|
||||
}
|
||||
|
||||
public enum NameTagVisibility {
|
||||
ALWAYS("always"),
|
||||
HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"),
|
||||
HIDE_FOR_OWN_TEAM("hideForOwnTeam"),
|
||||
NEVER("never");
|
||||
|
||||
private String identifier;
|
||||
|
||||
NameTagVisibility(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CollisionRule {
|
||||
ALWAYS("always"),
|
||||
PUSH_OTHER_TEAMS("pushOtherTeams"),
|
||||
PUSH_OWN_TEAM("pushOwnTeam"),
|
||||
NEVER("never");
|
||||
|
||||
private String identifier;
|
||||
|
||||
CollisionRule(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
package fr.themode.minestom.scoreboard;
|
||||
|
||||
import fr.themode.minestom.Viewable;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.server.play.DisplayScoreboardPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.ScoreboardObjectivePacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class BelowNameScoreboard implements Viewable {
|
||||
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
// WARNING: you shouldn't create scoreboards/teams with the same prefixes as those
|
||||
private static final String SCOREBOARD_PREFIX = "bn-";
|
||||
private static final String TEAM_PREFIX = "bnt-";
|
||||
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
|
||||
private String objectiveName;
|
||||
|
||||
private ScoreboardObjectivePacket scoreboardObjectivePacket;
|
||||
private DisplayScoreboardPacket displayScoreboardPacket;
|
||||
|
||||
public BelowNameScoreboard() {
|
||||
this.objectiveName = SCOREBOARD_PREFIX + counter.incrementAndGet();
|
||||
System.out.println("DEBUG: " + objectiveName);
|
||||
scoreboardObjectivePacket = new ScoreboardObjectivePacket();
|
||||
scoreboardObjectivePacket.objectiveName = objectiveName;
|
||||
scoreboardObjectivePacket.mode = 0;
|
||||
scoreboardObjectivePacket.objectiveValue = "test:" + objectiveName;
|
||||
scoreboardObjectivePacket.type = 0;
|
||||
|
||||
displayScoreboardPacket = new DisplayScoreboardPacket();
|
||||
displayScoreboardPacket.position = 2;
|
||||
displayScoreboardPacket.scoreName = objectiveName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewer(Player player) {
|
||||
this.viewers.add(player);
|
||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
playerConnection.sendPacket(scoreboardObjectivePacket);
|
||||
// TODO score
|
||||
playerConnection.sendPacket(displayScoreboardPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewer(Player player) {
|
||||
this.viewers.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getViewers() {
|
||||
return Collections.unmodifiableSet(viewers);
|
||||
}
|
||||
}
|
@ -16,11 +16,15 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
// TODO update tick
|
||||
public class Scoreboard implements Viewable {
|
||||
public class Sidebar implements Viewable {
|
||||
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
// WARNING: you shouldn't create scoreboards/teams with the same prefixes as those
|
||||
private static final String SCOREBOARD_PREFIX = "sb-";
|
||||
private static final String TEAM_PREFIX = "sbt-";
|
||||
|
||||
// Limited by notchian client, do not change
|
||||
private static final int MAX_LINES_COUNT = 15;
|
||||
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
@ -32,7 +36,7 @@ public class Scoreboard implements Viewable {
|
||||
|
||||
private String title;
|
||||
|
||||
public Scoreboard(String title) {
|
||||
public Sidebar(String title) {
|
||||
this.title = title;
|
||||
|
||||
this.objectiveName = SCOREBOARD_PREFIX + counter.incrementAndGet();
|
||||
@ -64,7 +68,7 @@ public class Scoreboard implements Viewable {
|
||||
this.lines.add(scoreboardLine);
|
||||
|
||||
// Send to current viewers
|
||||
sendPacketsToViewers(scoreboardLine.team.getCreationPacket(), scoreboardLine.getScoreCreationPacket(objectiveName));
|
||||
sendPacketsToViewers(scoreboardLine.sidebarTeam.getCreationPacket(), scoreboardLine.getScoreCreationPacket(objectiveName));
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +76,7 @@ public class Scoreboard implements Viewable {
|
||||
for (ScoreboardLine line : lines) {
|
||||
if (line.id.equals(id)) {
|
||||
line.refreshContent(content);
|
||||
sendPacketToViewers(line.team.updatePrefix(content));
|
||||
sendPacketToViewers(line.sidebarTeam.updatePrefix(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,7 +106,7 @@ public class Scoreboard implements Viewable {
|
||||
if (line.id.equals(id)) {
|
||||
|
||||
// Remove the line for current viewers
|
||||
sendPacketsToViewers(line.getScoreCreationPacket(objectiveName), line.team.getDestructionPacket());
|
||||
sendPacketsToViewers(line.getScoreCreationPacket(objectiveName), line.sidebarTeam.getDestructionPacket());
|
||||
|
||||
line.returnName(availableColors);
|
||||
iterator.remove();
|
||||
@ -130,7 +134,7 @@ public class Scoreboard implements Viewable {
|
||||
playerConnection.sendPacket(displayScoreboardPacket); // Show sidebar scoreboard (wait for scores packet)
|
||||
|
||||
for (ScoreboardLine line : lines) {
|
||||
playerConnection.sendPacket(line.team.getCreationPacket());
|
||||
playerConnection.sendPacket(line.sidebarTeam.getCreationPacket());
|
||||
playerConnection.sendPacket(line.getScoreCreationPacket(objectiveName));
|
||||
}
|
||||
}
|
||||
@ -146,7 +150,7 @@ public class Scoreboard implements Viewable {
|
||||
|
||||
for (ScoreboardLine line : lines) {
|
||||
playerConnection.sendPacket(line.getScoreDestructionPacket(objectiveName)); // Is it necessary?
|
||||
playerConnection.sendPacket(line.team.getDestructionPacket());
|
||||
playerConnection.sendPacket(line.sidebarTeam.getDestructionPacket());
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +168,7 @@ public class Scoreboard implements Viewable {
|
||||
private String teamName;
|
||||
private int colorName; // Name of the score (entityName) which is essentially an ID
|
||||
private String entityName;
|
||||
private Team team;
|
||||
private SidebarTeam sidebarTeam;
|
||||
|
||||
public ScoreboardLine(String id, String content, int line) {
|
||||
this.id = id;
|
||||
@ -179,7 +183,7 @@ public class Scoreboard implements Viewable {
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return team == null ? content : team.getPrefix();
|
||||
return sidebarTeam == null ? content : sidebarTeam.getPrefix();
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
@ -195,7 +199,7 @@ public class Scoreboard implements Viewable {
|
||||
private void createTeam() {
|
||||
this.entityName = Chat.COLOR_CHAR + Integer.toHexString(colorName);
|
||||
|
||||
this.team = new Team(teamName, content, "", entityName);
|
||||
this.sidebarTeam = new SidebarTeam(teamName, content, "", entityName);
|
||||
}
|
||||
|
||||
private void returnName(LinkedList<Integer> colors) {
|
||||
@ -228,7 +232,7 @@ public class Scoreboard implements Viewable {
|
||||
}
|
||||
|
||||
private void refreshContent(String content) {
|
||||
this.team.refreshPrefix(content);
|
||||
this.sidebarTeam.refreshPrefix(content);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package fr.themode.minestom.scoreboard;
|
||||
|
||||
import fr.themode.minestom.net.packet.server.play.TeamsPacket;
|
||||
|
||||
public class SidebarTeam {
|
||||
|
||||
private String teamName;
|
||||
private String prefix, suffix;
|
||||
private String entityName;
|
||||
|
||||
private String teamDisplayName = "displaynametest";
|
||||
private byte friendlyFlags = 0x00;
|
||||
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.NEVER;
|
||||
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
|
||||
private int teamColor = 2;
|
||||
|
||||
|
||||
protected SidebarTeam(String teamName, String prefix, String suffix, String entityName) {
|
||||
this.teamName = teamName;
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
this.entityName = entityName;
|
||||
}
|
||||
|
||||
protected TeamsPacket getCreationPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
teamsPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
||||
teamsPacket.teamDisplayName = teamDisplayName;
|
||||
teamsPacket.friendlyFlags = friendlyFlags;
|
||||
teamsPacket.nameTagVisibility = nameTagVisibility;
|
||||
teamsPacket.collisionRule = collisionRule;
|
||||
teamsPacket.teamColor = teamColor;
|
||||
teamsPacket.teamPrefix = prefix;
|
||||
teamsPacket.teamSuffix = suffix;
|
||||
teamsPacket.entities = new String[]{entityName};
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
protected TeamsPacket getDestructionPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
teamsPacket.action = TeamsPacket.Action.REMOVE_TEAM;
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
protected TeamsPacket updatePrefix(String prefix) {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
teamsPacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
|
||||
teamsPacket.teamDisplayName = teamDisplayName;
|
||||
teamsPacket.friendlyFlags = friendlyFlags;
|
||||
teamsPacket.nameTagVisibility = nameTagVisibility;
|
||||
teamsPacket.collisionRule = collisionRule;
|
||||
teamsPacket.teamColor = teamColor;
|
||||
teamsPacket.teamPrefix = prefix;
|
||||
teamsPacket.teamSuffix = suffix;
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
protected String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
protected String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
protected void refreshPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
}
|
@ -1,72 +1,160 @@
|
||||
package fr.themode.minestom.scoreboard;
|
||||
|
||||
import com.github.simplenet.packet.Packet;
|
||||
import fr.themode.minestom.chat.ChatColor;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.server.play.TeamsPacket;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class Team {
|
||||
|
||||
private String teamName;
|
||||
private String prefix, suffix;
|
||||
private String entityName;
|
||||
|
||||
private String teamDisplayName = "displaynametest";
|
||||
private String teamDisplayName = "";
|
||||
private byte friendlyFlags = 0x00;
|
||||
private String nameTagVisibility = "never";
|
||||
private String collisionRule = "never";
|
||||
private int teamColor = 2;
|
||||
private TeamsPacket.NameTagVisibility nameTagVisibility = TeamsPacket.NameTagVisibility.ALWAYS;
|
||||
private TeamsPacket.CollisionRule collisionRule = TeamsPacket.CollisionRule.NEVER;
|
||||
private ChatColor teamColor = ChatColor.WHITE;
|
||||
private String prefix = "", suffix = "";
|
||||
private String[] entities = new String[0];
|
||||
private Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
|
||||
private TeamsPacket teamsCreationPacket;
|
||||
|
||||
protected Team(String teamName, String prefix, String suffix, String entityName) {
|
||||
private Packet teamsDestroyPacket;
|
||||
|
||||
protected Team(String teamName) {
|
||||
this.teamName = teamName;
|
||||
|
||||
teamsCreationPacket = new TeamsPacket();
|
||||
teamsCreationPacket.teamName = teamName;
|
||||
teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
||||
teamsCreationPacket.teamDisplayName = teamDisplayName;
|
||||
teamsCreationPacket.friendlyFlags = friendlyFlags;
|
||||
teamsCreationPacket.nameTagVisibility = nameTagVisibility;
|
||||
teamsCreationPacket.collisionRule = collisionRule;
|
||||
teamsCreationPacket.teamColor = teamColor.getId();
|
||||
teamsCreationPacket.teamPrefix = prefix;
|
||||
teamsCreationPacket.teamSuffix = suffix;
|
||||
teamsCreationPacket.entities = entities;
|
||||
|
||||
TeamsPacket destroyPacket = new TeamsPacket();
|
||||
destroyPacket.teamName = teamName;
|
||||
destroyPacket.action = TeamsPacket.Action.REMOVE_TEAM;
|
||||
PacketUtils.writePacket(destroyPacket, packet -> teamsDestroyPacket = packet); // Directly write packet since it will not change
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
String newElement = player.getUsername();
|
||||
|
||||
TeamsPacket addPlayerPacket = new TeamsPacket();
|
||||
addPlayerPacket.teamName = teamName;
|
||||
addPlayerPacket.action = TeamsPacket.Action.ADD_PLAYERS_TEAM;
|
||||
addPlayerPacket.entities = new String[]{newElement};
|
||||
for (Player p : players) {
|
||||
p.getPlayerConnection().sendPacket(addPlayerPacket);
|
||||
}
|
||||
|
||||
String[] entitiesCache = new String[entities.length + 1];
|
||||
System.arraycopy(entities, 0, entitiesCache, 0, entities.length);
|
||||
entitiesCache[entities.length] = newElement;
|
||||
this.entities = entitiesCache;
|
||||
this.teamsCreationPacket.entities = entities;
|
||||
|
||||
this.players.add(player);
|
||||
player.getPlayerConnection().sendPacket(teamsCreationPacket);
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
TeamsPacket removePlayerPacket = new TeamsPacket();
|
||||
removePlayerPacket.teamName = teamName;
|
||||
removePlayerPacket.action = TeamsPacket.Action.REMOVE_PLAYERS_TEAM;
|
||||
removePlayerPacket.entities = new String[]{player.getUsername()};
|
||||
for (Player p : players) {
|
||||
p.getPlayerConnection().sendPacket(removePlayerPacket);
|
||||
}
|
||||
|
||||
this.players.remove(player);
|
||||
player.getPlayerConnection().sendPacket(teamsDestroyPacket); // TODO do not destroy, simply remove the player from the team
|
||||
|
||||
String[] entitiesCache = new String[entities.length - 1];
|
||||
int count = 0;
|
||||
for (Player p : players) {
|
||||
entitiesCache[count++] = p.getUsername();
|
||||
}
|
||||
this.entities = entitiesCache;
|
||||
this.teamsCreationPacket.entities = entities;
|
||||
}
|
||||
|
||||
public void setTeamDisplayName(String teamDisplayName) {
|
||||
this.teamDisplayName = teamDisplayName;
|
||||
this.teamsCreationPacket.teamDisplayName = teamDisplayName;
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setNameTagVisibility(TeamsPacket.NameTagVisibility nameTagVisibility) {
|
||||
this.nameTagVisibility = nameTagVisibility;
|
||||
this.teamsCreationPacket.nameTagVisibility = nameTagVisibility;
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setCollisionRule(TeamsPacket.CollisionRule collisionRule) {
|
||||
this.collisionRule = collisionRule;
|
||||
this.teamsCreationPacket.collisionRule = collisionRule;
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setTeamColor(ChatColor teamColor) {
|
||||
this.teamColor = teamColor;
|
||||
this.teamsCreationPacket.teamColor = teamColor.getId();
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
this.teamsCreationPacket.teamPrefix = prefix;
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
this.entityName = entityName;
|
||||
this.teamsCreationPacket.teamSuffix = suffix;
|
||||
sendUpdatePacket();
|
||||
}
|
||||
|
||||
protected TeamsPacket getCreationPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
teamsPacket.action = TeamsPacket.Action.CREATE_TEAM;
|
||||
teamsPacket.teamDisplayName = teamDisplayName;
|
||||
teamsPacket.friendlyFlags = friendlyFlags;
|
||||
teamsPacket.nameTagVisibility = nameTagVisibility;
|
||||
teamsPacket.collisionRule = collisionRule;
|
||||
teamsPacket.teamColor = teamColor;
|
||||
teamsPacket.teamPrefix = prefix;
|
||||
teamsPacket.teamSuffix = suffix;
|
||||
teamsPacket.entities = new String[]{entityName};
|
||||
return teamsPacket;
|
||||
public String getTeamName() {
|
||||
return teamName;
|
||||
}
|
||||
|
||||
protected TeamsPacket getDestructionPacket() {
|
||||
public TeamsPacket getTeamsCreationPacket() {
|
||||
return teamsCreationPacket;
|
||||
}
|
||||
|
||||
public TeamsPacket createTeamDestructionPacket() {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
teamsPacket.action = TeamsPacket.Action.REMOVE_TEAM;
|
||||
return teamsPacket;
|
||||
}
|
||||
|
||||
protected TeamsPacket updatePrefix(String prefix) {
|
||||
TeamsPacket teamsPacket = new TeamsPacket();
|
||||
teamsPacket.teamName = teamName;
|
||||
teamsPacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
|
||||
teamsPacket.teamDisplayName = teamDisplayName;
|
||||
teamsPacket.friendlyFlags = friendlyFlags;
|
||||
teamsPacket.nameTagVisibility = nameTagVisibility;
|
||||
teamsPacket.collisionRule = collisionRule;
|
||||
teamsPacket.teamColor = teamColor;
|
||||
teamsPacket.teamPrefix = prefix;
|
||||
teamsPacket.teamSuffix = suffix;
|
||||
return teamsPacket;
|
||||
public Set<Player> getPlayers() {
|
||||
return Collections.unmodifiableSet(players);
|
||||
}
|
||||
|
||||
protected String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
protected String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
protected void refreshPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
private void sendUpdatePacket() {
|
||||
TeamsPacket updatePacket = new TeamsPacket();
|
||||
updatePacket.teamName = teamName;
|
||||
updatePacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO;
|
||||
updatePacket.teamDisplayName = teamDisplayName;
|
||||
updatePacket.friendlyFlags = friendlyFlags;
|
||||
updatePacket.nameTagVisibility = nameTagVisibility;
|
||||
updatePacket.collisionRule = collisionRule;
|
||||
updatePacket.teamColor = teamColor.getId();
|
||||
updatePacket.teamPrefix = prefix;
|
||||
updatePacket.teamSuffix = suffix;
|
||||
PacketUtils.writePacket(updatePacket, packet -> players.forEach(p -> p.getPlayerConnection().sendPacket(packet)));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package fr.themode.minestom.scoreboard;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class TeamManager {
|
||||
|
||||
// Represents all registered teams
|
||||
private Set<Team> teams = new CopyOnWriteArraySet<>();
|
||||
|
||||
public Team createTeam(String teamName) {
|
||||
Team team = new Team(teamName);
|
||||
this.teams.add(team);
|
||||
return team;
|
||||
}
|
||||
|
||||
public Set<Team> getTeams() {
|
||||
return teams;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package fr.themode.minestom.timer;
|
||||
|
||||
import fr.themode.minestom.utils.time.TimeUnit;
|
||||
|
||||
public class SchedulerManager {
|
||||
|
||||
public void addRepeatingTask(Runnable runnable, TimeUnit timeUnit, int time) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package fr.themode.minestom.utils.time;
|
||||
|
||||
public class CooldownUtils {
|
||||
|
||||
public static boolean hasCooldown(long currentTime, long lastUpdate, TimeUnit timeUnit, int cooldown) {
|
||||
long cooldownMs = timeUnit.toMilliseconds(cooldown);
|
||||
return currentTime - lastUpdate < cooldownMs;
|
||||
}
|
||||
|
||||
public static boolean hasCooldown(long lastUpdate, TimeUnit timeUnit, int cooldown) {
|
||||
return hasCooldown(System.currentTimeMillis(), lastUpdate, timeUnit, cooldown);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package fr.themode.minestom.timer;
|
||||
package fr.themode.minestom.utils.time;
|
||||
|
||||
import fr.themode.minestom.Main;
|
||||
|
Loading…
Reference in New Issue
Block a user