add java 8 support (fixes #33), change folia support, restructure project

This commit is contained in:
Pyrbu 2023-05-03 07:24:34 +01:00
parent b3c9b246c7
commit 26105d514c
24 changed files with 386 additions and 102 deletions

@ -1,11 +1,10 @@
# ZNPCsPlus # ZNPCsPlus
[ZNPCsPlus](https://www.spigotmc.org/resources/znpcsplus.109380/) is an unofficial fork of the popular NPC plugin ZNPCs written with the Spigot/Bukkit API originally made by [ZNPCsPlus](https://www.spigotmc.org/resources/znpcsplus.109380/) is an remake of the popular NPC plugin ZNPCs written with the Spigot/Bukkit API originally made by
gonalez/ZNetwork. This fork was made because the original maintainer of the plugin decided to announce that he was gonalez/ZNetwork. This project was originally started because the maintainer of ZNPCs decided to announce that he was
[dropping support for the plugin](https://media.discordapp.net/attachments/1093914615873806477/1098409384855474237/znpc.png) [dropping support for the plugin](https://media.discordapp.net/attachments/1093914615873806477/1098409384855474237/znpc.png).
in the original project's [official discord server](https://discord.com/invite/RhNMH4T).
### Dependencies ### Dependencies
- Java 17 - Java 8
- Spigot 1.8 - 1.19.4 - Spigot 1.8 - 1.19.4
- PlaceholderAPI (OPTIONAL) - PlaceholderAPI (OPTIONAL)
@ -15,7 +14,10 @@ If you're using a Minecraft version that rejects Java 17 use the `-DPaper.Ignore
This fork makes several improvements over the original including: This fork makes several improvements over the original including:
- More performance-conscious code - More performance-conscious code
- Latest version support (1.19.4) - Latest version support (1.19.4)
- Fixes for long-running issues of the original plugin (ones that the original maintainer refused to even acknowledge) - Fixes for long-running issues of the original plugin
- Better stability
- Support for multiple different storage options (WIP)
- Better command system (WIP)
## Found a bug? ## Found a bug?
Open an issue in the GitHub [issue tracker](https://github.com/Pyrbu/ZNPCsPlus/issues) Open an issue in the GitHub [issue tracker](https://github.com/Pyrbu/ZNPCsPlus/issues)

@ -1,4 +1,5 @@
plugins { plugins {
id "java"
id "maven-publish" id "maven-publish"
} }

@ -86,7 +86,7 @@ public class NPCType {
} }
public Builder addProperties(EntityProperty<?>... properties) { public Builder addProperties(EntityProperty<?>... properties) {
allowedProperties.addAll(List.of(properties)); allowedProperties.addAll(Arrays.asList(properties));
return this; return this;
} }
@ -108,7 +108,7 @@ public class NPCType {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9))
allowedProperties.add(EntityProperty.GLOW); allowedProperties.add(EntityProperty.GLOW);
} }
return new NPCType(name, type, hologramOffset, Set.copyOf(allowedProperties)); return new NPCType(name, type, hologramOffset, new HashSet<>(allowedProperties));
} }
} }
} }

@ -1,27 +1,11 @@
plugins { subprojects {
id "java"
id "com.github.johnrengelman.shadow" version "8.1.1"
id "xyz.jpenilla.run-paper" version "2.0.1"
}
dependencies {
implementation project(path: ":spigot", configuration: "shadow")
implementation project(":api")
implementation project(":folia")
}
runServer {
minecraftVersion "1.19.4"
}
allprojects {
apply plugin: "java" apply plugin: "java"
group "lol.pyr" group "lol.pyr"
version "2.0.0" version "2.0.0"
compileJava { compileJava {
options.release.set(17) options.release.set(8)
} }
repositories { repositories {
@ -32,6 +16,9 @@ allprojects {
maven { maven {
url "https://repo.codemc.io/repository/maven-snapshots/" url "https://repo.codemc.io/repository/maven-snapshots/"
} }
maven {
url "https://libraries.minecraft.net"
}
maven { maven {
url "https://repo.papermc.io/repository/maven-public/" url "https://repo.papermc.io/repository/maven-public/"
} }
@ -46,6 +33,3 @@ allprojects {
} }
} }
} }
tasks.assemble.dependsOn shadowJar
tasks.compileJava.dependsOn clean

@ -1,3 +0,0 @@
dependencies {
compileOnly "dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT"
}

@ -1,27 +0,0 @@
package lol.pyr.znpcsplus.scheduling;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.TimeUnit;
public class FoliaScheduler extends TaskScheduler {
public FoliaScheduler(Plugin plugin) {
super(plugin);
}
@Override
public void runAsync(Runnable runnable) {
Bukkit.getAsyncScheduler().runNow(plugin, task -> runnable.run());
}
@Override
public void runLaterAsync(Runnable runnable, long ticks) {
Bukkit.getAsyncScheduler().runDelayed(plugin, task -> runnable.run(), ticks * 50, TimeUnit.MILLISECONDS);
}
@Override
public void runDelayedTimerAsync(Runnable runnable, long delay, long ticks) {
Bukkit.getAsyncScheduler().runAtFixedRate(plugin, task -> runnable.run(), delay * 50, ticks * 50, TimeUnit.MILLISECONDS);
}
}

@ -1,3 +1,3 @@
rootProject.name = "ZNPCsPlus" rootProject.name = "ZNPCsPlus"
include "api", "spigot", "folia" include "api", "spigot"

@ -1,12 +1,22 @@
plugins { plugins {
id "java"
id "com.github.johnrengelman.shadow" version "8.1.1" id "com.github.johnrengelman.shadow" version "8.1.1"
id "xyz.jpenilla.run-paper" version "2.0.1"
}
runServer {
minecraftVersion "1.19.4"
}
processResources {
expand("version": version)
} }
dependencies { dependencies {
compileOnly "org.spigotmc:spigot-api:1.19.4-R0.1-SNAPSHOT" compileOnly "org.spigotmc:spigot-api:1.19.4-R0.1-SNAPSHOT"
compileOnly "me.clip:placeholderapi:2.11.1" compileOnly "me.clip:placeholderapi:2.11.1"
compileOnly "com.mojang:authlib:3.4.40" compileOnly "com.mojang:authlib:1.5.21"
compileOnly "com.mojang:datafixerupper:4.0.26" compileOnly "com.mojang:datafixerupper:4.0.26"
implementation "commons-io:commons-io:2.11.0" implementation "commons-io:commons-io:2.11.0"
@ -19,13 +29,13 @@ dependencies {
implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1"
implementation "lol.pyr:director-adventure:2.0.1" implementation "lol.pyr:director-adventure:2.0.1"
implementation project(":api")
compileOnly project(":api")
compileOnly project(":folia")
} }
shadowJar { shadowJar {
archivesBaseName = "ZNPCsPlus"
archiveClassifier.set "" archiveClassifier.set ""
relocate "org.bstats", "lol.pyr.znpcsplus.lib.bstats" relocate "org.bstats", "lol.pyr.znpcsplus.lib.bstats"
relocate "org.apache.commons.io", "lol.pyr.znpcsplus.lib.commonsio" relocate "org.apache.commons.io", "lol.pyr.znpcsplus.lib.commonsio"
relocate "me.robertlit.spigotresources", "lol.pyr.znpcsplus.lib.spigotresources" relocate "me.robertlit.spigotresources", "lol.pyr.znpcsplus.lib.spigotresources"
@ -42,4 +52,6 @@ shadowJar {
relocate "lol.pyr.director", "lol.pyr.znpcsplus.lib.command" relocate "lol.pyr.director", "lol.pyr.znpcsplus.lib.command"
minimize() minimize()
} }
tasks.assemble.dependsOn shadowJar

@ -15,6 +15,11 @@ public class ReflectionBuilder {
private Class<?> expectType; private Class<?> expectType;
private boolean strict = true; private boolean strict = true;
public ReflectionBuilder(Class<?> clazz) {
this("");
withClassName(clazz);
}
public ReflectionBuilder(String reflectionPackage) { public ReflectionBuilder(String reflectionPackage) {
this(reflectionPackage, "", "", null); this(reflectionPackage, "", "", null);
} }

@ -5,40 +5,92 @@ import io.github.znetworkw.znpcservers.reflection.types.ClassReflection;
import io.github.znetworkw.znpcservers.reflection.types.FieldReflection; import io.github.znetworkw.znpcservers.reflection.types.FieldReflection;
import io.github.znetworkw.znpcservers.reflection.types.MethodReflection; import io.github.znetworkw.znpcservers.reflection.types.MethodReflection;
import io.github.znetworkw.znpcservers.utility.Utils; import io.github.znetworkw.znpcservers.utility.Utils;
import lol.pyr.znpcsplus.util.FoliaUtil;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
/** /**
* Class containing all of the lazy-loaded reflections that the plugin * Class containing all of the lazy-loaded reflections that the plugin
* uses to accessinaccessible things from the server jar. * uses to accessinaccessible things from the server jar.
*/ */
public final class Reflections { public final class Reflections {
public static final Class<?> ENTITY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_CLASS = new ClassReflection(
.withClassName("Entity")).get(); new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName("Entity")).get();
public static final Class<?> ENTITY_HUMAN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_HUMAN_CLASS = new ClassReflection(
.withSubClass("player") new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName("EntityHuman")).get(); .withSubClass("player")
.withClassName("EntityHuman")).get();
public static final ReflectionLazyLoader<Method> GET_PROFILE_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final ReflectionLazyLoader<Method> GET_PROFILE_METHOD = new MethodReflection(
.withClassName(ENTITY_HUMAN_CLASS) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withExpectResult(GameProfile.class)); .withClassName(ENTITY_HUMAN_CLASS)
.withExpectResult(GameProfile.class));
public static final ReflectionLazyLoader<Method> GET_HANDLE_PLAYER_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) public static final ReflectionLazyLoader<Method> GET_HANDLE_PLAYER_METHOD = new MethodReflection(
.withClassName("entity.CraftPlayer").withClassName("entity.CraftHumanEntity") new ReflectionBuilder(ReflectionPackage.BUKKIT)
.withMethodName("getHandle")); .withClassName("entity.CraftPlayer").withClassName("entity.CraftHumanEntity")
.withMethodName("getHandle"));
public static final FieldReflection.ValueModifier<Integer> ENTITY_ID_MODIFIER = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final FieldReflection.ValueModifier<Integer> ENTITY_ID_MODIFIER = new FieldReflection(
.withClassName(ENTITY_CLASS) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withFieldName("entityCount") .withClassName(ENTITY_CLASS)
.setStrict(!Utils.versionNewer(14))).staticValueModifier(int.class); .withFieldName("entityCount")
.setStrict(!Utils.versionNewer(14))).staticValueModifier(int.class);
public static final ReflectionLazyLoader<AtomicInteger> ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final ReflectionLazyLoader<AtomicInteger> ATOMIC_ENTITY_ID_FIELD = new FieldReflection(
.withClassName(ENTITY_CLASS) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withFieldName("entityCount") .withClassName(ENTITY_CLASS)
.withFieldName("d") .withFieldName("entityCount")
.withFieldName("c") .withFieldName("d")
.withExpectResult(AtomicInteger.class) .withFieldName("c")
.setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); .withExpectResult(AtomicInteger.class)
.setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class);
public static final Class<?> ASYNC_SCHEDULER_CLASS = new ClassReflection(
new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler")
.withClassName("AsyncScheduler")
.setStrict(FoliaUtil.isFolia())).get();
public static final Class<?> SCHEDULED_TASK_CLASS = new ClassReflection(
new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler")
.withClassName("ScheduledTask")
.setStrict(FoliaUtil.isFolia())).get();
public static final ReflectionLazyLoader<Method> FOLIA_GET_ASYNC_SCHEDULER = new MethodReflection(
new ReflectionBuilder(Bukkit.class)
.withMethodName("getAsyncScheduler")
.withExpectResult(ASYNC_SCHEDULER_CLASS)
.setStrict(FoliaUtil.isFolia()));
public static final ReflectionLazyLoader<Method> FOLIA_RUN_NOW = new MethodReflection(
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runNow")
.withParameterTypes(Plugin.class, Consumer.class)
.withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia()));
public static final ReflectionLazyLoader<Method> FOLIA_RUN_DELAYED = new MethodReflection(
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runDelayed")
.withParameterTypes(Plugin.class, Consumer.class, long.class, TimeUnit.class)
.withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia()));
public static final ReflectionLazyLoader<Method> FOLIA_RUN_AT_FIXED_RATE = new MethodReflection(
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runAtFixedRate")
.withParameterTypes(Plugin.class, Consumer.class, long.class, long.class, TimeUnit.class)
.withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia()));
} }
// Bukkit.getAsyncScheduler().runNow(plugin, task -> runnable.run());
// Bukkit.getAsyncScheduler().runDelayed(plugin, task -> runnable.run(), ticks * 50, TimeUnit.MILLISECONDS);
// Bukkit.getAsyncScheduler().runAtFixedRate(plugin, task -> runnable.run(), delay * 50, ticks * 50, TimeUnit.MILLISECONDS);

@ -1,14 +1,14 @@
package lol.pyr.znpcsplus.hologram; package lol.pyr.znpcsplus.hologram;
import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.config.Configs;
import lol.pyr.znpcsplus.util.ZLocation;
import lol.pyr.znpcsplus.util.Viewable; import lol.pyr.znpcsplus.util.Viewable;
import lol.pyr.znpcsplus.util.ZLocation;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
public class Hologram extends Viewable implements lol.pyr.znpcsplus.api.hologram.Hologram { public class Hologram extends Viewable implements lol.pyr.znpcsplus.api.hologram.Hologram {
private ZLocation location; private ZLocation location;
@ -70,7 +70,7 @@ public class Hologram extends Viewable implements lol.pyr.znpcsplus.api.hologram
final double lineSpacing = Configs.config().lineSpacing(); final double lineSpacing = Configs.config().lineSpacing();
double height = location.getY() + lines.size() * lineSpacing; double height = location.getY() + lines.size() * lineSpacing;
for (HologramLine line : lines) { for (HologramLine line : lines) {
line.setLocation(location.withY(height), line == newLine ? Set.of() : getViewers()); line.setLocation(location.withY(height), line == newLine ? Collections.emptySet() : getViewers());
height -= lineSpacing; height -= lineSpacing;
} }
} }

@ -48,7 +48,7 @@ public interface MetadataFactory {
throw new RuntimeException("Unsupported version!"); throw new RuntimeException("Unsupported version!");
} }
private static Map<ServerVersion, LazyLoader<? extends MetadataFactory>> buildFactoryMap() { static Map<ServerVersion, LazyLoader<? extends MetadataFactory>> buildFactoryMap() {
HashMap<ServerVersion, LazyLoader<? extends MetadataFactory>> map = new HashMap<>(); HashMap<ServerVersion, LazyLoader<? extends MetadataFactory>> map = new HashMap<>();
map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new));
map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new)); map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new));

@ -3,16 +3,16 @@ package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 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.data.EntityDataTypes;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.util.list.ListUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Optional; import java.util.Optional;
public class V1_13Factory extends V1_9Factory { public class V1_13Factory extends V1_9Factory {
@Override @Override
public Collection<EntityData> name(Component name) { public Collection<EntityData> name(Component name) {
return List.of( return ListUtil.immutableList(
new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.of(AdventureSerializer.getGsonSerializer().serialize(name))), new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.of(AdventureSerializer.getGsonSerializer().serialize(name))),
new EntityData(3, EntityDataTypes.BOOLEAN, true) new EntityData(3, EntityDataTypes.BOOLEAN, true)
); );

@ -3,10 +3,10 @@ package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 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.data.EntityDataTypes;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.util.list.ListUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class V1_8Factory implements MetadataFactory { public class V1_8Factory implements MetadataFactory {
@Override @Override
@ -21,7 +21,7 @@ public class V1_8Factory implements MetadataFactory {
@Override @Override
public Collection<EntityData> name(Component name) { public Collection<EntityData> name(Component name) {
return List.of( return ListUtil.immutableList(
new EntityData(2, EntityDataTypes.STRING, AdventureSerializer.getGsonSerializer().serialize(name)), new EntityData(2, EntityDataTypes.STRING, AdventureSerializer.getGsonSerializer().serialize(name)),
new EntityData(3, EntityDataTypes.BYTE, 1) new EntityData(3, EntityDataTypes.BYTE, 1)
); );

@ -3,10 +3,10 @@ package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 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.data.EntityDataTypes;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.util.list.ListUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class V1_9Factory extends V1_8Factory { public class V1_9Factory extends V1_8Factory {
@Override @Override
@ -21,7 +21,7 @@ public class V1_9Factory extends V1_8Factory {
@Override @Override
public Collection<EntityData> name(Component name) { public Collection<EntityData> name(Component name) {
return List.of( return ListUtil.immutableList(
new EntityData(2, EntityDataTypes.STRING, AdventureSerializer.getGsonSerializer().serialize(name)), new EntityData(2, EntityDataTypes.STRING, AdventureSerializer.getGsonSerializer().serialize(name)),
new EntityData(3, EntityDataTypes.BOOLEAN, true) new EntityData(3, EntityDataTypes.BOOLEAN, true)
); );

@ -43,7 +43,7 @@ public interface PacketFactory {
throw new RuntimeException("Unsupported version!"); throw new RuntimeException("Unsupported version!");
} }
private static Map<ServerVersion, LazyLoader<? extends PacketFactory>> buildFactoryMap() { static Map<ServerVersion, LazyLoader<? extends PacketFactory>> buildFactoryMap() {
HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> map = new HashMap<>(); HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> map = new HashMap<>();
map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new));
map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new)); map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new));

@ -22,6 +22,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -33,7 +34,7 @@ public class V1_8Factory implements PacketFactory {
createTeam(player, entity, properties); createTeam(player, entity, properties);
ZLocation location = entity.getLocation(); ZLocation location = entity.getLocation();
sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(),
entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), Collections.emptyList()));
sendAllMetadata(player, entity, properties); sendAllMetadata(player, entity, properties);
ZNPCsPlus.SCHEDULER.runLaterAsync(() -> removeTabPlayer(player, entity), 60); ZNPCsPlus.SCHEDULER.runLaterAsync(() -> removeTabPlayer(player, entity), 60);
}); });
@ -46,7 +47,7 @@ public class V1_8Factory implements PacketFactory {
ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
sendPacket(player, type.getLegacyId(clientVersion) == -1 ? sendPacket(player, type.getLegacyId(clientVersion) == -1 ?
new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), entity.getUuid(), type, location.toVector3d(), new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), entity.getUuid(), type, location.toVector3d(),
location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), Collections.emptyList()) :
new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(),
location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty()));
sendAllMetadata(player, entity, properties); sendAllMetadata(player, entity, properties);

@ -0,0 +1,48 @@
package lol.pyr.znpcsplus.scheduling;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class FoliaScheduler extends TaskScheduler {
public FoliaScheduler(Plugin plugin) {
super(plugin);
}
@Override
public void runAsync(Runnable runnable) {
try {
Object scheduler = Reflections.FOLIA_GET_ASYNC_SCHEDULER.get().invoke(null);
Reflections.FOLIA_RUN_NOW.get().invoke(scheduler, plugin, (Consumer<Object>) o -> runnable.run());
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
// Bukkit.getAsyncScheduler().runNow(plugin, task -> runnable.run());
}
@Override
public void runLaterAsync(Runnable runnable, long ticks) {
try {
Object scheduler = Reflections.FOLIA_GET_ASYNC_SCHEDULER.get().invoke(null);
Reflections.FOLIA_RUN_DELAYED.get().invoke(scheduler, plugin, (Consumer<Object>) o -> runnable.run(), ticks * 50, TimeUnit.MILLISECONDS);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
// Bukkit.getAsyncScheduler().runDelayed(plugin, task -> runnable.run(), ticks * 50, TimeUnit.MILLISECONDS);
}
@Override
public void runDelayedTimerAsync(Runnable runnable, long delay, long ticks) {
try {
Object scheduler = Reflections.FOLIA_GET_ASYNC_SCHEDULER.get().invoke(null);
Reflections.FOLIA_RUN_AT_FIXED_RATE.get().invoke(scheduler, plugin, (Consumer<Object>) o -> runnable.run(), delay * 50, ticks * 50, TimeUnit.MILLISECONDS);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
// Bukkit.getAsyncScheduler().runAtFixedRate(plugin, task -> runnable.run(), delay * 50, ticks * 50, TimeUnit.MILLISECONDS);
}
}

@ -5,9 +5,11 @@ import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.mojang.authlib.properties.PropertyMap; import com.mojang.authlib.properties.PropertyMap;
import lol.pyr.znpcsplus.util.list.ListUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class Skin { public class Skin {
private final long timestamp = System.currentTimeMillis(); private final long timestamp = System.currentTimeMillis();
@ -18,13 +20,13 @@ public class Skin {
} }
public Skin(TextureProperty... properties) { public Skin(TextureProperty... properties) {
this.properties.addAll(List.of(properties)); this.properties.addAll(ListUtil.immutableList(properties));
} }
public Skin(PropertyMap properties) { public Skin(PropertyMap properties) {
this.properties.addAll(properties.values().stream() this.properties.addAll(properties.values().stream()
.map(property -> new TextureProperty(property.getName(), property.getValue(), property.getSignature())) .map(property -> new TextureProperty(property.getName(), property.getValue(), property.getSignature()))
.toList()); .collect(Collectors.toList()));
} }
public Skin(JsonObject obj) { public Skin(JsonObject obj) {

@ -1,7 +1,9 @@
package lol.pyr.znpcsplus.util; package lol.pyr.znpcsplus.util;
public class FoliaUtil { public class FoliaUtil {
private static final Boolean FOLIA = isFolia();
public static boolean isFolia() { public static boolean isFolia() {
if (FOLIA != null) return FOLIA;
try { try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
return true; return true;

@ -0,0 +1,62 @@
package lol.pyr.znpcsplus.util.list;
import java.util.Iterator;
import java.util.ListIterator;
public class ArrayIterator<T> implements Iterator<T>, ListIterator<T> {
private final T[] array;
private int index = 0;
public ArrayIterator(T[] array) {
this.array = array;
}
@Override
public boolean hasNext() {
return array.length > index;
}
@Override
public T next() {
return array[index++];
}
private boolean inBounds(int index) {
return index >= 0 && index < array.length;
}
@Override
public boolean hasPrevious() {
return inBounds(index - 1);
}
@Override
public T previous() {
return array[--index];
}
@Override
public int nextIndex() {
return index + 1;
}
@Override
public int previousIndex() {
return index - 1;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void set(T t) {
throw new UnsupportedOperationException();
}
@Override
public void add(T t) {
throw new UnsupportedOperationException();
}
}

@ -0,0 +1,133 @@
package lol.pyr.znpcsplus.util.list;
import java.util.*;
public class ImmutableArrayList<T> implements List<T> {
private final T[] elements;
public ImmutableArrayList(T[] array) {
this.elements = array;
}
@Override
public int size() {
return elements.length;
}
@Override
public boolean isEmpty() {
return elements.length != 0;
}
@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
@Override
public Iterator<T> iterator() {
return new ArrayIterator<>(elements);
}
@Override
public Object[] toArray() {
return elements;
}
@SuppressWarnings("unchecked")
@Override
public <T1> T1[] toArray(T1[] a) {
return (T1[]) elements;
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object obj : c) if (!contains(obj)) return false;
return true;
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
return new ImmutableArrayList<>(Arrays.copyOfRange(elements, fromIndex, toIndex));
}
@Override
public T get(int index) {
return elements[index];
}
@Override
public int indexOf(Object o) {
for (int i = 0; i < elements.length; i++) if (Objects.equals(elements[i], o)) return i;
return -1;
}
@Override
public int lastIndexOf(Object o) {
for (int i = 0; i < elements.length; i++) {
int index = elements.length - (i + 1);
if (Objects.equals(elements[index], o)) return index;
}
return -1;
}
@Override
public ListIterator<T> listIterator() {
return new ArrayIterator<>(elements);
}
@Override
public ListIterator<T> listIterator(int index) {
return new ArrayIterator<>(elements);
}
@Override
public boolean add(T t) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public T set(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public void add(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException();
}
}

@ -0,0 +1,10 @@
package lol.pyr.znpcsplus.util.list;
import java.util.*;
public class ListUtil {
@SafeVarargs
public static <T> List<T> immutableList(T... elements) {
return new ImmutableArrayList<>(elements);
}
}