NPC
This commit is contained in:
parent
9d5c79cf6c
commit
6d3c2ceff0
32 changed files with 1603 additions and 48 deletions
100
core/dependency-reduced-pom.xml
Normal file
100
core/dependency-reduced-pom.xml
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>SheepWars</artifactId>
|
||||||
|
<groupId>org.ef3d0c3e.sheepwars</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>SheepWars-core</artifactId>
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.github.retrooper.packetevents</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.api</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>io.github.retrooper.packetevents</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.impl</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>de.cubbossa.cliententities.lib.packetevents.api</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.api</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>de.cubbossa.cliententities.lib.packetevents.impl</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.impl</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>fr.mrmicky.fastboard</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.fastboard</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot</artifactId>
|
||||||
|
<version>1.21.1-R0.1-SNAPSHOT</version>
|
||||||
|
<classifier>remapped-mojang</classifier>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.21.1-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.retrooper</groupId>
|
||||||
|
<artifactId>packetevents-spigot</artifactId>
|
||||||
|
<version>2.4.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.comphenix.protocol</groupId>
|
||||||
|
<artifactId>ProtocolLib</artifactId>
|
||||||
|
<version>5.2.0-SNAPSHOT-726</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${pom.basedir}/../libs/ProtocolLib.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sk89q.worldedit</groupId>
|
||||||
|
<artifactId>worldedit-bukkit</artifactId>
|
||||||
|
<version>7.3.6</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${pom.basedir}/../libs/worldedit-bukkit-7.3.6-SNAPSHOT-dist.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
16
core/pom.xml
16
core/pom.xml
|
@ -48,12 +48,18 @@
|
||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${pom.basedir}/../libs/ProtocolLib.jar</systemPath>
|
<systemPath>${pom.basedir}/../libs/ProtocolLib.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.retrooper</groupId>
|
||||||
|
<artifactId>packetevents-spigot</artifactId>
|
||||||
|
<version>2.4.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sk89q.worldedit</groupId>
|
<groupId>com.sk89q.worldedit</groupId>
|
||||||
<artifactId>worldedit-bukkit</artifactId>
|
<artifactId>worldedit-bukkit</artifactId>
|
||||||
<version>7.3.5</version>
|
<version>7.3.6</version>
|
||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${pom.basedir}/../libs/worldedit-bukkit-7.3.5.jar</systemPath>
|
<systemPath>${pom.basedir}/../libs/worldedit-bukkit-7.3.6-SNAPSHOT-dist.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>fr.mrmicky</groupId>
|
<groupId>fr.mrmicky</groupId>
|
||||||
|
@ -61,9 +67,9 @@
|
||||||
<version>2.1.3</version>
|
<version>2.1.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bukkit</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>bukkit</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>1.21.1-R0.1-SNAPSHOT</version>
|
<version>33.1.0-jre</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package org.ef3d0c3e.sheepwars;
|
package org.ef3d0c3e.sheepwars;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
import com.comphenix.protocol.ProtocolManager;
|
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||||
|
import org.ef3d0c3e.sheepwars.commands.CommandFactory;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
@ -15,6 +16,7 @@ import org.ef3d0c3e.sheepwars.events.EventListenerFactory;
|
||||||
import org.ef3d0c3e.sheepwars.game.Game;
|
import org.ef3d0c3e.sheepwars.game.Game;
|
||||||
import org.ef3d0c3e.sheepwars.level.VoidChunkGenerator;
|
import org.ef3d0c3e.sheepwars.level.VoidChunkGenerator;
|
||||||
import org.ef3d0c3e.sheepwars.locale.LocaleManager;
|
import org.ef3d0c3e.sheepwars.locale.LocaleManager;
|
||||||
|
import org.ef3d0c3e.sheepwars.packets.PacketListenerFactory;
|
||||||
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
import org.ef3d0c3e.sheepwars.versions.WrapperFactory;
|
import org.ef3d0c3e.sheepwars.versions.WrapperFactory;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -22,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.EventListener;
|
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
@ -31,8 +32,6 @@ public final class SheepWars extends JavaPlugin
|
||||||
@Getter
|
@Getter
|
||||||
private static Plugin plugin;
|
private static Plugin plugin;
|
||||||
@Getter
|
@Getter
|
||||||
private static ProtocolManager protocolManager;
|
|
||||||
@Getter
|
|
||||||
private static Config sheepWarsConfig;
|
private static Config sheepWarsConfig;
|
||||||
@Getter
|
@Getter
|
||||||
private static LocaleManager localeManager;
|
private static LocaleManager localeManager;
|
||||||
|
@ -87,7 +86,6 @@ public final class SheepWars extends JavaPlugin
|
||||||
{
|
{
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -136,22 +134,32 @@ public final class SheepWars extends JavaPlugin
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||||
|
PacketEvents.getAPI().load();
|
||||||
|
|
||||||
consoleMessage("--[ Setup done ]--");
|
consoleMessage("--[ Setup done ]--");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
PacketEvents.getAPI().terminate();
|
||||||
consoleMessage("Plugin Disabled!");
|
consoleMessage("Plugin Disabled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
plugin = this;
|
plugin = this;
|
||||||
protocolManager = ProtocolLibrary.getProtocolManager();
|
|
||||||
|
PacketEvents.getAPI().getSettings()
|
||||||
|
.debug(true)
|
||||||
|
.reEncodeByDefault(true);
|
||||||
|
PacketEvents.getAPI().init();
|
||||||
|
|
||||||
// Factories
|
// Factories
|
||||||
try {
|
try {
|
||||||
|
CommandFactory.registerCommands();
|
||||||
EventListenerFactory.create();
|
EventListenerFactory.create();
|
||||||
|
PacketListenerFactory.create();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
4
core/src/main/java/org/ef3d0c3e/sheepwars/Util.java
Normal file
4
core/src/main/java/org/ef3d0c3e/sheepwars/Util.java
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package org.ef3d0c3e.sheepwars;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.commands;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CmdSheepWars extends Command {
|
||||||
|
public CmdSheepWars()
|
||||||
|
{
|
||||||
|
super("sheepwars", "Plugin command", "/sheepwars", Arrays.asList("sw"));
|
||||||
|
setPermission("sw.admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) {
|
||||||
|
if (!(sender instanceof Player))
|
||||||
|
{
|
||||||
|
sender.sendMessage("§cYou must be a player to execute this command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Player p = (Player)sender;
|
||||||
|
final String category = args.length == 0 ? "help" : args[0];
|
||||||
|
if (category.equals("help"))
|
||||||
|
{
|
||||||
|
sender.sendMessage(" - §ahelp §fDisplays this page");
|
||||||
|
sender.sendMessage(" - §astart §fStarts the game");
|
||||||
|
sender.sendMessage(" - §adebug §7<option> §fFor developers");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> tabComplete(final @NotNull CommandSender sender, final @NotNull String label, final @NotNull String[] args)
|
||||||
|
{
|
||||||
|
if (args.length == 0) return null;
|
||||||
|
else if (args.length == 1)
|
||||||
|
{
|
||||||
|
return Lists.newArrayList(
|
||||||
|
"help",
|
||||||
|
"start",
|
||||||
|
"debug"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (args[0].equals("debug"))
|
||||||
|
{
|
||||||
|
if (args.length == 2) return Lists.newArrayList("<poses>");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.commands;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.*;
|
||||||
|
import org.bukkit.help.GenericCommandHelpTopic;
|
||||||
|
import org.bukkit.help.HelpTopic;
|
||||||
|
import org.bukkit.help.IndexHelpTopic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class CommandFactory implements CommandExecutor, TabCompleter
|
||||||
|
{
|
||||||
|
private static final HashMap<String, Command> COMMANDS;
|
||||||
|
static
|
||||||
|
{
|
||||||
|
COMMANDS = new HashMap<>();
|
||||||
|
|
||||||
|
// Find all commands and populate COMMANDS
|
||||||
|
Reflections refl = new Reflections("org.ef3d0c3e.sheepwars.commands");
|
||||||
|
Set<Class<? extends Command>> classes = refl.getSubTypesOf(Command.class);
|
||||||
|
|
||||||
|
for (Class C : classes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final Command cmd;
|
||||||
|
cmd = (Command)(C.getDeclaredConstructor().newInstance());
|
||||||
|
COMMANDS.put(cmd.getName(), cmd);
|
||||||
|
}
|
||||||
|
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers all commands
|
||||||
|
*/
|
||||||
|
public static void registerCommands()
|
||||||
|
{
|
||||||
|
final CommandFactory executor = new CommandFactory();
|
||||||
|
|
||||||
|
// Get command map
|
||||||
|
CommandMap map = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Field cmdMap = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
|
||||||
|
cmdMap.setAccessible(true);
|
||||||
|
map = (CommandMap)cmdMap.get(Bukkit.getPluginManager());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register commands
|
||||||
|
for (final Command cmd : COMMANDS.values())
|
||||||
|
map.register(cmd.getName(), cmd);
|
||||||
|
|
||||||
|
// Generate help
|
||||||
|
List<HelpTopic> cmdHelp = new ArrayList<>();
|
||||||
|
COMMANDS.forEach((name, cmd) -> cmdHelp.add(new GenericCommandHelpTopic(cmd)));
|
||||||
|
|
||||||
|
Bukkit.getHelpMap().addTopic(
|
||||||
|
new IndexHelpTopic(
|
||||||
|
"Hunt",
|
||||||
|
"Hunt minigame plugin",
|
||||||
|
"org.ef3d0c3e.hunt.help",
|
||||||
|
cmdHelp,
|
||||||
|
"Hunt plugin"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(final @NotNull CommandSender sender, final Command cmd, final @NotNull String label, final String[] args)
|
||||||
|
{
|
||||||
|
final Command bcmd = COMMANDS.get(cmd.getName().toLowerCase());
|
||||||
|
if (bcmd == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bcmd.execute(sender, label, args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> onTabComplete(final @NotNull CommandSender sender, final Command cmd, final @NotNull String label, final String[] args)
|
||||||
|
{
|
||||||
|
final Command bcmd = COMMANDS.get(cmd.getName().toLowerCase());
|
||||||
|
if (bcmd == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return bcmd.tabComplete(sender, label, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.ef3d0c3e.sheepwars.events.EventListenerFactory;
|
||||||
import org.ef3d0c3e.sheepwars.events.WantsListen;
|
import org.ef3d0c3e.sheepwars.events.WantsListen;
|
||||||
import org.ef3d0c3e.sheepwars.level.LevelFactory;
|
import org.ef3d0c3e.sheepwars.level.LevelFactory;
|
||||||
import org.ef3d0c3e.sheepwars.level.lobby.LobbyLevel;
|
import org.ef3d0c3e.sheepwars.level.lobby.LobbyLevel;
|
||||||
|
import org.ef3d0c3e.sheepwars.packets.PacketListenerFactory;
|
||||||
|
|
||||||
public class Game {
|
public class Game {
|
||||||
private static void changePhase(WantsListen.Target phase)
|
private static void changePhase(WantsListen.Target phase)
|
||||||
|
@ -15,8 +16,7 @@ public class Game {
|
||||||
|
|
||||||
EventListenerFactory.update(phase);
|
EventListenerFactory.update(phase);
|
||||||
//TimedListenerFactory.update(phase);
|
//TimedListenerFactory.update(phase);
|
||||||
//PacketListenerFactory.update(phase);
|
PacketListenerFactory.update(phase);
|
||||||
//RecipeFactory.update(phase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -43,7 +43,7 @@ public class Game {
|
||||||
//LevelFactory.add(level);
|
//LevelFactory.add(level);
|
||||||
|
|
||||||
// Create lobby world
|
// Create lobby world
|
||||||
// Game level is created once it is needeed
|
// Game level is created once it is needed
|
||||||
// @see CmdHunt
|
// @see CmdHunt
|
||||||
new BukkitRunnable()
|
new BukkitRunnable()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.hologram;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public abstract class Hologram
|
||||||
|
{
|
||||||
|
@Getter
|
||||||
|
private final int networkId;
|
||||||
|
@Getter
|
||||||
|
private final ArrayList<HologramComponent> components;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param networkId Base network id
|
||||||
|
*/
|
||||||
|
protected Hologram(final int networkId)
|
||||||
|
{
|
||||||
|
this.networkId = networkId;
|
||||||
|
components = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds component to hologram
|
||||||
|
* @param component Component to add
|
||||||
|
*/
|
||||||
|
public void addComponent(final @NonNull HologramComponent component)
|
||||||
|
{
|
||||||
|
this.components.add(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets hologram location for player
|
||||||
|
* @param cp Player to get location for
|
||||||
|
* @return Hologram location
|
||||||
|
*/
|
||||||
|
public abstract @NonNull Location getLocation(final @NonNull CPlayer cp);
|
||||||
|
|
||||||
|
protected boolean sendPredicate(final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.hologram;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for a Hologram's component
|
||||||
|
*/
|
||||||
|
public abstract class HologramComponent
|
||||||
|
{
|
||||||
|
@Getter
|
||||||
|
private Vector offset;
|
||||||
|
|
||||||
|
protected HologramComponent(final @NonNull Vector offset)
|
||||||
|
{
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the amount of network entity id that the component takes
|
||||||
|
* @return The number of entity id taken by the component
|
||||||
|
*/
|
||||||
|
protected abstract int getNetworkOffset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds hologram packets
|
||||||
|
*
|
||||||
|
* @param networkId Base network id
|
||||||
|
* @param cp Player to build hologram component for
|
||||||
|
* @return Packets to display component
|
||||||
|
*/
|
||||||
|
protected abstract @NonNull List<PacketWrapper<?>> build(final @NonNull Location location, final int networkId, final @NonNull CPlayer cp);
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.hologram;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.ef3d0c3e.sheepwars.SheepWars;
|
||||||
|
import org.ef3d0c3e.sheepwars.events.CPlayerJoinEvent;
|
||||||
|
import org.ef3d0c3e.sheepwars.events.WantsListen;
|
||||||
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HologramFactory
|
||||||
|
{
|
||||||
|
private static final HashMap<Integer, Hologram> registry = new HashMap<>();
|
||||||
|
|
||||||
|
public static void register(final @NonNull Hologram hologram)
|
||||||
|
{
|
||||||
|
registry.put(hologram.getNetworkId(), hologram);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unregister(final @NonNull Hologram hologram)
|
||||||
|
{
|
||||||
|
registry.remove(hologram.getNetworkId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends hologram to player
|
||||||
|
* @param hologram Hologram to send
|
||||||
|
* @param cp Player to send hologram to
|
||||||
|
*/
|
||||||
|
public static void send(final @NonNull Hologram hologram, final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
final List<HologramComponent> components = hologram.getComponents();
|
||||||
|
final Location location = hologram.getLocation(cp);
|
||||||
|
|
||||||
|
int networkId = hologram.getNetworkId();
|
||||||
|
for (final HologramComponent component : components)
|
||||||
|
{
|
||||||
|
// Build & send packets
|
||||||
|
for (final PacketWrapper<?> packet : component.build(location, networkId, cp))
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), packet);
|
||||||
|
|
||||||
|
// Offset network id
|
||||||
|
networkId += component.getNetworkOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-sends hologram to player
|
||||||
|
* @param hologram Hologram to un-send
|
||||||
|
* @param cp Player to un-send to
|
||||||
|
*/
|
||||||
|
public static void unsend(final @NonNull Hologram hologram, final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
int networkId = hologram.getNetworkId();
|
||||||
|
|
||||||
|
final List<HologramComponent> components = hologram.getComponents();
|
||||||
|
int size = 0;
|
||||||
|
for (final HologramComponent component : components)
|
||||||
|
{
|
||||||
|
size += component.getNetworkOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] list = new int[size];
|
||||||
|
int pos = 0;
|
||||||
|
for (final HologramComponent component : hologram.getComponents())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < component.getNetworkOffset(); ++i) {
|
||||||
|
list[pos] = networkId + i;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
networkId += component.getNetworkOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
final WrapperPlayServerDestroyEntities remove = new WrapperPlayServerDestroyEntities();
|
||||||
|
remove.setEntityIds(list);
|
||||||
|
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@WantsListen(phase = WantsListen.Target.Always)
|
||||||
|
public static class HologramListener implements Listener
|
||||||
|
{
|
||||||
|
// TODO..., on chunk load request [something...]
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(final CPlayerJoinEvent ev)
|
||||||
|
{
|
||||||
|
final CPlayer cp = ev.getPlayer();
|
||||||
|
for (final Hologram hologram : registry.values())
|
||||||
|
{
|
||||||
|
if (!hologram.sendPredicate(cp)) continue;
|
||||||
|
|
||||||
|
send(hologram, cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.hologram;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||||
|
import com.github.retrooper.packetevents.util.Vector3d;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnLivingEntity;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.ef3d0c3e.sheepwars.packets.EntityMetadata;
|
||||||
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a text component
|
||||||
|
*/
|
||||||
|
public abstract class HologramTextComponent extends HologramComponent
|
||||||
|
{
|
||||||
|
protected HologramTextComponent(@NonNull Vector offset)
|
||||||
|
{
|
||||||
|
super(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract @NonNull Component getText(final @NonNull CPlayer cp);
|
||||||
|
|
||||||
|
protected int getNetworkOffset() { return 1; }
|
||||||
|
|
||||||
|
protected @NonNull List<PacketWrapper<?>> build(final @NonNull Location location, final int networkId, final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
// Spawn
|
||||||
|
final Location loc = location.clone().add(getOffset());
|
||||||
|
final WrapperPlayServerSpawnEntity spawn = new WrapperPlayServerSpawnEntity(
|
||||||
|
networkId, Optional.of(UUID.randomUUID()),
|
||||||
|
EntityTypes.ARMOR_STAND,
|
||||||
|
new Vector3d(loc.getX(), loc.getY(), loc.getZ()),
|
||||||
|
loc.getYaw(), 0.f, loc.getPitch(),
|
||||||
|
0,
|
||||||
|
Optional.empty()
|
||||||
|
);
|
||||||
|
// Metadata
|
||||||
|
final WrapperPlayServerEntityMetadata meta = new WrapperPlayServerEntityMetadata(
|
||||||
|
networkId,
|
||||||
|
Arrays.asList(
|
||||||
|
new EntityMetadata.Status()
|
||||||
|
.isInvisible(true)
|
||||||
|
.into(),
|
||||||
|
new EntityMetadata.NoGravity(true).into(),
|
||||||
|
new EntityMetadata.CustomNameVisible(true).into(),
|
||||||
|
new EntityMetadata.CustomName(getText(cp)).into()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return List.of(spawn, meta);
|
||||||
|
}
|
||||||
|
}
|
211
core/src/main/java/org/ef3d0c3e/sheepwars/items/IItem.java
Normal file
211
core/src/main/java/org/ef3d0c3e/sheepwars/items/IItem.java
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.items;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Item;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Sheep;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.enchantment.EnchantItemEvent;
|
||||||
|
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||||
|
import org.bukkit.event.entity.ItemDespawnEvent;
|
||||||
|
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.ef3d0c3e.sheepwars.SheepWars;
|
||||||
|
import org.ef3d0c3e.sheepwars.events.WantsListen;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
// TODO: Add option to prevent using the item in crafting recipes
|
||||||
|
public abstract class IItem
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* UUID persistant tag
|
||||||
|
*/
|
||||||
|
static private final PersistentDataType<byte[], UUID> TAG_UUID = new UUIDItemTagType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key used to store item's id
|
||||||
|
*/
|
||||||
|
static protected final NamespacedKey KEY_ID = new NamespacedKey(SheepWars.getPlugin(), "hunt_uuid");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item's id
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.MODULE)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public IItem()
|
||||||
|
{
|
||||||
|
this.id = UUID.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IItem(final UUID id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets item's key
|
||||||
|
* @param item Item to get id of
|
||||||
|
* @return Item's id or null
|
||||||
|
*/
|
||||||
|
protected static @Nullable UUID getId(final ItemStack item)
|
||||||
|
{
|
||||||
|
final ItemMeta meta = item.getItemMeta();
|
||||||
|
if (meta == null)
|
||||||
|
return null;
|
||||||
|
final PersistentDataContainer container = meta.getPersistentDataContainer();
|
||||||
|
if (container == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return container.getOrDefault(KEY_ID, TAG_UUID, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean replace(final @NonNull Inventory inv, final @NonNull IItem item, final @NonNull ItemStack replace)
|
||||||
|
{
|
||||||
|
boolean replaced = false;
|
||||||
|
for (int i = 0; i < inv.getSize(); ++i)
|
||||||
|
{
|
||||||
|
if (inv.getItem(i) == null || inv.getItem(i).getItemMeta() == null) continue;
|
||||||
|
final IItem base = ItemFactory.getItem(inv.getItem(i));
|
||||||
|
if (base == null || base.getId() != item.getId()) continue;
|
||||||
|
|
||||||
|
inv.setItem(i, replace);
|
||||||
|
replaced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replaced;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies custom item to itemstack
|
||||||
|
* @param item Item to apply custom item to
|
||||||
|
* @return ItemStack
|
||||||
|
*/
|
||||||
|
public ItemStack apply(final ItemStack item)
|
||||||
|
{
|
||||||
|
final ItemStack custom = item.clone();
|
||||||
|
final ItemMeta meta = custom.getItemMeta();
|
||||||
|
meta.getPersistentDataContainer().set(KEY_ID, TAG_UUID, getId());
|
||||||
|
custom.setItemMeta(meta);
|
||||||
|
|
||||||
|
return custom;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean onDrop(final Player p, final ItemStack item);
|
||||||
|
protected abstract boolean onInteract(final Player p, final ItemStack item, final Action action, final EquipmentSlot hand, final Block clicked, final BlockFace clickedFace);
|
||||||
|
protected boolean onEnchant(final EnchantItemEvent ev) { return true; }
|
||||||
|
protected boolean onPickup(final LivingEntity ent, final Item item, final int remaining) { return false; }
|
||||||
|
protected boolean onDespawn(final Item item) { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Events to handle custom items
|
||||||
|
* Note: Does not handle events related to entities/inventories not linked to a player
|
||||||
|
*/
|
||||||
|
@WantsListen(phase = WantsListen.Target.Always)
|
||||||
|
public static class Events implements Listener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handles custom item interactions
|
||||||
|
* @param ev Event
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
public void onInteract(final PlayerInteractEvent ev)
|
||||||
|
{
|
||||||
|
if (ev.getItem() == null)
|
||||||
|
return;
|
||||||
|
final IItem item = ItemFactory.getItem(ev.getItem());
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ev.setCancelled(item.onInteract(
|
||||||
|
ev.getPlayer(),
|
||||||
|
ev.getItem(),
|
||||||
|
ev.getAction(),
|
||||||
|
ev.getHand(),
|
||||||
|
ev.getClickedBlock(),
|
||||||
|
ev.getBlockFace()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles custom item dropping
|
||||||
|
* @param ev Event
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
public void onDrop(final PlayerDropItemEvent ev)
|
||||||
|
{
|
||||||
|
final ItemStack stack = ev.getItemDrop().getItemStack();
|
||||||
|
|
||||||
|
final IItem item = ItemFactory.getItem(stack);
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ev.setCancelled(item.onDrop(ev.getPlayer(), stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles custom item enchant
|
||||||
|
* @param ev Event
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
public void onEnchant(final EnchantItemEvent ev)
|
||||||
|
{
|
||||||
|
final IItem item = ItemFactory.getItem(ev.getItem());
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item.onEnchant(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles custom item pickup
|
||||||
|
* @param ev Event
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
public void onPickup(final EntityPickupItemEvent ev)
|
||||||
|
{
|
||||||
|
final IItem item = ItemFactory.getItem(ev.getItem().getItemStack());
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ev.setCancelled(item.onPickup(
|
||||||
|
ev.getEntity(),
|
||||||
|
ev.getItem(),
|
||||||
|
ev.getRemaining()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles custom item despawn
|
||||||
|
* @param ev Event
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
public void onDespawn(final ItemDespawnEvent ev)
|
||||||
|
{
|
||||||
|
final IItem item = ItemFactory.getItem(ev.getEntity().getItemStack());
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ev.setCancelled(item.onDespawn(ev.getEntity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.items;
|
||||||
|
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to register custom items
|
||||||
|
*/
|
||||||
|
public class ItemFactory
|
||||||
|
{
|
||||||
|
protected static HashMap<UUID, IItem> registry = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets custom item from itemstack
|
||||||
|
* @param item Item
|
||||||
|
* @return Custom item (null for normal item)
|
||||||
|
*/
|
||||||
|
public static @Nullable IItem getItem(final ItemStack item)
|
||||||
|
{
|
||||||
|
final UUID id = IItem.getId(item);
|
||||||
|
if (id == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return registry.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers custom item to registry
|
||||||
|
* @param item Item to register
|
||||||
|
*/
|
||||||
|
public static void registerItem(final IItem item)
|
||||||
|
{
|
||||||
|
registry.put(item.getId(), item);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.items;
|
||||||
|
|
||||||
|
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UUIDItemTagType implements PersistentDataType<byte[], UUID>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public @NotNull Class<byte[]> getPrimitiveType()
|
||||||
|
{
|
||||||
|
return byte[].class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Class<UUID> getComplexType()
|
||||||
|
{
|
||||||
|
return UUID.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] toPrimitive(UUID uuid, @NotNull PersistentDataAdapterContext context)
|
||||||
|
{
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(16);
|
||||||
|
buffer.putLong(uuid.getLeastSignificantBits());
|
||||||
|
buffer.putLong(uuid.getMostSignificantBits());
|
||||||
|
return buffer.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull UUID fromPrimitive(byte @NotNull [] bytes, @NotNull PersistentDataAdapterContext context)
|
||||||
|
{
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||||
|
long leastBits = buffer.getLong();
|
||||||
|
long mostBits = buffer.getLong();
|
||||||
|
return new UUID(mostBits, leastBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ public abstract class Level
|
||||||
@WantsListen(phase = WantsListen.Target.Always)
|
@WantsListen(phase = WantsListen.Target.Always)
|
||||||
public static class Events implements Listener
|
public static class Events implements Listener
|
||||||
{
|
{
|
||||||
|
// FIXME: For the 'default' world, you need to remove it because
|
||||||
|
// we can't register it at the same time it gets loaded... (API limitation)
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onChunkLoad(final ChunkLoadEvent ev)
|
public void onChunkLoad(final ChunkLoadEvent ev)
|
||||||
{
|
{
|
||||||
|
@ -88,6 +90,15 @@ public abstract class Level
|
||||||
public void onWorldInit(final WorldInitEvent ev)
|
public void onWorldInit(final WorldInitEvent ev)
|
||||||
{
|
{
|
||||||
ev.getWorld().setKeepSpawnInMemory(false);
|
ev.getWorld().setKeepSpawnInMemory(false);
|
||||||
|
final Level level = LevelFactory.get(ev.getWorld().getName());
|
||||||
|
if (level == null) return;
|
||||||
|
|
||||||
|
if (!level.initialized)
|
||||||
|
{
|
||||||
|
level.handle = Bukkit.getWorld(level.getWorldName());
|
||||||
|
level.postWorld();
|
||||||
|
level.initialized = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
package org.ef3d0c3e.sheepwars.level.lobby;
|
package org.ef3d0c3e.sheepwars.level.lobby;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import com.github.retrooper.packetevents.manager.player.PlayerManager;
|
||||||
|
import com.github.retrooper.packetevents.protocol.npc.NPC;
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.Location;
|
||||||
|
import com.github.retrooper.packetevents.util.Vector3d;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
@ -14,6 +21,8 @@ import org.bukkit.inventory.PlayerInventory;
|
||||||
import org.ef3d0c3e.sheepwars.events.*;
|
import org.ef3d0c3e.sheepwars.events.*;
|
||||||
import org.ef3d0c3e.sheepwars.game.Game;
|
import org.ef3d0c3e.sheepwars.game.Game;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@WantsListen(phase = WantsListen.Target.Lobby)
|
@WantsListen(phase = WantsListen.Target.Lobby)
|
||||||
public class LobbyEvents implements Listener
|
public class LobbyEvents implements Listener
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.ef3d0c3e.sheepwars.SheepWars;
|
||||||
import org.ef3d0c3e.sheepwars.level.Level;
|
import org.ef3d0c3e.sheepwars.level.Level;
|
||||||
import org.ef3d0c3e.sheepwars.level.VoidBiomeProvider;
|
import org.ef3d0c3e.sheepwars.level.VoidBiomeProvider;
|
||||||
import org.ef3d0c3e.sheepwars.level.VoidChunkGenerator;
|
import org.ef3d0c3e.sheepwars.level.VoidChunkGenerator;
|
||||||
|
import org.ef3d0c3e.sheepwars.npc.NPCFactory;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
@ -54,13 +55,13 @@ public class LobbyLevel extends Level
|
||||||
HologramFactory.register(hologram);
|
HologramFactory.register(hologram);
|
||||||
|
|
||||||
skinNpc = new SkinDisplayNPC(config.SKIN.getLocation(getHandle()));
|
skinNpc = new SkinDisplayNPC(config.SKIN.getLocation(getHandle()));
|
||||||
NPCManager.register(skinNpc);
|
NPCFactory.register(skinNpc);
|
||||||
|
|
||||||
teamNpc = new TeamNPC(config.TEAM.getLocation(getHandle()));
|
teamNpc = new TeamNPC(config.TEAM.getLocation(getHandle()));
|
||||||
NPCManager.register(teamNpc);
|
NPCFactory.register(teamNpc);
|
||||||
|
|
||||||
kitNpc = new KitNPC(config.KIT.getLocation(getHandle()));
|
kitNpc = new KitNPC(config.KIT.getLocation(getHandle()));
|
||||||
NPCManager.register(kitNpc);
|
NPCFactory.register(kitNpc);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
135
core/src/main/java/org/ef3d0c3e/sheepwars/npc/NPCFactory.java
Normal file
135
core/src/main/java/org/ef3d0c3e/sheepwars/npc/NPCFactory.java
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.npc;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType;
|
||||||
|
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||||
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
import com.comphenix.protocol.events.PacketListener;
|
||||||
|
import com.comphenix.protocol.injector.GamePhase;
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||||
|
import com.comphenix.protocol.wrappers.WrappedEnumEntityUseAction;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.ef3d0c3e.sheepwars.SheepWars;
|
||||||
|
import org.ef3d0c3e.sheepwars.events.CPlayerJoinEvent;
|
||||||
|
import org.ef3d0c3e.sheepwars.events.WantsListen;
|
||||||
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class NPCFactory
|
||||||
|
{
|
||||||
|
private static HashMap<Integer, PlayerNPC> registry = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers NPC into the registry
|
||||||
|
* @param npc NPC to register (does nothing if NPC's networkId is already registered)
|
||||||
|
*/
|
||||||
|
public static void register(final @NonNull PlayerNPC npc)
|
||||||
|
{
|
||||||
|
registry.put(npc.getNetworkId(), npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters NPC from the registry
|
||||||
|
* @param npc NPC to unregister
|
||||||
|
* @return npc on successful unregister, null otherwise
|
||||||
|
*/
|
||||||
|
public static @Nullable
|
||||||
|
PlayerNPC unregsiter(final @NonNull PlayerNPC npc)
|
||||||
|
{
|
||||||
|
return registry.remove(npc.getNetworkId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets NPC from registry using network id
|
||||||
|
* @param eid's NPC network id
|
||||||
|
* @return NPC if found, null otherwise
|
||||||
|
*/
|
||||||
|
public static @Nullable PlayerNPC get(int eid)
|
||||||
|
{
|
||||||
|
return registry.get(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WantsListen(phase = WantsListen.Target.Always)
|
||||||
|
public static class NPCListener implements Listener
|
||||||
|
{
|
||||||
|
// TODO..., on chunk load request [something...]
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(final CPlayerJoinEvent ev)
|
||||||
|
{
|
||||||
|
final CPlayer cp = ev.getPlayer();
|
||||||
|
for (final PlayerNPC npc : registry.values())
|
||||||
|
{
|
||||||
|
if (!npc.sendPredicate(cp)) continue;
|
||||||
|
|
||||||
|
npc.sendInfo(cp, false);
|
||||||
|
npc.send(cp);
|
||||||
|
npc.sendNametag(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@WantsListen(phase = WantsListen.Target.Always)
|
||||||
|
public static class NPCPacketListener implements PacketListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onPacketSending(final PacketEvent packetEvent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketReceiving(final PacketEvent packetEvent)
|
||||||
|
{
|
||||||
|
final PacketContainer interact = packetEvent.getPacket();
|
||||||
|
final PlayerNPC npc = get(interact.getIntegers().read(0));
|
||||||
|
if (npc == null) return;
|
||||||
|
|
||||||
|
final CPlayer cp = CPlayer.get(packetEvent.getPlayer());
|
||||||
|
final Location npcLoc = npc.getLocation(cp);
|
||||||
|
if (!npcLoc.getWorld().equals(cp.getHandle().getWorld())) return; // Fake packet check
|
||||||
|
|
||||||
|
final double distSq = cp.getHandle().getLocation().distanceSquared(npcLoc);
|
||||||
|
if (distSq >= 49.0) return; // Reach check
|
||||||
|
|
||||||
|
|
||||||
|
final WrappedEnumEntityUseAction action = interact.getEnumEntityUseActions().read(0);
|
||||||
|
if (action.getAction().equals(EnumWrappers.EntityUseAction.INTERACT))
|
||||||
|
{
|
||||||
|
npc.onInteract(
|
||||||
|
cp,
|
||||||
|
action.getHand(),
|
||||||
|
interact.getBooleans().read(0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListeningWhitelist getSendingWhitelist()
|
||||||
|
{
|
||||||
|
return ListeningWhitelist.EMPTY_WHITELIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ListeningWhitelist listeningWhitelist = ListeningWhitelist.newBuilder()
|
||||||
|
.gamePhase(GamePhase.PLAYING)
|
||||||
|
.types(PacketType.Play.Client.USE_ENTITY)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListeningWhitelist getReceivingWhitelist()
|
||||||
|
{
|
||||||
|
return listeningWhitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Plugin getPlugin()
|
||||||
|
{
|
||||||
|
return SheepWars.getPlugin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
214
core/src/main/java/org/ef3d0c3e/sheepwars/npc/PlayerNPC.java
Normal file
214
core/src/main/java/org/ef3d0c3e/sheepwars/npc/PlayerNPC.java
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.npc;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||||
|
import com.github.retrooper.packetevents.protocol.npc.NPC;
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||||
|
import com.github.retrooper.packetevents.util.Vector3d;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
||||||
|
import com.mojang.authlib.properties.Property;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.ef3d0c3e.sheepwars.packets.EntityMetadata;
|
||||||
|
import org.ef3d0c3e.sheepwars.packets.PlayerMetadata;
|
||||||
|
import org.ef3d0c3e.sheepwars.player.CPlayer;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public abstract class PlayerNPC
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The NPC's unique id
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private final UUID uniqueId;
|
||||||
|
@Getter
|
||||||
|
private final int networkId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param networkId NPC (unique) network id
|
||||||
|
*/
|
||||||
|
public PlayerNPC(final int networkId)
|
||||||
|
{
|
||||||
|
uniqueId = UUID.randomUUID();
|
||||||
|
this.networkId = networkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract @NonNull String getName();
|
||||||
|
protected abstract @NonNull List<Component> getNametag(final @NonNull CPlayer cp);
|
||||||
|
protected abstract @NonNull Property getTextures(final @NonNull CPlayer cp);
|
||||||
|
protected abstract @NonNull Location getLocation(final @NonNull CPlayer cp);
|
||||||
|
protected abstract boolean sendPredicate(final @NonNull CPlayer cp);
|
||||||
|
protected @NonNull List<EntityData> getMetadata(final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
return List.of(
|
||||||
|
new PlayerMetadata.SkinParts()
|
||||||
|
.all()
|
||||||
|
.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the NPC (resend metadata, skin profile etc...)
|
||||||
|
* @param cp Player to update NPC for
|
||||||
|
*/
|
||||||
|
protected void update(final @NonNull CPlayer cp) {}
|
||||||
|
// TODO: add more methods, such as inventory, potion effects...
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when NPC is interacted with (Right click)
|
||||||
|
* @param cp Player that interacted
|
||||||
|
* @param hand Interacted hand
|
||||||
|
* @param sneaking Whether player is sneaking
|
||||||
|
*/
|
||||||
|
protected abstract void onInteract(final @NonNull CPlayer cp, final EnumWrappers.Hand hand, boolean sneaking);
|
||||||
|
|
||||||
|
protected void send(final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
// Spawn packet
|
||||||
|
final Location loc = getLocation(cp);
|
||||||
|
final WrapperPlayServerSpawnEntity spawn = new WrapperPlayServerSpawnEntity(
|
||||||
|
networkId, Optional.of(uniqueId),
|
||||||
|
EntityTypes.PLAYER,
|
||||||
|
new Vector3d(loc.getX(), loc.getY(), loc.getZ()),
|
||||||
|
loc.getPitch(), loc.getYaw(), loc.getYaw(),
|
||||||
|
0,
|
||||||
|
Optional.empty()
|
||||||
|
);
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
final WrapperPlayServerEntityMetadata playerMeta = new WrapperPlayServerEntityMetadata(
|
||||||
|
networkId,
|
||||||
|
getMetadata(cp)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Team packet (to hide the nametag)
|
||||||
|
final WrapperPlayServerTeams team = new WrapperPlayServerTeams(
|
||||||
|
"NPC-" + getName(),
|
||||||
|
WrapperPlayServerTeams.TeamMode.CREATE,
|
||||||
|
new WrapperPlayServerTeams.ScoreBoardTeamInfo(
|
||||||
|
Component.empty(),
|
||||||
|
null, null,
|
||||||
|
WrapperPlayServerTeams.NameTagVisibility.NEVER,
|
||||||
|
WrapperPlayServerTeams.CollisionRule.NEVER,
|
||||||
|
NamedTextColor.WHITE,
|
||||||
|
WrapperPlayServerTeams.OptionData.NONE
|
||||||
|
),
|
||||||
|
Collections.singletonList("NPC-" + getName())
|
||||||
|
);
|
||||||
|
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), spawn);
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), playerMeta);
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), team);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes NPC nametag for player
|
||||||
|
* @note {@see sendNametag(cp)} should be called after this method
|
||||||
|
* @param cp Player
|
||||||
|
* @param number Number of nametags to remove
|
||||||
|
*/
|
||||||
|
protected void removeNametag(final @NonNull CPlayer cp, int number)
|
||||||
|
{
|
||||||
|
final int eids[] = new int[number];
|
||||||
|
for (int i = 0; i < number; ++i) eids[i] = getNetworkId() + i + 1;
|
||||||
|
|
||||||
|
final WrapperPlayServerDestroyEntities remove = new WrapperPlayServerDestroyEntities();
|
||||||
|
remove.setEntityIds(eids);
|
||||||
|
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendNametag(final @NonNull CPlayer cp)
|
||||||
|
{
|
||||||
|
final List<Component> tags = getNametag(cp);
|
||||||
|
int i = 0;
|
||||||
|
for (final Component tag : tags)
|
||||||
|
{
|
||||||
|
// Spawn
|
||||||
|
final Location loc = getLocation(cp);
|
||||||
|
final WrapperPlayServerSpawnEntity spawn = new WrapperPlayServerSpawnEntity(
|
||||||
|
networkId+i+1, Optional.of(UUID.randomUUID()),
|
||||||
|
EntityTypes.ARMOR_STAND,
|
||||||
|
new Vector3d(loc.getX(), loc.getY()+(tags.size()-i-1)*0.3, loc.getZ()),
|
||||||
|
0.f, 0.f, 0.f,
|
||||||
|
0,
|
||||||
|
Optional.empty()
|
||||||
|
);
|
||||||
|
// Metadata
|
||||||
|
final WrapperPlayServerEntityMetadata meta = new WrapperPlayServerEntityMetadata(
|
||||||
|
networkId+i+1,
|
||||||
|
Arrays.asList(
|
||||||
|
new EntityMetadata.Status()
|
||||||
|
.isInvisible(true)
|
||||||
|
.into(),
|
||||||
|
new EntityMetadata.NoGravity(true).into(),
|
||||||
|
new EntityMetadata.CustomNameVisible(true).into(),
|
||||||
|
new EntityMetadata.CustomName(tag).into()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), spawn);
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), meta);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends player info (profile)
|
||||||
|
* @note Setting {@ref resend} to true will send a destroy packet and then resend the player packet
|
||||||
|
* @param cp Player to send to
|
||||||
|
* @param resend If true, will send a {@code PlayerInfoRemove} packet first
|
||||||
|
*/
|
||||||
|
protected void sendInfo(final @NonNull CPlayer cp, boolean resend)
|
||||||
|
{
|
||||||
|
// Remove any previously sent NPC
|
||||||
|
if (resend)
|
||||||
|
{
|
||||||
|
final WrapperPlayServerPlayerInfoRemove infoRemove = new WrapperPlayServerPlayerInfoRemove(getUniqueId());
|
||||||
|
final WrapperPlayServerDestroyEntities remove = new WrapperPlayServerDestroyEntities(networkId);
|
||||||
|
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), infoRemove);
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Property texture = getTextures(cp);
|
||||||
|
final WrapperPlayServerPlayerInfoUpdate info = new WrapperPlayServerPlayerInfoUpdate(
|
||||||
|
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
|
||||||
|
new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
|
||||||
|
new UserProfile(
|
||||||
|
uniqueId,
|
||||||
|
"NPC-" + getName(),
|
||||||
|
List.of(
|
||||||
|
new TextureProperty(
|
||||||
|
texture.name(),
|
||||||
|
texture.value(),
|
||||||
|
texture.signature()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
GameMode.SURVIVAL,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
PacketEvents.getAPI().getPlayerManager().sendPacket(cp.getHandle(), info);
|
||||||
|
|
||||||
|
// Also resend nametag
|
||||||
|
if (resend)
|
||||||
|
send(cp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.packets;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class ArmorStandMetadata {
|
||||||
|
public static class Status implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
15,
|
||||||
|
EntityDataTypes.BYTE,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte value;
|
||||||
|
|
||||||
|
public Status() {
|
||||||
|
this.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isSmall(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status hasArms(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b10 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status hasBasePlate(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b100 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isMarker(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.packets;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class EntityMetadata {
|
||||||
|
public static class Status implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
0,
|
||||||
|
EntityDataTypes.BYTE,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte value;
|
||||||
|
|
||||||
|
public Status() {
|
||||||
|
this.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status onFire(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isCrouching(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b10 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isSprinting(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isSwimming(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b10000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isInvisible(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b100000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isGlowing(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1000000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status isElytraFlying(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b10000000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class AirTicks implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
1,
|
||||||
|
EntityDataTypes.INT,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class CustomName implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
2,
|
||||||
|
EntityDataTypes.OPTIONAL_ADV_COMPONENT,
|
||||||
|
Optional.of(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class CustomNameVisible implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
3,
|
||||||
|
EntityDataTypes.BOOLEAN,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Silent implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
4,
|
||||||
|
EntityDataTypes.BOOLEAN,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class NoGravity implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
5,
|
||||||
|
EntityDataTypes.BOOLEAN,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.packets;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
|
||||||
|
interface IntoEntityData {
|
||||||
|
EntityData into();
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.packets;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
|
import com.comphenix.protocol.events.PacketListener;
|
||||||
|
import org.ef3d0c3e.sheepwars.SheepWars;
|
||||||
|
import org.ef3d0c3e.sheepwars.events.WantsListen;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class PacketListenerFactory
|
||||||
|
{
|
||||||
|
static private HashSet<Class<? extends PacketListener>> registrable = new HashSet<>();
|
||||||
|
static private HashSet<PacketListener> registered = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
|
public static void create() throws Exception
|
||||||
|
{
|
||||||
|
final Reflections refl = new Reflections("org.ef3d0c3e.sheepwars");
|
||||||
|
final Set<Class<? extends PacketListener>> classes = refl.getSubTypesOf(PacketListener.class);
|
||||||
|
for (final Class<? extends PacketListener> clz : classes)
|
||||||
|
{
|
||||||
|
if (clz.getAnnotation(WantsListen.class) == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
registrable.add(clz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all listeners for current phase
|
||||||
|
* Unregisters uneeded listeners
|
||||||
|
* @param phase Current phase
|
||||||
|
*/
|
||||||
|
public static void update(final WantsListen.Target phase)
|
||||||
|
{
|
||||||
|
// Un register
|
||||||
|
for (Iterator<PacketListener> it = registered.iterator(); it.hasNext();)
|
||||||
|
{
|
||||||
|
final PacketListener listener = it.next();
|
||||||
|
final WantsListen.Target target = listener.getClass().getAnnotation(WantsListen.class).phase();
|
||||||
|
|
||||||
|
if (target.isCompatible(phase)) continue;
|
||||||
|
|
||||||
|
ProtocolLibrary.getProtocolManager().removePacketListener(listener);
|
||||||
|
it.remove();
|
||||||
|
SheepWars.debugMessage("Unregistered " + listener.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register
|
||||||
|
for (final Class<? extends PacketListener> clz : registrable)
|
||||||
|
{
|
||||||
|
final WantsListen.Target target = clz.getAnnotation(WantsListen.class).phase();
|
||||||
|
|
||||||
|
if (!target.isCompatible(phase)) continue;
|
||||||
|
|
||||||
|
boolean shouldRegister = true;
|
||||||
|
// Check if not already registered
|
||||||
|
for (final PacketListener l : registered)
|
||||||
|
{
|
||||||
|
if (!l.getClass().equals(clz)) continue;
|
||||||
|
|
||||||
|
shouldRegister = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!shouldRegister) continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final PacketListener l = clz.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
|
registered.add(l);
|
||||||
|
ProtocolLibrary.getProtocolManager().addPacketListener(l);
|
||||||
|
SheepWars.debugMessage("Registered " + l.getClass().getName());
|
||||||
|
}
|
||||||
|
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package org.ef3d0c3e.sheepwars.packets;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class PlayerMetadata {
|
||||||
|
public static class SkinParts implements IntoEntityData {
|
||||||
|
@Override
|
||||||
|
public EntityData into() {
|
||||||
|
return new EntityData(
|
||||||
|
17,
|
||||||
|
EntityDataTypes.BYTE,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte value;
|
||||||
|
|
||||||
|
public SkinParts() {
|
||||||
|
this.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts cape(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts jacket(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b10 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts leftSleeve(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b100 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts rightSleeve(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts leftPants(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b10000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts rightPants(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b100000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts hat(boolean v) {
|
||||||
|
value = (byte)(value | (v ? 0b1000000 : 0b0));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinParts all() {
|
||||||
|
value = (byte)0xFF;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,6 @@ public class WrapperFactory
|
||||||
{
|
{
|
||||||
// Build version string (e.g: "1.20.2" -> "1_20_R2")
|
// Build version string (e.g: "1.20.2" -> "1_20_R2")
|
||||||
final String bukkitVersion = Bukkit.getVersion();
|
final String bukkitVersion = Bukkit.getVersion();
|
||||||
Bukkit.getConsoleSender().sendMessage("version=" + bukkitVersion);
|
|
||||||
Matcher matcher = Pattern.compile("\\(MC: (?<version>\\d)\\.(?<major>\\d+)(?:\\.(?<minor>\\d+))?\\)").matcher(bukkitVersion);
|
Matcher matcher = Pattern.compile("\\(MC: (?<version>\\d)\\.(?<major>\\d+)(?:\\.(?<minor>\\d+))?\\)").matcher(bukkitVersion);
|
||||||
if (!matcher.find()) throw new RuntimeException("Could not determine minecraft version from Bukkit version: `" + bukkitVersion + "`");
|
if (!matcher.find()) throw new RuntimeException("Could not determine minecraft version from Bukkit version: `" + bukkitVersion + "`");
|
||||||
String version;
|
String version;
|
||||||
|
|
|
@ -2,7 +2,7 @@ name: SheepWars
|
||||||
version: '2.0α'
|
version: '2.0α'
|
||||||
main: org.ef3d0c3e.sheepwars.SheepWars
|
main: org.ef3d0c3e.sheepwars.SheepWars
|
||||||
api-version: 1.21
|
api-version: 1.21
|
||||||
depend: [ ProtocolLib, WorldEdit ]
|
depend: [ ProtocolLib, WorldEdit, packetevents ]
|
||||||
authors: [ ef3d0c3e ]
|
authors: [ ef3d0c3e ]
|
||||||
load: STARTUP
|
load: STARTUP
|
||||||
description: The SheepWars minigame, for free, forever
|
description: The SheepWars minigame, for free, forever
|
||||||
|
|
26
dist/dependency-reduced-pom.xml
vendored
26
dist/dependency-reduced-pom.xml
vendored
|
@ -9,6 +9,14 @@
|
||||||
<artifactId>SheepWars-dist</artifactId>
|
<artifactId>SheepWars-dist</artifactId>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<finalName>SheepWars</finalName>
|
||||||
|
<outputDirectory>/home/baraquiel/Programming/Minecraft/Sheepwars211/plugins</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.6.0</version>
|
<version>3.6.0</version>
|
||||||
|
@ -22,21 +30,21 @@
|
||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<relocations>
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.github.retrooper.packetevents</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.api</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>io.github.retrooper.packetevents</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.impl</shadedPattern>
|
||||||
|
</relocation>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>fr.mrmicky.fastboard</pattern>
|
<pattern>fr.mrmicky.fastboard</pattern>
|
||||||
<shadedPattern>org.ef3d0c3e.sheepwars.fastboard</shadedPattern>
|
<shadedPattern>org.ef3d0c3e.lib.fastboard</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
</relocations>
|
</relocations>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>2.3.2</version>
|
|
||||||
<configuration>
|
|
||||||
<finalName>SheepWars</finalName>
|
|
||||||
<outputDirectory>/home/baraquiel/Programming/Minecraft/Sheepwars211/plugins</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
32
dist/pom.xml
vendored
32
dist/pom.xml
vendored
|
@ -13,6 +13,15 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<finalName>SheepWars</finalName>
|
||||||
|
<outputDirectory>/home/baraquiel/Programming/Minecraft/Sheepwars211/plugins</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
@ -27,22 +36,21 @@
|
||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<relocations>
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.github.retrooper.packetevents</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.api</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>io.github.retrooper.packetevents</pattern>
|
||||||
|
<shadedPattern>org.ef3d0c3e.lib.packetevents.impl</shadedPattern>
|
||||||
|
</relocation>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>fr.mrmicky.fastboard</pattern>
|
<pattern>fr.mrmicky.fastboard</pattern>
|
||||||
<shadedPattern>org.ef3d0c3e.sheepwars.fastboard</shadedPattern>
|
<shadedPattern>org.ef3d0c3e.lib.fastboard</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
</relocations>
|
</relocations>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>2.3.2</version>
|
|
||||||
<configuration>
|
|
||||||
<finalName>SheepWars</finalName>
|
|
||||||
<outputDirectory>/home/baraquiel/Programming/Minecraft/Sheepwars211/plugins</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -54,10 +62,10 @@
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 1.21.1 -->
|
<!-- 1.21.0 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ef3d0c3e.sheepwars</groupId>
|
<groupId>org.ef3d0c3e.sheepwars</groupId>
|
||||||
<artifactId>SheepWars-spigot-1.21.1</artifactId>
|
<artifactId>SheepWars-spigot-1.21.0</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
Binary file not shown.
10
pom.xml
10
pom.xml
|
@ -12,7 +12,7 @@
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>spigot-1.21.1</module>
|
<module>spigot-1.21.0</module>
|
||||||
<module>dist</module>
|
<module>dist</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
@ -24,6 +24,10 @@
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>codemc-releases</id>
|
||||||
|
<url>https://repo.codemc.io/repository/maven-snapshots/</url>
|
||||||
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>central</id>
|
<id>central</id>
|
||||||
<url>https://repo1.maven.org/maven2/</url>
|
<url>https://repo1.maven.org/maven2/</url>
|
||||||
|
@ -36,10 +40,6 @@
|
||||||
<id>sonatype</id>
|
<id>sonatype</id>
|
||||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
|
||||||
<id>lukasalt-repo</id>
|
|
||||||
<url>https://repo.lukasa.lt/repository/maven-public/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>SheepWars-spigot-1.21.1</artifactId>
|
<artifactId>SheepWars-spigot-1.21.0</artifactId>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>22</java.version>
|
<java.version>22</java.version>
|
|
@ -1,4 +1,4 @@
|
||||||
package org.ef3d0c3e.sheepwars.v1_21_R1;
|
package org.ef3d0c3e.sheepwars.v1_21_R0;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.protocol.PacketType;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
Loading…
Reference in a new issue