diff --git a/pom.xml b/pom.xml
index 07cfb89..9f2a475 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
com.loohp
Limbo
Limbo
- 0.6.19-ALPHA
+ 0.6.20-ALPHA
Standalone Limbo Minecraft Server.
https://github.com/LOOHP/Limbo
@@ -256,31 +256,31 @@
net.kyori
adventure-text-serializer-gson
- 4.10.1
+ 4.12.0
compile
net.kyori
adventure-text-serializer-legacy
- 4.10.1
+ 4.12.0
compile
net.kyori
adventure-text-serializer-plain
- 4.10.1
+ 4.12.0
compile
net.kyori
adventure-api
- 4.10.1
+ 4.12.0
compile
net.kyori
adventure-nbt
- 4.10.1
+ 4.12.0
compile
diff --git a/src/main/java/com/loohp/limbo/Limbo.java b/src/main/java/com/loohp/limbo/Limbo.java
index 8eef992..3f83cbf 100644
--- a/src/main/java/com/loohp/limbo/Limbo.java
+++ b/src/main/java/com/loohp/limbo/Limbo.java
@@ -19,42 +19,9 @@
package com.loohp.limbo;
-import java.awt.GraphicsEnvironment;
-import java.awt.image.BufferedImage;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.json.simple.parser.JSONParser;
-import org.json.simple.parser.ParseException;
-
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.loohp.limbo.bossbar.KeyedBossBar;
import com.loohp.limbo.commands.CommandSender;
import com.loohp.limbo.commands.DefaultCommands;
import com.loohp.limbo.consolegui.GUI;
@@ -66,6 +33,7 @@ import com.loohp.limbo.network.ServerConnection;
import com.loohp.limbo.network.protocol.packets.Packet;
import com.loohp.limbo.network.protocol.packets.PacketIn;
import com.loohp.limbo.network.protocol.packets.PacketOut;
+import com.loohp.limbo.network.protocol.packets.PacketPlayOutBoss;
import com.loohp.limbo.permissions.PermissionsManager;
import com.loohp.limbo.player.Player;
import com.loohp.limbo.plugins.LimboPlugin;
@@ -74,21 +42,56 @@ import com.loohp.limbo.scheduler.LimboScheduler;
import com.loohp.limbo.scheduler.Tick;
import com.loohp.limbo.utils.CustomStringUtils;
import com.loohp.limbo.utils.ImageUtils;
+import com.loohp.limbo.utils.NamespacedKey;
import com.loohp.limbo.utils.NetworkUtils;
import com.loohp.limbo.world.DimensionRegistry;
import com.loohp.limbo.world.Environment;
import com.loohp.limbo.world.Schematic;
import com.loohp.limbo.world.World;
-
+import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.querz.nbt.io.NBTUtil;
import net.querz.nbt.tag.CompoundTag;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
import javax.swing.UnsupportedLookAndFeelException;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
-public class Limbo {
+public final class Limbo {
public static final String LIMBO_BRAND = "Limbo";
@@ -135,39 +138,41 @@ public class Limbo {
public final int SERVER_IMPLEMENTATION_PROTOCOL = 761;
public final String LIMBO_IMPLEMENTATION_VERSION;
- private AtomicBoolean isRunning;
+ private final AtomicBoolean isRunning;
- private ServerConnection server;
- private Console console;
+ private final ServerConnection server;
+ private final Console console;
- private List worlds = new ArrayList<>();
- private Map playersByName = new HashMap<>();
- private Map playersByUUID = new HashMap<>();
+ private final List worlds = new CopyOnWriteArrayList<>();
+ final Map playersByName = new ConcurrentHashMap<>();
+ final Map playersByUUID = new ConcurrentHashMap<>();
+ private final Map bossBars = new ConcurrentHashMap<>();
- private ServerProperties properties;
+ private final ServerProperties properties;
- private PluginManager pluginManager;
- private EventsManager eventsManager;
- private PermissionsManager permissionManager;
- private File pluginFolder;
+ private final PluginManager pluginManager;
+ private final EventsManager eventsManager;
+ private final PermissionsManager permissionManager;
+ private final File pluginFolder;
- private File internalDataFolder;
+ private final File internalDataFolder;
- private DimensionRegistry dimensionRegistry;
+ private final DimensionRegistry dimensionRegistry;
- private Tick tick;
- private LimboScheduler scheduler;
+ private final Tick tick;
+ private final LimboScheduler scheduler;
- private Metrics metrics;
+ private final Metrics metrics;
- public AtomicInteger entityIdCount = new AtomicInteger();
+ public final AtomicInteger entityIdCount = new AtomicInteger();
@SuppressWarnings("deprecation")
- private Unsafe unsafe = new Unsafe();
+ private Unsafe unsafe;
@SuppressWarnings("unchecked")
public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException {
instance = this;
+ unsafe = new Unsafe(this);
isRunning = new AtomicBoolean(true);
if (!noGui) {
@@ -305,7 +310,7 @@ public class Limbo {
e.printStackTrace();
}
}
-
+
scheduler = new LimboScheduler();
tick = new Tick(this);
@@ -428,7 +433,31 @@ public class Limbo {
worlds.remove(world);
}
}
-
+
+ public KeyedBossBar createBossBar(NamespacedKey namespacedKey, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) {
+ KeyedBossBar keyedBossBar = new KeyedBossBar(namespacedKey, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags))));
+ bossBars.put(namespacedKey, keyedBossBar);
+ return keyedBossBar;
+ }
+
+ public void removeBossBar(NamespacedKey namespacedKey) {
+ KeyedBossBar keyedBossBar = bossBars.remove(namespacedKey);
+ keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().getLimboListener());
+ keyedBossBar.getUnsafe().invalidate();
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE);
+ for (Player player : keyedBossBar.getPlayers()) {
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public Map getBossBars() {
+ return Collections.unmodifiableMap(bossBars);
+ }
+
public ServerProperties getServerProperties() {
return properties;
}
@@ -457,16 +486,6 @@ public class Limbo {
return playersByUUID.get(uuid);
}
- public void addPlayer(Player player) {
- playersByName.put(player.getName(), player);
- playersByUUID.put(player.getUniqueId(), player);
- }
-
- public void removePlayer(Player player) {
- playersByName.remove(player.getName());
- playersByUUID.remove(player.getUniqueId());
- }
-
public List getWorlds() {
return new ArrayList<>(worlds);
}
diff --git a/src/main/java/com/loohp/limbo/Unsafe.java b/src/main/java/com/loohp/limbo/Unsafe.java
index a76779d..c148ea0 100644
--- a/src/main/java/com/loohp/limbo/Unsafe.java
+++ b/src/main/java/com/loohp/limbo/Unsafe.java
@@ -28,13 +28,16 @@ import com.loohp.limbo.player.Player;
import com.loohp.limbo.utils.GameMode;
import com.loohp.limbo.world.World;
+@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated
public class Unsafe {
-
+
+ private final Limbo instance;
private com.loohp.limbo.player.Unsafe playerUnsafe;
private com.loohp.limbo.world.Unsafe worldUnsafe;
- protected Unsafe() {
+ protected Unsafe(Limbo instance) {
+ this.instance = instance;
try {
Constructor playerConstructor = com.loohp.limbo.player.Unsafe.class.getDeclaredConstructor();
playerConstructor.setAccessible(true);
@@ -78,4 +81,17 @@ public class Unsafe {
playerUnsafe.a(player, location);
}
+ @Deprecated
+ public void addPlayer(Player player) {
+ instance.playersByName.put(player.getName(), player);
+ instance.playersByUUID.put(player.getUniqueId(), player);
+ }
+
+ @Deprecated
+ public void removePlayer(Player player) {
+ instance.getBossBars().values().forEach(each -> each.hidePlayer(player));
+ instance.playersByName.remove(player.getName());
+ instance.playersByUUID.remove(player.getUniqueId());
+ }
+
}
diff --git a/src/main/java/com/loohp/limbo/bossbar/KeyedBossBar.java b/src/main/java/com/loohp/limbo/bossbar/KeyedBossBar.java
new file mode 100644
index 0000000..06edd31
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/bossbar/KeyedBossBar.java
@@ -0,0 +1,176 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.bossbar;
+
+import com.loohp.limbo.network.protocol.packets.PacketPlayOutBoss;
+import com.loohp.limbo.player.Player;
+import com.loohp.limbo.utils.NamespacedKey;
+import net.kyori.adventure.bossbar.BossBar;
+import net.kyori.adventure.text.Component;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class KeyedBossBar {
+
+ private final UUID uuid;
+ private final NamespacedKey key;
+ private final BossBar properties;
+ private final Set players;
+ protected final LimboBossBarHandler listener;
+ protected final AtomicBoolean valid;
+ private final Unsafe unsafe;
+
+ @SuppressWarnings("DeprecatedIsStillUsed")
+ @Deprecated
+ public KeyedBossBar(NamespacedKey key, BossBar properties) {
+ this.uuid = UUID.randomUUID();
+ this.key = key;
+ this.properties = properties;
+ this.players = ConcurrentHashMap.newKeySet();
+ this.listener = new LimboBossBarHandler(this);
+ this.properties.addListener(listener);
+ this.valid = new AtomicBoolean(true);
+ this.unsafe = new Unsafe(this);
+ }
+
+ public UUID getUniqueId() {
+ return uuid;
+ }
+
+ public NamespacedKey getKey() {
+ return key;
+ }
+
+ public BossBar getProperties() {
+ return properties;
+ }
+
+ public Set getPlayers() {
+ return Collections.unmodifiableSet(players);
+ }
+
+ public UUID getUuid() {
+ return uuid;
+ }
+
+ public boolean isValid() {
+ return valid.get();
+ }
+
+ @Deprecated
+ public Unsafe getUnsafe() {
+ return unsafe;
+ }
+
+ public boolean showPlayer(Player player) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(this, PacketPlayOutBoss.BossBarAction.ADD);
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException ignore) {
+ }
+ return players.add(player);
+ }
+
+ public boolean hidePlayer(Player player) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(this, PacketPlayOutBoss.BossBarAction.REMOVE);
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException ignore) {
+ }
+ return players.remove(player);
+ }
+
+ public static class LimboBossBarHandler implements BossBar.Listener {
+
+ private final KeyedBossBar parent;
+
+ private LimboBossBarHandler(KeyedBossBar parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void bossBarNameChanged(@NotNull BossBar bar, @NotNull Component oldName, @NotNull Component newName) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(parent, PacketPlayOutBoss.BossBarAction.UPDATE_NAME);
+ for (Player player : parent.getPlayers()) {
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void bossBarProgressChanged(@NotNull BossBar bar, float oldProgress, float newProgress) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(parent, PacketPlayOutBoss.BossBarAction.UPDATE_PROGRESS);
+ for (Player player : parent.getPlayers()) {
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void bossBarColorChanged(@NotNull BossBar bar, BossBar.@NotNull Color oldColor, BossBar.@NotNull Color newColor) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(parent, PacketPlayOutBoss.BossBarAction.UPDATE_STYLE);
+ for (Player player : parent.getPlayers()) {
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void bossBarOverlayChanged(@NotNull BossBar bar, BossBar.@NotNull Overlay oldOverlay, BossBar.@NotNull Overlay newOverlay) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(parent, PacketPlayOutBoss.BossBarAction.UPDATE_STYLE);
+ for (Player player : parent.getPlayers()) {
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void bossBarFlagsChanged(@NotNull BossBar bar, @NotNull Set flagsAdded, @NotNull Set flagsRemoved) {
+ PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(parent, PacketPlayOutBoss.BossBarAction.UPDATE_PROPERTIES);
+ for (Player player : parent.getPlayers()) {
+ try {
+ player.clientConnection.sendPacket(packetPlayOutBoss);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/loohp/limbo/bossbar/Unsafe.java b/src/main/java/com/loohp/limbo/bossbar/Unsafe.java
new file mode 100644
index 0000000..1322f52
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/bossbar/Unsafe.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.bossbar;
+
+@SuppressWarnings("DeprecatedIsStillUsed")
+@Deprecated
+public class Unsafe {
+
+ private final KeyedBossBar instance;
+
+ protected Unsafe(KeyedBossBar instance) {
+ this.instance = instance;
+ }
+
+ @Deprecated
+ public KeyedBossBar.LimboBossBarHandler getLimboListener() {
+ return instance.listener;
+ }
+
+ @Deprecated
+ public void invalidate() {
+ instance.valid.set(false);
+ }
+
+}
diff --git a/src/main/java/com/loohp/limbo/commands/CommandSender.java b/src/main/java/com/loohp/limbo/commands/CommandSender.java
index 97d0870..77ceedb 100644
--- a/src/main/java/com/loohp/limbo/commands/CommandSender.java
+++ b/src/main/java/com/loohp/limbo/commands/CommandSender.java
@@ -34,46 +34,46 @@ import net.md_5.bungee.api.chat.BaseComponent;
public interface CommandSender extends Audience {
- public void sendMessage(BaseComponent[] component, UUID uuid);
+ void sendMessage(BaseComponent[] component, UUID uuid);
- public void sendMessage(BaseComponent component, UUID uuid);
+ void sendMessage(BaseComponent component, UUID uuid);
- public void sendMessage(String message, UUID uuid);
+ void sendMessage(String message, UUID uuid);
- public void sendMessage(BaseComponent[] component);
+ void sendMessage(BaseComponent[] component);
- public void sendMessage(BaseComponent component);
+ void sendMessage(BaseComponent component);
- public void sendMessage(String message);
+ void sendMessage(String message);
- public boolean hasPermission(String permission);
+ boolean hasPermission(String permission);
- public String getName();
-
- public void sendMessage(Identity source, Component message, MessageType type);
-
- public void openBook(Book book);
-
- public void stopSound(SoundStop stop);
-
- public void playSound(Sound sound, Sound.Emitter emitter);
-
- public void playSound(Sound sound, double x, double y, double z);
-
- public void playSound(Sound sound);
-
- public void sendActionBar(Component message);
-
- public void sendPlayerListHeaderAndFooter(Component header, Component footer);
-
- public void sendTitlePart(TitlePart part, T value);
-
- public void clearTitle();
-
- public void resetTitle();
-
- public void showBossBar(BossBar bar);
+ String getName();
- public void hideBossBar(BossBar bar);
+ void sendMessage(Identity source, Component message, MessageType type);
+
+ void openBook(Book book);
+
+ void stopSound(SoundStop stop);
+
+ void playSound(Sound sound, Sound.Emitter emitter);
+
+ void playSound(Sound sound, double x, double y, double z);
+
+ void playSound(Sound sound);
+
+ void sendActionBar(Component message);
+
+ void sendPlayerListHeaderAndFooter(Component header, Component footer);
+
+ void sendTitlePart(TitlePart part, T value);
+
+ void clearTitle();
+
+ void resetTitle();
+
+ void showBossBar(BossBar bar);
+
+ void hideBossBar(BossBar bar);
}
diff --git a/src/main/java/com/loohp/limbo/entity/Entity.java b/src/main/java/com/loohp/limbo/entity/Entity.java
index 1c26d77..eb6dac2 100644
--- a/src/main/java/com/loohp/limbo/entity/Entity.java
+++ b/src/main/java/com/loohp/limbo/entity/Entity.java
@@ -28,11 +28,12 @@ import com.loohp.limbo.location.Location;
import com.loohp.limbo.utils.BungeecordAdventureConversionUtils;
import com.loohp.limbo.world.World;
+import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
-public abstract class Entity {
+public abstract class Entity implements Sound.Emitter {
@WatchableField(MetadataIndex = 0, WatchableObjectType = WatchableObjectType.BYTE, IsBitmask = true, Bitmask = 0x01)
protected boolean onFire = false;
diff --git a/src/main/java/com/loohp/limbo/network/Channel.java b/src/main/java/com/loohp/limbo/network/Channel.java
index fc24e25..5df2265 100644
--- a/src/main/java/com/loohp/limbo/network/Channel.java
+++ b/src/main/java/com/loohp/limbo/network/Channel.java
@@ -48,7 +48,7 @@ public class Channel implements AutoCloseable {
private void ensureOpen() {
if (!valid.get()) {
- throw new IllegalStateException("Channel already closed!");
+ close();
}
}
@@ -106,10 +106,13 @@ public class Channel implements AutoCloseable {
}
@Override
- public synchronized void close() throws Exception {
+ public synchronized void close() {
if (valid.compareAndSet(true, false)) {
- input.close();
- output.close();
+ try {
+ input.close();
+ output.close();
+ } catch (Exception ignore) {
+ }
}
}
diff --git a/src/main/java/com/loohp/limbo/network/ClientConnection.java b/src/main/java/com/loohp/limbo/network/ClientConnection.java
index 2ebb860..fd16033 100644
--- a/src/main/java/com/loohp/limbo/network/ClientConnection.java
+++ b/src/main/java/com/loohp/limbo/network/ClientConnection.java
@@ -491,7 +491,7 @@ public class ClientConnection extends Thread {
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
- Limbo.getInstance().addPlayer(player);
+ Limbo.getInstance().getUnsafe().addPlayer(player);
break;
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
@@ -519,7 +519,7 @@ public class ClientConnection extends Thread {
player = new Player(this, data.getUsername(), data.getUuid(), Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
- Limbo.getInstance().addPlayer(player);
+ Limbo.getInstance().getUnsafe().addPlayer(player);
break;
}
@@ -757,7 +757,7 @@ public class ClientConnection extends Thread {
state = ClientState.DISCONNECTED;
if (player != null) {
- Limbo.getInstance().removePlayer(player);
+ Limbo.getInstance().getUnsafe().removePlayer(player);
}
Limbo.getInstance().getServerConnection().getClients().remove(this);
running = false;
diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/ClientboundSetActionBarTextPacket.java b/src/main/java/com/loohp/limbo/network/protocol/packets/ClientboundSetActionBarTextPacket.java
new file mode 100644
index 0000000..63d6088
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/network/protocol/packets/ClientboundSetActionBarTextPacket.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.network.protocol.packets;
+
+import com.loohp.limbo.utils.DataTypeIO;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+public class ClientboundSetActionBarTextPacket extends PacketOut {
+
+ private Component actionBar;
+
+ public ClientboundSetActionBarTextPacket(Component actionBar) {
+ this.actionBar = actionBar;
+ }
+
+ public Component getActionBar() {
+ return actionBar;
+ }
+
+ @Override
+ public byte[] serializePacket() throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ DataOutputStream output = new DataOutputStream(buffer);
+ output.writeByte(Packet.getPlayOut().get(getClass()));
+ DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(actionBar), StandardCharsets.UTF_8);
+
+ return buffer.toByteArray();
+ }
+}
diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutBoss.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutBoss.java
new file mode 100644
index 0000000..6a81aba
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutBoss.java
@@ -0,0 +1,117 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.network.protocol.packets;
+
+import com.loohp.limbo.bossbar.KeyedBossBar;
+import com.loohp.limbo.utils.DataTypeIO;
+import net.kyori.adventure.bossbar.BossBar;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+public class PacketPlayOutBoss extends PacketOut {
+
+ public enum BossBarAction {
+ ADD,
+ REMOVE,
+ UPDATE_PROGRESS,
+ UPDATE_NAME,
+ UPDATE_STYLE,
+ UPDATE_PROPERTIES;
+ }
+
+ private static int encodeProperties(boolean darkenScreen, boolean playMusic, boolean createWorldFog) {
+ int i = 0;
+ if (darkenScreen) {
+ i |= 1;
+ }
+ if (playMusic) {
+ i |= 2;
+ }
+ if (createWorldFog) {
+ i |= 4;
+ }
+ return i;
+ }
+
+ private KeyedBossBar bossBar;
+ private BossBarAction action;
+
+ public PacketPlayOutBoss(KeyedBossBar bossBar, BossBarAction action) {
+ this.bossBar = bossBar;
+ this.action = action;
+ }
+
+ public KeyedBossBar getBossBar() {
+ return bossBar;
+ }
+
+ public BossBarAction getAction() {
+ return action;
+ }
+
+ @Override
+ public byte[] serializePacket() throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ DataOutputStream output = new DataOutputStream(buffer);
+ output.writeByte(Packet.getPlayOut().get(getClass()));
+
+ DataTypeIO.writeUUID(output, bossBar.getUniqueId());
+ DataTypeIO.writeVarInt(output, action.ordinal());
+
+ BossBar properties = bossBar.getProperties();
+ switch (action) {
+ case ADD: {
+ DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(properties.name()), StandardCharsets.UTF_8);
+ output.writeFloat(properties.progress());
+ DataTypeIO.writeVarInt(output, properties.color().ordinal());
+ DataTypeIO.writeVarInt(output, properties.overlay().ordinal());
+ output.writeByte(encodeProperties(properties.hasFlag(BossBar.Flag.DARKEN_SCREEN), properties.hasFlag(BossBar.Flag.PLAY_BOSS_MUSIC), properties.hasFlag(BossBar.Flag.CREATE_WORLD_FOG)));
+ break;
+ }
+ case REMOVE: {
+ break;
+ }
+ case UPDATE_PROGRESS: {
+ output.writeFloat(properties.progress());
+ break;
+ }
+ case UPDATE_NAME: {
+ DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(properties.name()), StandardCharsets.UTF_8);
+ break;
+ }
+ case UPDATE_STYLE: {
+ DataTypeIO.writeVarInt(output, properties.color().ordinal());
+ DataTypeIO.writeVarInt(output, properties.overlay().ordinal());
+ break;
+ }
+ case UPDATE_PROPERTIES: {
+ output.writeByte(encodeProperties(properties.hasFlag(BossBar.Flag.DARKEN_SCREEN), properties.hasFlag(BossBar.Flag.PLAY_BOSS_MUSIC), properties.hasFlag(BossBar.Flag.CREATE_WORLD_FOG)));
+ break;
+ }
+ }
+
+ return buffer.toByteArray();
+ }
+}
diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutNamedSoundEffect.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutNamedSoundEffect.java
new file mode 100644
index 0000000..d175e84
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutNamedSoundEffect.java
@@ -0,0 +1,112 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.network.protocol.packets;
+
+import com.loohp.limbo.sounds.SoundEffect;
+import com.loohp.limbo.utils.DataTypeIO;
+import net.kyori.adventure.sound.Sound;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+
+public class PacketPlayOutNamedSoundEffect extends PacketOut {
+
+ private SoundEffect sound;
+ private Sound.Source source;
+ private int x;
+ private int y;
+ private int z;
+ private float volume;
+ private float pitch;
+ private long seed;
+
+ public PacketPlayOutNamedSoundEffect(SoundEffect sound, Sound.Source source, double x, double y, double z, float volume, float pitch, long seed) {
+ this.sound = sound;
+ this.source = source;
+ this.x = (int) (x * 8.0);
+ this.y = (int) (y * 8.0);
+ this.z = (int) (z * 8.0);
+ this.volume = volume;
+ this.pitch = pitch;
+ this.seed = seed;
+ }
+
+ public SoundEffect getSound() {
+ return sound;
+ }
+
+ public Sound.Source getSource() {
+ return source;
+ }
+
+ public double getX() {
+ return (float) this.x / 8.0F;
+ }
+
+ public double getY() {
+ return (float) this.y / 8.0F;
+ }
+
+ public double getZ() {
+ return (float) this.z / 8.0F;
+ }
+
+ public float getVolume() {
+ return volume;
+ }
+
+ public float getPitch() {
+ return pitch;
+ }
+
+ public long getSeed() {
+ return seed;
+ }
+
+ @Override
+ public byte[] serializePacket() throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ DataOutputStream output = new DataOutputStream(buffer);
+ output.writeByte(Packet.getPlayOut().get(getClass()));
+
+ DataTypeIO.writeVarInt(output, 0);
+ DataTypeIO.writeString(output, sound.getSound().toString(), StandardCharsets.UTF_8);
+ Optional fixedRange = sound.fixedRange();
+ if (fixedRange.isPresent()) {
+ output.writeBoolean(true);
+ output.writeFloat(fixedRange.get());
+ } else {
+ output.writeBoolean(false);
+ }
+ DataTypeIO.writeVarInt(output, source.ordinal());
+ output.writeInt(x);
+ output.writeInt(y);
+ output.writeInt(z);
+ output.writeFloat(volume);
+ output.writeFloat(pitch);
+ output.writeLong(seed);
+
+ return buffer.toByteArray();
+ }
+}
diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutStopSound.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutStopSound.java
new file mode 100644
index 0000000..2201d49
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutStopSound.java
@@ -0,0 +1,74 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.network.protocol.packets;
+
+import com.loohp.limbo.utils.DataTypeIO;
+import com.loohp.limbo.utils.NamespacedKey;
+import net.kyori.adventure.sound.Sound;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+public class PacketPlayOutStopSound extends PacketOut {
+
+ private NamespacedKey sound;
+ private Sound.Source source;
+
+ public PacketPlayOutStopSound(NamespacedKey sound, Sound.Source source) {
+ this.sound = sound;
+ this.source = source;
+ }
+
+ public NamespacedKey getSound() {
+ return sound;
+ }
+
+ public Sound.Source getSource() {
+ return source;
+ }
+
+ @Override
+ public byte[] serializePacket() throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ DataOutputStream output = new DataOutputStream(buffer);
+ output.writeByte(Packet.getPlayOut().get(getClass()));
+
+ if (source != null) {
+ if (sound != null) {
+ output.writeByte(3);
+ DataTypeIO.writeVarInt(output, source.ordinal());
+ DataTypeIO.writeString(output, sound.toString(), StandardCharsets.UTF_8);
+ } else {
+ output.writeByte(1);
+ DataTypeIO.writeVarInt(output, source.ordinal());
+ }
+ } else if (sound != null) {
+ output.writeByte(2);
+ DataTypeIO.writeString(output, sound.toString(), StandardCharsets.UTF_8);
+ } else {
+ output.writeByte(0);
+ }
+
+ return buffer.toByteArray();
+ }
+}
diff --git a/src/main/java/com/loohp/limbo/player/Player.java b/src/main/java/com/loohp/limbo/player/Player.java
index dac915e..a2e854d 100644
--- a/src/main/java/com/loohp/limbo/player/Player.java
+++ b/src/main/java/com/loohp/limbo/player/Player.java
@@ -31,6 +31,7 @@ import com.loohp.limbo.events.player.PlayerTeleportEvent;
import com.loohp.limbo.location.Location;
import com.loohp.limbo.network.ClientConnection;
import com.loohp.limbo.network.protocol.packets.ClientboundClearTitlesPacket;
+import com.loohp.limbo.network.protocol.packets.ClientboundSetActionBarTextPacket;
import com.loohp.limbo.network.protocol.packets.ClientboundSetSubtitleTextPacket;
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitleTextPacket;
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
@@ -38,10 +39,13 @@ import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
import com.loohp.limbo.network.protocol.packets.PacketOut;
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState;
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
+import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect;
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerListHeaderFooter;
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
import com.loohp.limbo.network.protocol.packets.PacketPlayOutResourcePackSend;
import com.loohp.limbo.network.protocol.packets.PacketPlayOutRespawn;
+import com.loohp.limbo.network.protocol.packets.PacketPlayOutStopSound;
+import com.loohp.limbo.sounds.SoundEffect;
import com.loohp.limbo.utils.BungeecordAdventureConversionUtils;
import com.loohp.limbo.utils.GameMode;
import com.loohp.limbo.utils.MessageSignature;
@@ -50,6 +54,7 @@ import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.inventory.Book;
+import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.sound.Sound.Emitter;
import net.kyori.adventure.sound.SoundStop;
@@ -65,6 +70,7 @@ import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
public class Player extends LivingEntity implements CommandSender {
@@ -448,7 +454,13 @@ public class Player extends LivingEntity implements CommandSender {
@Override
public void stopSound(SoundStop stop) {
- throw new UnsupportedOperationException("This function has not been implemented yet.");
+ Key sound = stop.sound();
+ PacketPlayOutStopSound stopSound = new PacketPlayOutStopSound(sound == null ? null : NamespacedKey.fromKey(sound), stop.source());
+ try {
+ clientConnection.sendPacket(stopSound);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
@Override
@@ -458,27 +470,37 @@ public class Player extends LivingEntity implements CommandSender {
@Override
public void playSound(Sound sound, double x, double y, double z) {
- throw new UnsupportedOperationException("This function has not been implemented yet.");
+ PacketPlayOutNamedSoundEffect namedSoundEffect = new PacketPlayOutNamedSoundEffect(
+ SoundEffect.createVariableRangeEvent(NamespacedKey.fromKey(sound.name())),
+ sound.source(), x, y, z, sound.volume(), sound.pitch(), sound.seed().orElse(ThreadLocalRandom.current().nextLong())
+ );
+ try {
+ clientConnection.sendPacket(namedSoundEffect);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
@Override
public void playSound(Sound sound) {
- throw new UnsupportedOperationException("This function has not been implemented yet.");
+ playSound(sound, x, y, z);
}
@Override
public void sendActionBar(Component message) {
try {
- ClientboundSystemChatPacket chat = new ClientboundSystemChatPacket(message, true);
- clientConnection.sendPacket(chat);
- } catch (IOException ignored) {}
+ ClientboundSetActionBarTextPacket setActionBar = new ClientboundSetActionBarTextPacket(message);
+ clientConnection.sendPacket(setActionBar);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
@Override
public void sendPlayerListHeaderAndFooter(Component header, Component footer) {
try {
- PacketPlayOutPlayerListHeaderFooter packsend = new PacketPlayOutPlayerListHeaderFooter(header, footer);
- clientConnection.sendPacket(packsend);
+ PacketPlayOutPlayerListHeaderFooter listHeaderFooter = new PacketPlayOutPlayerListHeaderFooter(header, footer);
+ clientConnection.sendPacket(listHeaderFooter);
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/src/main/java/com/loohp/limbo/scheduler/Tick.java b/src/main/java/com/loohp/limbo/scheduler/Tick.java
index 4f668ed..7c4619f 100644
--- a/src/main/java/com/loohp/limbo/scheduler/Tick.java
+++ b/src/main/java/com/loohp/limbo/scheduler/Tick.java
@@ -40,88 +40,82 @@ public class Tick {
private Queue asyncTasksQueue = new ConcurrentLinkedQueue<>();
public Tick(Limbo instance) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- tickingInterval = (int) Math.round(1000.0 / Limbo.getInstance().getServerProperties().getDefinedTicksPerSecond());
-
- for (int i = 0; i < 4; i++) {
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- while (instance.isRunning()) {
- LimboSchedulerTask task = asyncTasksQueue.poll();
- if (task == null) {
- try {
- TimeUnit.NANOSECONDS.sleep(10000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- } else {
- LimboTask limboTask = task.getTask();
- try {
- limboTask.run();
- } catch (Throwable e) {
- System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage());
- e.printStackTrace();
- }
- }
- }
- }
- });
- thread.start();
- threads.add(thread);
- }
-
- while (instance.isRunning()) {
- long start = System.currentTimeMillis();
- tick.incrementAndGet();
- instance.getPlayers().forEach(each -> {
- if (each.clientConnection.isReady()) {
+ new Thread(() -> {
+ tickingInterval = (int) Math.round(1000.0 / Limbo.getInstance().getServerProperties().getDefinedTicksPerSecond());
+
+ for (int i = 0; i < 4; i++) {
+ Thread thread = new Thread(() -> {
+ while (instance.isRunning()) {
+ LimboSchedulerTask task = asyncTasksQueue.poll();
+ if (task == null) {
try {
- each.playerInteractManager.update();
- } catch (IOException e) {
+ TimeUnit.NANOSECONDS.sleep(10000);
+ } catch (InterruptedException e) {
e.printStackTrace();
}
- /*
- try {
- each.getDataWatcher().update();
- } catch (IllegalArgumentException | IllegalAccessException e) {
- e.printStackTrace();
- }
- */
- }
- });
- instance.getWorlds().forEach(each -> {
- try {
- each.update();
- } catch (IllegalArgumentException | IllegalAccessException e) {
- e.printStackTrace();
- }
- });
-
- CurrentSchedulerTask tasks = instance.getScheduler().collectTasks(getCurrentTick());
- if (tasks != null) {
- asyncTasksQueue.addAll(tasks.getAsyncTasks());
-
- tasks.getSyncedTasks().forEach(task -> {
- LimboTask limboTask = task.getTask();
+ } else {
+ LimboTask limboTask = task.getTask();
try {
limboTask.run();
} catch (Throwable e) {
System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage());
e.printStackTrace();
}
- });
- }
-
- long end = System.currentTimeMillis();
- try {
- TimeUnit.MILLISECONDS.sleep(tickingInterval - (end - start));
- } catch (InterruptedException e) {
+ }
+ }
+ });
+ thread.start();
+ threads.add(thread);
+ }
+
+ while (instance.isRunning()) {
+ long start = System.currentTimeMillis();
+ tick.incrementAndGet();
+ instance.getPlayers().forEach(each -> {
+ if (each.clientConnection.isReady()) {
+ try {
+ each.playerInteractManager.update();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ /*
+ try {
+ each.getDataWatcher().update();
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ */
+ }
+ });
+ instance.getWorlds().forEach(each -> {
+ try {
+ each.update();
+ } catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
- }
+ });
+
+ CurrentSchedulerTask tasks = instance.getScheduler().collectTasks(getCurrentTick());
+ if (tasks != null) {
+ asyncTasksQueue.addAll(tasks.getAsyncTasks());
+
+ tasks.getSyncedTasks().forEach(task -> {
+ LimboTask limboTask = task.getTask();
+ try {
+ limboTask.run();
+ } catch (Throwable e) {
+ System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage());
+ e.printStackTrace();
+ }
+ });
+ }
+
+ long end = System.currentTimeMillis();
+ try {
+ TimeUnit.MILLISECONDS.sleep(tickingInterval - (end - start));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
}).start();
}
diff --git a/src/main/java/com/loohp/limbo/sounds/SoundEffect.java b/src/main/java/com/loohp/limbo/sounds/SoundEffect.java
new file mode 100644
index 0000000..bd1feba
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/sounds/SoundEffect.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * Copyright (C) 2022. Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.loohp.limbo.sounds;
+
+import com.loohp.limbo.utils.NamespacedKey;
+
+import java.util.Optional;
+
+public class SoundEffect {
+
+ public static SoundEffect createVariableRangeEvent(NamespacedKey namespacedKey) {
+ return new SoundEffect(namespacedKey, 16.0F, false);
+ }
+
+ public static SoundEffect createFixedRangeEvent(NamespacedKey namespacedKey, float range) {
+ return new SoundEffect(namespacedKey, range, true);
+ }
+
+ private final NamespacedKey sound;
+ private final float range;
+ private final boolean newSystem;
+
+ private SoundEffect(NamespacedKey sound, float range, boolean newSystem) {
+ this.sound = sound;
+ this.range = range;
+ this.newSystem = newSystem;
+ }
+
+ public NamespacedKey getSound() {
+ return sound;
+ }
+
+ public float getRange() {
+ return range;
+ }
+
+ public boolean isNewSystem() {
+ return newSystem;
+ }
+
+ public Optional fixedRange() {
+ return this.newSystem ? Optional.of(this.range) : Optional.empty();
+ }
+}
diff --git a/src/main/java/com/loohp/limbo/utils/NamespacedKey.java b/src/main/java/com/loohp/limbo/utils/NamespacedKey.java
index 7733d2b..721babd 100644
--- a/src/main/java/com/loohp/limbo/utils/NamespacedKey.java
+++ b/src/main/java/com/loohp/limbo/utils/NamespacedKey.java
@@ -19,12 +19,25 @@
package com.loohp.limbo.utils;
+import com.loohp.limbo.plugins.LimboPlugin;
+import net.kyori.adventure.key.Key;
+
+import java.util.Objects;
+
public class NamespacedKey {
public static final String MINECRAFT_KEY = "minecraft";
- private String namespace;
- private String key;
+ public static NamespacedKey minecraft(String key) {
+ return new NamespacedKey(MINECRAFT_KEY, key);
+ }
+
+ public static NamespacedKey fromKey(Key key) {
+ return new NamespacedKey(key.namespace(), key.value());
+ }
+
+ private final String namespace;
+ private final String key;
public NamespacedKey(String namespacedKey) {
int index = namespacedKey.indexOf(":");
@@ -37,14 +50,14 @@ public class NamespacedKey {
}
}
+ public NamespacedKey(LimboPlugin plugin, String key) {
+ this(plugin.getName().toLowerCase().replace(" ", "_"), key);
+ }
+
public NamespacedKey(String namespace, String key) {
this.namespace = namespace;
this.key = key;
}
-
- public static NamespacedKey minecraft(String key) {
- return new NamespacedKey(MINECRAFT_KEY, key);
- }
public String getNamespace() {
return namespace;
@@ -54,40 +67,25 @@ public class NamespacedKey {
return key;
}
+ public Key toKey() {
+ return Key.key(namespace, key);
+ }
+
@Override
public String toString() {
return namespace + ":" + key;
}
@Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((key == null) ? 0 : key.hashCode());
- result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
- return result;
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NamespacedKey that = (NamespacedKey) o;
+ return namespace.equals(that.namespace) && key.equals(that.key);
}
@Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- NamespacedKey other = (NamespacedKey) obj;
- if (key == null) {
- if (other.key != null)
- return false;
- } else if (!key.equals(other.key))
- return false;
- if (namespace == null) {
- if (other.namespace != null)
- return false;
- } else if (!namespace.equals(other.namespace))
- return false;
- return true;
+ public int hashCode() {
+ return Objects.hash(namespace, key);
}
-
}
diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json
index 8a90cb0..59d366e 100644
--- a/src/main/resources/mapping.json
+++ b/src/main/resources/mapping.json
@@ -49,7 +49,11 @@
"ClientboundSetTitlesAnimationPacket": "0x5C",
"ClientboundSetTitleTextPacket": "0x5B",
"ClientboundSetSubtitleTextPacket": "0x59",
- "ClientboundClearTitlesPacket": "0x0C"
+ "ClientboundSetActionBarTextPacket": "0x42",
+ "ClientboundClearTitlesPacket": "0x0C",
+ "PacketPlayOutBoss": "0x0A",
+ "PacketPlayOutNamedSoundEffect": "0x5E",
+ "PacketPlayOutStopSound": "0x5F"
},
"StatusIn": {
"0x01": "PacketStatusInPing",