Compare commits

..

20 Commits
3.0.1 ... 3.2.0

Author SHA1 Message Date
Auxilor
f0cd9ae16d Updated to 3.2.0 2021-01-20 20:13:09 +00:00
Auxilor
b220428b8c Added StaticBaseConfig, a non-updating config implementation 2021-01-20 20:12:53 +00:00
Auxilor
8386aacfd8 Updated to 3.1.3 2021-01-20 19:06:07 +00:00
Auxilor
3c54e24102 Reworked gradients 2021-01-20 19:05:55 +00:00
Auxilor
3dc0693b8c Reworked gradients 2021-01-20 18:47:56 +00:00
Auxilor
f087113ddf Updated to 3.1.2 2021-01-20 17:38:51 +00:00
Auxilor
d5d1f5d8cc Added fix for PacketPlayOutRecipeUpdate being too large 2021-01-20 17:35:29 +00:00
Auxilor
0d5bf901e2 Updated to 3.1.1 2021-01-20 11:27:57 +00:00
Auxilor
ae0445f47b Fixed recipe listener registration 2021-01-20 11:27:46 +00:00
Auxilor
a6ba24b7a5 Added auto version 2021-01-19 17:39:25 +00:00
Auxilor
1b00831147 Prevented duplicate module registration 2021-01-19 17:38:36 +00:00
Auxilor
479cff60d5 Fixed list emptiness java 2021-01-19 17:30:01 +00:00
Auxilor
d2499b1e27 Fixed artifact id name 2021-01-19 17:10:45 +00:00
Auxilor
4f65f33953 Reworked project structure 2021-01-19 17:02:04 +00:00
Auxilor
6d4a69c781 Removed debug message 2021-01-19 14:30:39 +00:00
Auxilor
e90e58b50a Moved event listeners 2021-01-19 14:29:09 +00:00
Auxilor
826bdb63d0 Removed pointless bukkit services 2021-01-19 14:07:48 +00:00
Auxilor
4ecba69161 Updated to 3.0.3 2021-01-19 13:59:21 +00:00
Auxilor
e64510ebf5 Fixed FastCollatedDropQueueRunnable 2021-01-19 13:58:57 +00:00
Auxilor
50a506af62 Added gradient support 2021-01-19 11:36:47 +00:00
146 changed files with 2114 additions and 486 deletions

2
.gitignore vendored
View File

@@ -14,7 +14,7 @@ bin/
# Gradle
.gradle
**/build/
!src/**/build/
!eco-util/src/**/build/
.gradletasknamecache
!gradle-wrapper.jar
gradle-app.setting

View File

@@ -6,97 +6,91 @@ plugins {
}
dependencies {
implementation 'org.apache.maven:maven-artifact:3.0.3'
implementation 'org.bstats:bstats-bukkit:1.7'
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
compileOnly 'com.github.TechFortress:GriefPrevention:16.14.0'
compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
compileOnly 'com.github.cryptomorin:kingdoms:1.10.3.1'
compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0'
compileOnly 'com.github.angeschossen:LandsAPI:4.7.3'
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
compileOnly 'org.jetbrains:annotations:19.0.0'
compileOnly fileTree(dir: 'lib', include: ['*.jar'])
// Lombok
compileOnly 'org.projectlombok:lombok:1.18.16'
annotationProcessor 'org.projectlombok:lombok:1.18.16'
testCompileOnly 'org.projectlombok:lombok:1.18.16'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'
implementation project(":eco-util")
implementation project(":eco-core").getSubprojects()
}
allprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'maven-publish'
apply plugin: 'com.github.johnrengelman.shadow'
repositories {
mavenCentral()
jcenter()
mavenLocal()
maven { url 'https://jitpack.io' }
repositories {
mavenCentral()
jcenter()
mavenLocal()
maven { url 'https://jitpack.io' }
// NMS (for jitpack compilation)
maven { url 'https://repo.codemc.org/repository/nms/' }
// NMS (for jitpack compilation)
maven { url 'https://repo.codemc.org/repository/nms/' }
// bStats
maven { url 'https://repo.codemc.org/repository/maven-public' }
// bStats
maven { url 'https://repo.codemc.org/repository/maven-public' }
// Spigot API
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
// Spigot API
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
// PlaceholderAPI
maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
// PlaceholderAPI
maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
// ProtocolLib
maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
// ProtocolLib
maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
// WorldGuard
maven { url 'https://maven.enginehub.org/repo/' }
// WorldGuard
maven { url 'https://maven.enginehub.org/repo/' }
// FactionsUUID
maven { url 'https://ci.ender.zone/plugin/repository/everything/' }
// FactionsUUID
maven { url 'https://ci.ender.zone/plugin/repository/everything/' }
// NoCheatPlus
maven { url 'https://repo.md-5.net/content/repositories/snapshots/' }
}
tasks.withType(JavaCompile) {
options.deprecation = true
options.encoding = 'UTF-8'
}
configurations.all {
exclude group: "org.codehaus.plexus", module: "plexus-utils"
exclude group: "com.mojang", module: "brigadier"
exclude group: "org.kitteh", module: "paste-gg-api"
exclude group: "org.spongepowered", module: "configurate-hocon"
exclude group: "com.darkblade12", module: "particleeffect"
}
shadowJar {
relocate('org.bstats.bukkit', 'com.willfp.eco.util.shaded.bstats')
relocate('org.apache.maven', 'com.willfp.eco.util.shaded.maven')
}
publishing {
publications {
shadow(MavenPublication) {
from components.java
artifact shadowJar
}
// NoCheatPlus
maven { url 'https://repo.md-5.net/content/repositories/snapshots/' }
}
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
compileOnly 'org.jetbrains:annotations:19.0.0'
// Lombok
compileOnly 'org.projectlombok:lombok:1.18.16'
annotationProcessor 'org.projectlombok:lombok:1.18.16'
testCompileOnly 'org.projectlombok:lombok:1.18.16'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'
}
tasks.withType(JavaCompile) {
options.deprecation = true
options.encoding = 'UTF-8'
}
configurations.all {
exclude group: "org.codehaus.plexus", module: "plexus-utils"
exclude group: "com.mojang", module: "brigadier"
exclude group: "org.kitteh", module: "paste-gg-api"
exclude group: "org.spongepowered", module: "configurate-hocon"
exclude group: "com.darkblade12", module: "particleeffect"
}
shadowJar {
relocate('org.bstats.bukkit', 'com.willfp.eco.util.shaded.bstats')
relocate('org.apache.maven', 'com.willfp.eco.util.shaded.maven')
}
jar {
onlyIf { !sourceSets.main.allSource.files.isEmpty() }
}
compileJava {
onlyIf { !sourceSets.main.allSource.files.isEmpty() }
}
compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean
build.dependsOn shadowJar
}
compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean
publishToMavenLocal.dependsOn shadowJar
build.dependsOn shadowJar
build.dependsOn publishToMavenLocal
group = 'com.willfp'
archivesBaseName = project.name
version = '3.0.1'
version = findProperty("version")
java.sourceCompatibility = JavaVersion.VERSION_1_8

8
eco-core/build.gradle Normal file
View File

@@ -0,0 +1,8 @@
group 'com.willfp'
version rootProject.version
subprojects {
dependencies {
compileOnly project(":eco-util")
}
}

View File

@@ -0,0 +1,9 @@
group 'com.willfp'
version rootProject.version
subprojects {
dependencies {
compileOnly project(':eco-core:core-proxy')
compileOnly project(':eco-core:core-plugin')
}
}

View File

@@ -0,0 +1,6 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.15.2-R0.1-SNAPSHOT'
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.proxy.v1_15_R1;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import net.minecraft.server.v1_15_R1.MinecraftKey;
import net.minecraft.server.v1_15_R1.PacketPlayOutAutoRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public final class AutoCraft implements AutoCraftProxy {
@Override
public void modifyPacket(@NotNull final Object packet) throws NoSuchFieldException, IllegalAccessException {
PacketPlayOutAutoRecipe recipePacket = (PacketPlayOutAutoRecipe) packet;
Field fKey = recipePacket.getClass().getDeclaredField("b");
fKey.setAccessible(true);
MinecraftKey key = (MinecraftKey) fKey.get(recipePacket);
fKey.set(recipePacket, new MinecraftKey(key.getNamespace(), key.getKey() + "_displayed"));
}
}

View File

@@ -0,0 +1,11 @@
package com.willfp.eco.proxy.v1_15_R1;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import org.jetbrains.annotations.NotNull;
public final class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(@NotNull final Object object) {
return object;
}
}

View File

@@ -0,0 +1,46 @@
package com.willfp.eco.proxy.v1_15_R1;
import com.willfp.eco.proxy.proxies.PacketPlayOutRecipeUpdateFixProxy;
import net.minecraft.server.v1_15_R1.IRecipe;
import net.minecraft.server.v1_15_R1.PacketPlayOutRecipeUpdate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("unchecked")
public final class PacketPlayOutRecipeUpdateFix implements PacketPlayOutRecipeUpdateFixProxy {
@Override
public List<Object> splitPackets(@NotNull final Object object,
@NotNull final Player player) {
if (!(object instanceof PacketPlayOutRecipeUpdate)) {
throw new IllegalArgumentException("Parameter not packet!");
}
PacketPlayOutRecipeUpdate oldPacket = (PacketPlayOutRecipeUpdate) object;
List<IRecipe<?>> recipes = new ArrayList<>();
try {
Field f = oldPacket.getClass().getDeclaredField("a");
f.setAccessible(true);
recipes.addAll((Collection<? extends IRecipe<?>>) f.get(oldPacket));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
List<Object> splitPackets = new ArrayList<>();
List<IRecipe<?>> splitRecipes = new ArrayList<>();
for (int i = 0; i < recipes.size(); i++) {
splitRecipes.add(recipes.get(i));
if (i % 100 == 0) {
PacketPlayOutRecipeUpdate newPacket = new PacketPlayOutRecipeUpdate(splitRecipes);
splitPackets.add(newPacket);
splitRecipes.clear();
}
}
return splitPackets;
}
}

View File

@@ -0,0 +1,47 @@
package com.willfp.eco.proxy.v1_15_R1;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.util.display.Display;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public final class VillagerTrade implements VillagerTradeProxy {
@Override
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) {
try {
// Enables removing final modifier
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
// Bukkit MerchantRecipe result
Field fResult = MerchantRecipe.class.getDeclaredField("result");
fResult.setAccessible(true);
ItemStack result = merchantRecipe.getResult();
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_15_R1.MerchantRecipe handle = (net.minecraft.server.v1_15_R1.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe
modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final
Field fSelling = net.minecraft.server.v1_15_R1.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,6 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.1-R0.1-SNAPSHOT'
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.proxy.v1_16_R1;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import net.minecraft.server.v1_16_R1.MinecraftKey;
import net.minecraft.server.v1_16_R1.PacketPlayOutAutoRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public final class AutoCraft implements AutoCraftProxy {
@Override
public void modifyPacket(@NotNull final Object packet) throws NoSuchFieldException, IllegalAccessException {
PacketPlayOutAutoRecipe recipePacket = (PacketPlayOutAutoRecipe) packet;
Field fKey = recipePacket.getClass().getDeclaredField("b");
fKey.setAccessible(true);
MinecraftKey key = (MinecraftKey) fKey.get(recipePacket);
fKey.set(recipePacket, new MinecraftKey(key.getNamespace(), key.getKey() + "_displayed"));
}
}

View File

@@ -0,0 +1,104 @@
package com.willfp.eco.proxy.v1_16_R1;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.util.display.Display;
import net.minecraft.server.v1_16_R1.ChatBaseComponent;
import net.minecraft.server.v1_16_R1.ChatHoverable;
import net.minecraft.server.v1_16_R1.ChatMessage;
import net.minecraft.server.v1_16_R1.ChatModifier;
import net.minecraft.server.v1_16_R1.IChatBaseComponent;
import net.minecraft.server.v1_16_R1.MojangsonParser;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(@NotNull final Object object) {
if (!(object instanceof IChatBaseComponent)) {
return object;
}
IChatBaseComponent chatComponent = (IChatBaseComponent) object;
chatComponent.stream().forEach(this::modifyBaseComponent);
return chatComponent;
}
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
component.getSiblings().forEach(this::modifyBaseComponent);
if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent)
.map(o -> (IChatBaseComponent) o)
.forEach(this::modifyBaseComponent);
}
ChatHoverable hoverable = component.getChatModifier().getHoverEvent();
if (hoverable == null) {
return;
}
JsonObject jsonObject = hoverable.b();
JsonElement json = hoverable.b().get("contents");
if (json.getAsJsonObject().get("id") == null) {
return;
}
if (json.getAsJsonObject().get("tag") == null) {
return;
}
String id = json.getAsJsonObject().get("id").toString();
String tag = json.getAsJsonObject().get("tag").toString();
ItemStack itemStack = getFromTag(tag, id);
Display.displayAndFinalize(itemStack);
json.getAsJsonObject().remove("tag");
String newTag = toJson(itemStack);
json.getAsJsonObject().add("tag", new JsonPrimitive(newTag));
jsonObject.remove("contents");
jsonObject.add("contents", json);
ChatHoverable newHoverable = ChatHoverable.a(jsonObject);
ChatModifier modifier = component.getChatModifier();
modifier = modifier.setChatHoverable(newHoverable);
((ChatBaseComponent) component).setChatModifier(modifier);
}
private static ItemStack getFromTag(@NotNull final String jsonTag,
@NotNull final String id) {
String processedId = id;
String processedJsonTag = jsonTag;
processedId = processedId.replace("minecraft:", "");
processedId = processedId.toUpperCase();
processedId = processedId.replace("\"", "");
processedJsonTag = processedJsonTag.substring(1, processedJsonTag.length() - 1);
processedJsonTag = processedJsonTag.replace("id:", "\"id\":");
processedJsonTag = processedJsonTag.replace("\\", "");
Material material = Material.getMaterial(processedId);
assert material != null;
ItemStack itemStack = new ItemStack(material);
net.minecraft.server.v1_16_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
try {
nmsStack.setTag(MojangsonParser.parse(processedJsonTag));
} catch (CommandSyntaxException e) {
e.printStackTrace();
}
return CraftItemStack.asBukkitCopy(nmsStack);
}
private static String toJson(@NotNull final ItemStack itemStack) {
return CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString();
}
}

View File

@@ -0,0 +1,46 @@
package com.willfp.eco.proxy.v1_16_R1;
import com.willfp.eco.proxy.proxies.PacketPlayOutRecipeUpdateFixProxy;
import net.minecraft.server.v1_16_R1.IRecipe;
import net.minecraft.server.v1_16_R1.PacketPlayOutRecipeUpdate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("unchecked")
public final class PacketPlayOutRecipeUpdateFix implements PacketPlayOutRecipeUpdateFixProxy {
@Override
public List<Object> splitPackets(@NotNull final Object object,
@NotNull final Player player) {
if (!(object instanceof PacketPlayOutRecipeUpdate)) {
throw new IllegalArgumentException("Parameter not packet!");
}
PacketPlayOutRecipeUpdate oldPacket = (PacketPlayOutRecipeUpdate) object;
List<IRecipe<?>> recipes = new ArrayList<>();
try {
Field f = oldPacket.getClass().getDeclaredField("a");
f.setAccessible(true);
recipes.addAll((Collection<? extends IRecipe<?>>) f.get(oldPacket));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
List<Object> splitPackets = new ArrayList<>();
List<IRecipe<?>> splitRecipes = new ArrayList<>();
for (int i = 0; i < recipes.size(); i++) {
splitRecipes.add(recipes.get(i));
if (i % 100 == 0) {
PacketPlayOutRecipeUpdate newPacket = new PacketPlayOutRecipeUpdate(splitRecipes);
splitPackets.add(newPacket);
splitRecipes.clear();
}
}
return splitPackets;
}
}

View File

@@ -0,0 +1,47 @@
package com.willfp.eco.proxy.v1_16_R1;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.util.display.Display;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public final class VillagerTrade implements VillagerTradeProxy {
@Override
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) {
try {
// Enables removing final modifier
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
// Bukkit MerchantRecipe result
Field fResult = MerchantRecipe.class.getDeclaredField("result");
fResult.setAccessible(true);
ItemStack result = merchantRecipe.getResult();
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_16_R1.MerchantRecipe handle = (net.minecraft.server.v1_16_R1.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe
modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final
Field fSelling = net.minecraft.server.v1_16_R1.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,6 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.3-R0.1-SNAPSHOT'
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.proxy.v1_16_R2;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import net.minecraft.server.v1_16_R2.MinecraftKey;
import net.minecraft.server.v1_16_R2.PacketPlayOutAutoRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public final class AutoCraft implements AutoCraftProxy {
@Override
public void modifyPacket(@NotNull final Object packet) throws NoSuchFieldException, IllegalAccessException {
PacketPlayOutAutoRecipe recipePacket = (PacketPlayOutAutoRecipe) packet;
Field fKey = recipePacket.getClass().getDeclaredField("b");
fKey.setAccessible(true);
MinecraftKey key = (MinecraftKey) fKey.get(recipePacket);
fKey.set(recipePacket, new MinecraftKey(key.getNamespace(), key.getKey() + "_displayed"));
}
}

View File

@@ -0,0 +1,104 @@
package com.willfp.eco.proxy.v1_16_R2;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.util.display.Display;
import net.minecraft.server.v1_16_R2.ChatBaseComponent;
import net.minecraft.server.v1_16_R2.ChatHoverable;
import net.minecraft.server.v1_16_R2.ChatMessage;
import net.minecraft.server.v1_16_R2.ChatModifier;
import net.minecraft.server.v1_16_R2.IChatBaseComponent;
import net.minecraft.server.v1_16_R2.MojangsonParser;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(@NotNull final Object object) {
if (!(object instanceof IChatBaseComponent)) {
return object;
}
IChatBaseComponent chatComponent = (IChatBaseComponent) object;
chatComponent.stream().forEach(this::modifyBaseComponent);
return chatComponent;
}
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
component.getSiblings().forEach(this::modifyBaseComponent);
if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent)
.map(o -> (IChatBaseComponent) o)
.forEach(this::modifyBaseComponent);
}
ChatHoverable hoverable = component.getChatModifier().getHoverEvent();
if (hoverable == null) {
return;
}
JsonObject jsonObject = hoverable.b();
JsonElement json = hoverable.b().get("contents");
if (json.getAsJsonObject().get("id") == null) {
return;
}
if (json.getAsJsonObject().get("tag") == null) {
return;
}
String id = json.getAsJsonObject().get("id").toString();
String tag = json.getAsJsonObject().get("tag").toString();
ItemStack itemStack = getFromTag(tag, id);
Display.displayAndFinalize(itemStack);
json.getAsJsonObject().remove("tag");
String newTag = toJson(itemStack);
json.getAsJsonObject().add("tag", new JsonPrimitive(newTag));
jsonObject.remove("contents");
jsonObject.add("contents", json);
ChatHoverable newHoverable = ChatHoverable.a(jsonObject);
ChatModifier modifier = component.getChatModifier();
modifier = modifier.setChatHoverable(newHoverable);
((ChatBaseComponent) component).setChatModifier(modifier);
}
private static ItemStack getFromTag(@NotNull final String jsonTag,
@NotNull final String id) {
String processedId = id;
String processedJsonTag = jsonTag;
processedId = processedId.replace("minecraft:", "");
processedId = processedId.toUpperCase();
processedId = processedId.replace("\"", "");
processedJsonTag = processedJsonTag.substring(1, processedJsonTag.length() - 1);
processedJsonTag = processedJsonTag.replace("id:", "\"id\":");
processedJsonTag = processedJsonTag.replace("\\", "");
Material material = Material.getMaterial(processedId);
assert material != null;
ItemStack itemStack = new ItemStack(material);
net.minecraft.server.v1_16_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
try {
nmsStack.setTag(MojangsonParser.parse(processedJsonTag));
} catch (CommandSyntaxException e) {
e.printStackTrace();
}
return CraftItemStack.asBukkitCopy(nmsStack);
}
private static String toJson(@NotNull final ItemStack itemStack) {
return CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString();
}
}

View File

@@ -0,0 +1,46 @@
package com.willfp.eco.proxy.v1_16_R2;
import com.willfp.eco.proxy.proxies.PacketPlayOutRecipeUpdateFixProxy;
import net.minecraft.server.v1_16_R2.IRecipe;
import net.minecraft.server.v1_16_R2.PacketPlayOutRecipeUpdate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("unchecked")
public final class PacketPlayOutRecipeUpdateFix implements PacketPlayOutRecipeUpdateFixProxy {
@Override
public List<Object> splitPackets(@NotNull final Object object,
@NotNull final Player player) {
if (!(object instanceof PacketPlayOutRecipeUpdate)) {
throw new IllegalArgumentException("Parameter not packet!");
}
PacketPlayOutRecipeUpdate oldPacket = (PacketPlayOutRecipeUpdate) object;
List<IRecipe<?>> recipes = new ArrayList<>();
try {
Field f = oldPacket.getClass().getDeclaredField("a");
f.setAccessible(true);
recipes.addAll((Collection<? extends IRecipe<?>>) f.get(oldPacket));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
List<Object> splitPackets = new ArrayList<>();
List<IRecipe<?>> splitRecipes = new ArrayList<>();
for (int i = 0; i < recipes.size(); i++) {
splitRecipes.add(recipes.get(i));
if (i % 100 == 0) {
PacketPlayOutRecipeUpdate newPacket = new PacketPlayOutRecipeUpdate(splitRecipes);
splitPackets.add(newPacket);
splitRecipes.clear();
}
}
return splitPackets;
}
}

View File

@@ -0,0 +1,47 @@
package com.willfp.eco.proxy.v1_16_R2;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.util.display.Display;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public final class VillagerTrade implements VillagerTradeProxy {
@Override
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) {
try {
// Enables removing final modifier
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
// Bukkit MerchantRecipe result
Field fResult = MerchantRecipe.class.getDeclaredField("result");
fResult.setAccessible(true);
ItemStack result = merchantRecipe.getResult();
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_16_R2.MerchantRecipe handle = (net.minecraft.server.v1_16_R2.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe
modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final
Field fSelling = net.minecraft.server.v1_16_R2.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,6 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT'
}

View File

@@ -0,0 +1,19 @@
package com.willfp.eco.proxy.v1_16_R3;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import net.minecraft.server.v1_16_R3.MinecraftKey;
import net.minecraft.server.v1_16_R3.PacketPlayOutAutoRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
public final class AutoCraft implements AutoCraftProxy {
@Override
public void modifyPacket(@NotNull final Object packet) throws NoSuchFieldException, IllegalAccessException {
PacketPlayOutAutoRecipe recipePacket = (PacketPlayOutAutoRecipe) packet;
Field fKey = recipePacket.getClass().getDeclaredField("b");
fKey.setAccessible(true);
MinecraftKey key = (MinecraftKey) fKey.get(recipePacket);
fKey.set(recipePacket, new MinecraftKey(key.getNamespace(), key.getKey() + "_displayed"));
}
}

View File

@@ -0,0 +1,104 @@
package com.willfp.eco.proxy.v1_16_R3;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.util.display.Display;
import net.minecraft.server.v1_16_R3.ChatBaseComponent;
import net.minecraft.server.v1_16_R3.ChatHoverable;
import net.minecraft.server.v1_16_R3.ChatMessage;
import net.minecraft.server.v1_16_R3.ChatModifier;
import net.minecraft.server.v1_16_R3.IChatBaseComponent;
import net.minecraft.server.v1_16_R3.MojangsonParser;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public final class ChatComponent implements ChatComponentProxy {
@Override
public Object modifyComponent(@NotNull final Object object) {
if (!(object instanceof IChatBaseComponent)) {
return object;
}
IChatBaseComponent chatComponent = (IChatBaseComponent) object;
chatComponent.stream().forEach(this::modifyBaseComponent);
return chatComponent;
}
private void modifyBaseComponent(@NotNull final IChatBaseComponent component) {
component.getSiblings().forEach(this::modifyBaseComponent);
if (component instanceof ChatMessage) {
Arrays.stream(((ChatMessage) component).getArgs())
.filter(o -> o instanceof IChatBaseComponent)
.map(o -> (IChatBaseComponent) o)
.forEach(this::modifyBaseComponent);
}
ChatHoverable hoverable = component.getChatModifier().getHoverEvent();
if (hoverable == null) {
return;
}
JsonObject jsonObject = hoverable.b();
JsonElement json = hoverable.b().get("contents");
if (json.getAsJsonObject().get("id") == null) {
return;
}
if (json.getAsJsonObject().get("tag") == null) {
return;
}
String id = json.getAsJsonObject().get("id").toString();
String tag = json.getAsJsonObject().get("tag").toString();
ItemStack itemStack = getFromTag(tag, id);
Display.displayAndFinalize(itemStack);
json.getAsJsonObject().remove("tag");
String newTag = toJson(itemStack);
json.getAsJsonObject().add("tag", new JsonPrimitive(newTag));
jsonObject.remove("contents");
jsonObject.add("contents", json);
ChatHoverable newHoverable = ChatHoverable.a(jsonObject);
ChatModifier modifier = component.getChatModifier();
modifier = modifier.setChatHoverable(newHoverable);
((ChatBaseComponent) component).setChatModifier(modifier);
}
private static ItemStack getFromTag(@NotNull final String jsonTag,
@NotNull final String id) {
String processedId = id;
String processedJsonTag = jsonTag;
processedId = processedId.replace("minecraft:", "");
processedId = processedId.toUpperCase();
processedId = processedId.replace("\"", "");
processedJsonTag = processedJsonTag.substring(1, processedJsonTag.length() - 1);
processedJsonTag = processedJsonTag.replace("id:", "\"id\":");
processedJsonTag = processedJsonTag.replace("\\", "");
Material material = Material.getMaterial(processedId);
assert material != null;
ItemStack itemStack = new ItemStack(material);
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
try {
nmsStack.setTag(MojangsonParser.parse(processedJsonTag));
} catch (CommandSyntaxException e) {
e.printStackTrace();
}
return CraftItemStack.asBukkitCopy(nmsStack);
}
private static String toJson(@NotNull final ItemStack itemStack) {
return CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString();
}
}

View File

@@ -0,0 +1,46 @@
package com.willfp.eco.proxy.v1_16_R3;
import com.willfp.eco.proxy.proxies.PacketPlayOutRecipeUpdateFixProxy;
import net.minecraft.server.v1_16_R3.IRecipe;
import net.minecraft.server.v1_16_R3.PacketPlayOutRecipeUpdate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("unchecked")
public final class PacketPlayOutRecipeUpdateFix implements PacketPlayOutRecipeUpdateFixProxy {
@Override
public List<Object> splitPackets(@NotNull final Object object,
@NotNull final Player player) {
if (!(object instanceof PacketPlayOutRecipeUpdate)) {
throw new IllegalArgumentException("Parameter not packet!");
}
PacketPlayOutRecipeUpdate oldPacket = (PacketPlayOutRecipeUpdate) object;
List<IRecipe<?>> recipes = new ArrayList<>();
try {
Field f = oldPacket.getClass().getDeclaredField("a");
f.setAccessible(true);
recipes.addAll((Collection<? extends IRecipe<?>>) f.get(oldPacket));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
List<Object> splitPackets = new ArrayList<>();
List<IRecipe<?>> splitRecipes = new ArrayList<>();
for (int i = 0; i < recipes.size(); i++) {
splitRecipes.add(recipes.get(i));
if (i % 100 == 0) {
PacketPlayOutRecipeUpdate newPacket = new PacketPlayOutRecipeUpdate(splitRecipes);
splitPackets.add(newPacket);
splitRecipes.clear();
}
}
return splitPackets;
}
}

View File

@@ -0,0 +1,47 @@
package com.willfp.eco.proxy.v1_16_R3;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.util.display.Display;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public final class VillagerTrade implements VillagerTradeProxy {
@Override
public void displayTrade(@NotNull final MerchantRecipe merchantRecipe) {
try {
// Enables removing final modifier
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
// Bukkit MerchantRecipe result
Field fResult = MerchantRecipe.class.getDeclaredField("result");
fResult.setAccessible(true);
ItemStack result = merchantRecipe.getResult();
Display.displayAndFinalize(result);
fResult.set(merchantRecipe, result);
// Get NMS MerchantRecipe from CraftMerchantRecipe
Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle");
fHandle.setAccessible(true);
net.minecraft.server.v1_16_R3.MerchantRecipe handle = (net.minecraft.server.v1_16_R3.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe
modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final
Field fSelling = net.minecraft.server.v1_16_R3.MerchantRecipe.class.getDeclaredField("sellingItem");
fSelling.setAccessible(true);
modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL);
ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem);
Display.displayAndFinalize(selling);
fSelling.set(handle, CraftItemStack.asNMSCopy(selling));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,24 @@
group 'com.willfp'
version rootProject.version
dependencies {
implementation 'org.apache.maven:maven-artifact:3.0.3'
implementation 'org.bstats:bstats-bukkit:1.7'
compileOnly project(":eco-core:core-proxy")
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
compileOnly 'com.github.TechFortress:GriefPrevention:16.14.0'
compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
compileOnly 'com.github.cryptomorin:kingdoms:1.10.3.1'
compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0'
compileOnly 'com.github.angeschossen:LandsAPI:4.7.3'
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
compileOnly fileTree(dir: '../../lib', include: ['*.jar'])
}
processResources {
filesNotMatching(["**/*.png", "**/models/**", "**/textures/**"]) {
expand projectVersion: project.version
}
}

View File

@@ -0,0 +1,128 @@
package com.willfp.eco.spigot;
import com.comphenix.protocol.ProtocolLibrary;
import com.willfp.eco.spigot.display.packets.PacketAutoRecipe;
import com.willfp.eco.spigot.display.packets.PacketChat;
import com.willfp.eco.spigot.display.packets.PacketOpenWindowMerchant;
import com.willfp.eco.spigot.display.packets.PacketSetCreativeSlot;
import com.willfp.eco.spigot.display.packets.PacketSetSlot;
import com.willfp.eco.spigot.display.packets.PacketWindowItems;
import com.willfp.eco.spigot.integrations.anticheat.plugins.AnticheatAAC;
import com.willfp.eco.spigot.integrations.anticheat.plugins.AnticheatMatrix;
import com.willfp.eco.spigot.integrations.anticheat.plugins.AnticheatNCP;
import com.willfp.eco.spigot.integrations.antigrief.plugins.AntigriefFactionsUUID;
import com.willfp.eco.spigot.integrations.antigrief.plugins.AntigriefGriefPrevention;
import com.willfp.eco.spigot.integrations.antigrief.plugins.AntigriefKingdoms;
import com.willfp.eco.spigot.integrations.antigrief.plugins.AntigriefLands;
import com.willfp.eco.spigot.integrations.antigrief.plugins.AntigriefTowny;
import com.willfp.eco.spigot.integrations.antigrief.plugins.AntigriefWorldGuard;
import com.willfp.eco.util.command.AbstractCommand;
import com.willfp.eco.util.drops.internal.FastCollatedDropQueue;
import com.willfp.eco.util.events.armorequip.ArmorListener;
import com.willfp.eco.util.events.armorequip.DispenserArmorListener;
import com.willfp.eco.util.events.entitydeathbyentity.EntityDeathByEntityListeners;
import com.willfp.eco.util.events.naturalexpgainevent.NaturalExpGainListeners;
import com.willfp.eco.util.integrations.IntegrationLoader;
import com.willfp.eco.util.integrations.anticheat.AnticheatManager;
import com.willfp.eco.util.integrations.antigrief.AntigriefManager;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import com.willfp.eco.util.recipe.RecipeListener;
import lombok.Getter;
import org.bukkit.event.Listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class EcoPlugin extends AbstractEcoPlugin {
/**
* Instance of eco.
*/
@Getter
private static EcoPlugin instance;
/**
* Create a new instance of eco.
*/
public EcoPlugin() {
super("eco", 87955, 10043, "com.willfp.eco.proxy", "&a");
instance = this;
}
@Override
public void enable() {
new FastCollatedDropQueue.CollatedRunnable(this);
this.getEventManager().registerListener(new NaturalExpGainListeners());
this.getEventManager().registerListener(new ArmorListener());
this.getEventManager().registerListener(new DispenserArmorListener());
this.getEventManager().registerListener(new EntityDeathByEntityListeners(this));
this.getEventManager().registerListener(new RecipeListener(this));
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketPlayOutRecipeUpdateFix(this));
}
@Override
public void disable() {
}
@Override
public void load() {
}
@Override
public void onReload() {
new FastCollatedDropQueue.CollatedRunnable(this);
}
@Override
public void postLoad() {
}
@Override
public List<IntegrationLoader> getIntegrationLoaders() {
return Arrays.asList(
// AntiGrief
new IntegrationLoader("WorldGuard", () -> AntigriefManager.register(new AntigriefWorldGuard())),
new IntegrationLoader("GriefPrevention", () -> AntigriefManager.register(new AntigriefGriefPrevention())),
new IntegrationLoader("FactionsUUID", () -> AntigriefManager.register(new AntigriefFactionsUUID())),
new IntegrationLoader("Towny", () -> AntigriefManager.register(new AntigriefTowny())),
new IntegrationLoader("Lands", () -> AntigriefManager.register(new AntigriefLands(this))),
new IntegrationLoader("Kingdoms", () -> AntigriefManager.register(new AntigriefKingdoms())),
// Anticheat
new IntegrationLoader("AAC5", () -> AnticheatManager.register(this, new AnticheatAAC())),
new IntegrationLoader("Matrix", () -> AnticheatManager.register(this, new AnticheatMatrix())),
new IntegrationLoader("NoCheatPlus", () -> AnticheatManager.register(this, new AnticheatNCP()))
);
}
@Override
public List<AbstractCommand> getCommands() {
return new ArrayList<>();
}
@Override
public List<AbstractPacketAdapter> getPacketAdapters() {
return Arrays.asList(
new PacketAutoRecipe(this),
new PacketChat(this),
new PacketOpenWindowMerchant(this),
new PacketSetCreativeSlot(this),
new PacketSetSlot(this),
new PacketWindowItems(this)
);
}
@Override
public List<Listener> getListeners() {
return new ArrayList<>();
}
@Override
public List<Class<?>> getUpdatableClasses() {
return new ArrayList<>();
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.spigot;
import com.willfp.eco.util.proxy.AbstractProxy;
import com.willfp.eco.proxy.util.ProxyFactory;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class InternalProxyUtils {
/**
* Get the implementation of a specified proxy.
*
* @param proxyClass The proxy interface.
* @param <T> The type of the proxy.
* @return The proxy implementation.
*/
public @NotNull <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
return new ProxyFactory<>(EcoPlugin.getInstance(), proxyClass).getProxy();
}
}

View File

@@ -0,0 +1,44 @@
package com.willfp.eco.spigot;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.willfp.eco.proxy.proxies.PacketPlayOutRecipeUpdateFixProxy;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class PacketPlayOutRecipeUpdateFix extends PacketAdapter {
/**
* Create new fixer for PacketPlayOutRecipeUpdate.
*
* @param plugin Plugin.
*/
public PacketPlayOutRecipeUpdateFix(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Server.RECIPE_UPDATE);
}
@Override
public void onPacketSending(@NotNull final PacketEvent event) {
PacketContainer packet = event.getPacket();
Player player = event.getPlayer();
List<Object> packets = InternalProxyUtils.getProxy(PacketPlayOutRecipeUpdateFixProxy.class).splitPackets(packet.getHandle(), player);
if (packets.size() > 1) {
event.setCancelled(true);
for (Object o : packets) {
PacketContainer container = PacketContainer.fromPacket(o);
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, container);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}

View File

@@ -0,0 +1,51 @@
package com.willfp.eco.spigot.display.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.proxy.proxies.AutoCraftProxy;
import com.willfp.eco.spigot.InternalProxyUtils;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
public class PacketAutoRecipe extends AbstractPacketAdapter {
/**
* Instantiate a new listener for {@link PacketType.Play.Server#SET_SLOT}.
*
* @param plugin The plugin to listen through.
*/
public PacketAutoRecipe(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Server.AUTO_RECIPE, false);
}
@Override
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
if (!AbstractEcoPlugin.LOADED_ECO_PLUGINS.contains(packet.getMinecraftKeys().getValues().get(0).getFullKey().split(":")[0])) {
return;
}
if (packet.getMinecraftKeys().getValues().get(0).getFullKey().split(":")[1].contains("displayed")) {
return;
}
try {
InternalProxyUtils.getProxy(AutoCraftProxy.class).modifyPacket(packet.getHandle());
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
PacketContainer newAutoRecipe = new PacketContainer(PacketType.Play.Server.AUTO_RECIPE);
newAutoRecipe.getMinecraftKeys().write(0, packet.getMinecraftKeys().read(0));
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newAutoRecipe);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,41 @@
package com.willfp.eco.spigot.display.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.willfp.eco.proxy.proxies.ChatComponentProxy;
import com.willfp.eco.spigot.InternalProxyUtils;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class PacketChat extends AbstractPacketAdapter {
/**
* Instantiate a new listener for {@link PacketType.Play.Server#CHAT}.
*
* @param plugin The plugin to listen through.
*/
public PacketChat(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Server.CHAT, ListenerPriority.MONITOR, true);
}
@Override
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
for (int i = 0; i < packet.getChatComponents().size(); i++) {
WrappedChatComponent component = packet.getChatComponents().read(i);
if (component == null) {
continue;
}
if (component.getHandle() == null) {
return;
}
WrappedChatComponent newComponent = WrappedChatComponent.fromHandle(InternalProxyUtils.getProxy(ChatComponentProxy.class).modifyComponent(component.getHandle()));
packet.getChatComponents().write(i, newComponent);
}
}
}

View File

@@ -0,0 +1,35 @@
package com.willfp.eco.spigot.display.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.spigot.InternalProxyUtils;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import org.bukkit.entity.Player;
import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.stream.Collectors;
public class PacketOpenWindowMerchant extends AbstractPacketAdapter {
/**
* Instantiate a new listener for {@link PacketType.Play.Server#OPEN_WINDOW_MERCHANT}.
*
* @param plugin The plugin to listen through.
*/
public PacketOpenWindowMerchant(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Server.OPEN_WINDOW_MERCHANT, false);
}
@Override
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
List<MerchantRecipe> recipes = packet.getMerchantRecipeLists().readSafely(0);
recipes = recipes.stream().peek(merchantRecipe -> InternalProxyUtils.getProxy(VillagerTradeProxy.class).displayTrade(merchantRecipe)).collect(Collectors.toList());
packet.getMerchantRecipeLists().writeSafely(0, recipes);
}
}

View File

@@ -0,0 +1,26 @@
package com.willfp.eco.spigot.display.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.util.display.Display;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class PacketSetCreativeSlot extends AbstractPacketAdapter {
/**
* Instantiate a new listener for {@link PacketType.Play.Client#SET_CREATIVE_SLOT}.
*
* @param plugin The plugin to listen through.
*/
public PacketSetCreativeSlot(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Client.SET_CREATIVE_SLOT, false);
}
@Override
public void onReceive(@NotNull final PacketContainer packet,
@NotNull final Player player) {
packet.getItemModifier().modify(0, Display::revert);
}
}

View File

@@ -0,0 +1,26 @@
package com.willfp.eco.spigot.display.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.util.display.Display;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class PacketSetSlot extends AbstractPacketAdapter {
/**
* Instantiate a new listener for {@link PacketType.Play.Server#SET_SLOT}.
*
* @param plugin The plugin to listen through.
*/
public PacketSetSlot(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Server.SET_SLOT, false);
}
@Override
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
packet.getItemModifier().modify(0, Display::display);
}
}

View File

@@ -0,0 +1,32 @@
package com.willfp.eco.spigot.display.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.util.display.Display;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class PacketWindowItems extends AbstractPacketAdapter {
/**
* Instantiate a new listener for {@link PacketType.Play.Server#WINDOW_ITEMS}.
*
* @param plugin The plugin to listen through.
*/
public PacketWindowItems(@NotNull final AbstractEcoPlugin plugin) {
super(plugin, PacketType.Play.Server.WINDOW_ITEMS, false);
}
@Override
public void onSend(@NotNull final PacketContainer packet,
@NotNull final Player player) {
packet.getItemListModifier().modify(0, itemStacks -> {
if (itemStacks == null) {
return null;
}
itemStacks.forEach(Display::display);
return itemStacks;
});
}
}

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
package com.willfp.eco.spigot.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import me.konsolas.aac.api.AACAPI;
@@ -12,9 +12,9 @@ import java.util.Objects;
public class AnticheatAAC implements AnticheatWrapper, Listener {
/**
* AAC exemption for EcoEnchants.
* AAC exemption for eco.
*/
private final AACExemption ecoEnchantsExemption = new AACExemption("EcoEnchants");
private final AACExemption ecoExemption = new AACExemption("eco");
/**
* AAC api.
@@ -28,11 +28,11 @@ public class AnticheatAAC implements AnticheatWrapper, Listener {
@Override
public void exempt(@NotNull final Player player) {
api.addExemption(player, ecoEnchantsExemption);
api.addExemption(player, ecoExemption);
}
@Override
public void unexempt(@NotNull final Player player) {
api.removeExemption(player, ecoEnchantsExemption);
api.removeExemption(player, ecoExemption);
}
}

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
package com.willfp.eco.spigot.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import me.rerere.matrix.api.events.PlayerViolationEvent;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
package com.willfp.eco.spigot.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import fr.neatmonster.nocheatplus.checks.CheckType;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
package com.willfp.eco.spigot.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import me.vagdedes.spartan.api.PlayerViolationEvent;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
package com.willfp.eco.spigot.integrations.antigrief.plugins;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
package com.willfp.eco.spigot.integrations.antigrief.plugins;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import me.ryanhamshire.GriefPrevention.Claim;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
package com.willfp.eco.spigot.integrations.antigrief.plugins;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import org.bukkit.Location;

View File

@@ -1,7 +1,7 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
package com.willfp.eco.spigot.integrations.antigrief.plugins;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import me.angeschossen.lands.api.integration.LandsIntegration;
import me.angeschossen.lands.api.land.Area;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
package com.willfp.eco.spigot.integrations.antigrief.plugins;
import com.palmergames.bukkit.towny.object.Town;
import com.palmergames.bukkit.towny.object.TownyPermission;

View File

@@ -1,4 +1,4 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
package com.willfp.eco.spigot.integrations.antigrief.plugins;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.LocalPlayer;

View File

@@ -1,6 +1,6 @@
name: eco
version: 3.0.1
main: com.willfp.eco.spigot.EcoSpigotMain
version: ${projectVersion}
main: com.willfp.eco.spigot.EcoPlugin
api-version: 1.15
authors: [Auxilor]
website: willfp.com

View File

@@ -0,0 +1,2 @@
group 'com.willfp'
version rootProject.version

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.proxy.proxies;
import com.willfp.eco.util.proxy.AbstractProxy;
import org.jetbrains.annotations.NotNull;
public interface AutoCraftProxy extends AbstractProxy {
/**
* Fix crafting inventory on auto-recipe.
*
* @param packet The packet to modify.
*/
void modifyPacket(@NotNull Object packet) throws NoSuchFieldException, IllegalAccessException;
}

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.proxy.proxies;
import com.willfp.eco.util.proxy.AbstractProxy;
import org.jetbrains.annotations.NotNull;
public interface ChatComponentProxy extends AbstractProxy {
/**
* Modify hover {@link org.bukkit.inventory.ItemStack}s using EnchantDisplay#displayEnchantments.
* @param object The NMS ChatComponent to modify.
* @return The modified ChatComponent.
*/
Object modifyComponent(@NotNull Object object);
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.proxy.proxies;
import com.willfp.eco.util.proxy.AbstractProxy;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface PacketPlayOutRecipeUpdateFixProxy extends AbstractProxy {
/**
* Split recipe update packet into smaller packets.
*
* @param object The packet.
* @param player The player.
* @return The packets, split up.
*/
List<Object> splitPackets(@NotNull Object object,
@NotNull Player player);
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.proxy.proxies;
import com.willfp.eco.util.proxy.AbstractProxy;
import org.bukkit.inventory.MerchantRecipe;
public interface VillagerTradeProxy extends AbstractProxy {
/**
* Apply enchant display to the result of trades.
*
* @param merchantRecipe The recipe to modify.
*/
void displayTrade(MerchantRecipe merchantRecipe);
}

View File

@@ -0,0 +1,75 @@
package com.willfp.eco.proxy.util;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.proxy.AbstractProxy;
import com.willfp.eco.util.proxy.ProxyConstants;
import com.willfp.eco.util.proxy.UnsupportedVersionException;
import org.jetbrains.annotations.NotNull;
import java.util.IdentityHashMap;
import java.util.Map;
public class ProxyFactory<T extends AbstractProxy> extends PluginDependent {
/**
* Cached proxy implementations in order to not perform expensive reflective class-finding.
*/
private static final Map<Class<? extends AbstractProxy>, AbstractProxy> CACHE = new IdentityHashMap<>();
/**
* The class of the proxy interface.
*/
private final Class<T> proxyClass;
/**
* Create a new Proxy Factory for a specific type.
*
* @param plugin The plugin to create proxies for.
* @param proxyClass The class of the proxy interface.
*/
public ProxyFactory(@NotNull final AbstractEcoPlugin plugin,
@NotNull final Class<T> proxyClass) {
super(plugin);
this.proxyClass = proxyClass;
}
/**
* Get the implementation of a proxy.
*
* @return The proxy implementation.
*/
public @NotNull T getProxy() {
try {
T cachedProxy = attemptCache();
if (cachedProxy != null) {
return cachedProxy;
}
String className = this.getPlugin().getProxyPackage() + "." + ProxyConstants.NMS_VERSION + "." + proxyClass.getSimpleName().replace("Proxy", "");
final Class<?> class2 = Class.forName(className);
Object instance = class2.getConstructor().newInstance();
if (proxyClass.isAssignableFrom(class2) && proxyClass.isInstance(instance)) {
T proxy = proxyClass.cast(instance);
CACHE.put(proxyClass, proxy);
return proxy;
}
} catch (Exception e) {
// If not returned, then throw error
}
throw new UnsupportedVersionException("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION);
}
private T attemptCache() {
Object proxy = CACHE.get(proxyClass);
if (proxy == null) {
return null;
}
if (proxyClass.isInstance(proxy)) {
return proxyClass.cast(proxy);
}
return null;
}
}

24
eco-util/build.gradle Normal file
View File

@@ -0,0 +1,24 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.apache.maven:maven-artifact:3.0.3'
compileOnly 'org.bstats:bstats-bukkit:1.7'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9'
}
compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean
build.dependsOn publishToMavenLocal
publishing {
publications {
shadow(MavenPublication) {
from components.java
artifact shadowJar
artifactId 'eco'
}
}
}

View File

@@ -0,0 +1,204 @@
package com.willfp.eco.util;
import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
import com.willfp.eco.util.optional.Prerequisite;
import lombok.experimental.UtilityClass;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static net.md_5.bungee.api.ChatColor.COLOR_CHAR;
@UtilityClass
public class StringUtils {
/**
* Regex for gradients.
*/
private static final Pattern GRADIENT_REGEX = Pattern.compile("<GRADIENT:([0-9A-Fa-f]{6})>(.*?)</GRADIENT:([0-9A-Fa-f]{6})>");
/**
* Regex for hex codes.
*/
private static final Pattern HEX_PATTERN = Pattern.compile("&#" + "([A-Fa-f0-9]{6})" + "");
/**
* Translate a string - converts Placeholders and Color codes.
*
* @param message The message to translate.
* @param player The player to translate placeholders with respect to.
* @return The message, translated.
*/
public String translate(@NotNull final String message,
@Nullable final Player player) {
String processedMessage = message;
if (Prerequisite.MINIMUM_1_16.isMet()) {
processedMessage = translateGradients(processedMessage);
}
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
processedMessage = translateHexColorCodes(processedMessage);
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
return processedMessage;
}
/**
* Translate a string without respect to a player.
*
* @param message The message to translate.
* @return The message, translated.
* @see StringUtils#translate(String, Player)
*/
public String translate(@NotNull final String message) {
return translate(message, null);
}
private static String translateHexColorCodes(@NotNull final String message) {
Matcher matcher = HEX_PATTERN.matcher(message);
StringBuffer buffer = new StringBuffer(message.length() + 4 * 8);
while (matcher.find()) {
String group = matcher.group(1);
matcher.appendReplacement(buffer, COLOR_CHAR + "x"
+ COLOR_CHAR + group.charAt(0) + COLOR_CHAR + group.charAt(1)
+ COLOR_CHAR + group.charAt(2) + COLOR_CHAR + group.charAt(3)
+ COLOR_CHAR + group.charAt(4) + COLOR_CHAR + group.charAt(5));
}
return matcher.appendTail(buffer).toString();
}
/**
* Colors a string with a gradient.
*
* @param string The string to color.
* @param start The start color.
* @param end The end color.
* @return The string, colored.
*/
private static String processGradients(@NotNull final String string,
@NotNull final Color start,
@NotNull final Color end) {
String processedString = string;
List<ChatColor> modifiers = new ArrayList<>();
if (processedString.contains("&l")) {
modifiers.add(ChatColor.BOLD);
}
if (processedString.contains("&o")) {
modifiers.add(ChatColor.ITALIC);
}
if (processedString.contains("&n")) {
modifiers.add(ChatColor.UNDERLINE);
}
if (processedString.contains("&k")) {
modifiers.add(ChatColor.MAGIC);
}
processedString = processedString.replace("&l", "");
processedString = processedString.replace("&o", "");
processedString = processedString.replace("&n", "");
processedString = processedString.replace("&k", "");
StringBuilder stringBuilder = new StringBuilder();
ChatColor[] colors = getGradientColors(start, end, processedString.length());
String[] characters = processedString.split("");
for (int i = 0; i < processedString.length(); i++) {
stringBuilder.append(colors[i]);
modifiers.forEach(stringBuilder::append);
stringBuilder.append(characters[i]);
}
return stringBuilder.toString();
}
/**
* Creates chatColors for gradients.
*
* @param start The start color.
* @param end The end color.
* @param step How many colors are returned.
* @return Array of chat colors.
*/
private static ChatColor[] getGradientColors(@NotNull final Color start,
@NotNull final Color end,
final int step) {
ChatColor[] colors = new ChatColor[step];
int stepR = Math.abs(start.getRed() - end.getRed()) / (step - 1);
int stepG = Math.abs(start.getGreen() - end.getGreen()) / (step - 1);
int stepB = Math.abs(start.getBlue() - end.getBlue()) / (step - 1);
int[] direction = new int[]{
start.getRed() < end.getRed() ? +1 : -1,
start.getGreen() < end.getGreen() ? +1 : -1,
start.getBlue() < end.getBlue() ? +1 : -1
};
for (int i = 0; i < step; i++) {
Color color = new Color(start.getRed() + ((stepR * i) * direction[0]), start.getGreen() + ((stepG * i) * direction[1]), start.getBlue() + ((stepB * i) * direction[2]));
colors[i] = ChatColor.of(color);
}
return colors;
}
/**
* Add gradients to a string.
*
* @param string The string.
* @return The string, colorized.
*/
private static String translateGradients(@NotNull final String string) {
String processedString = string;
Matcher matcher = GRADIENT_REGEX.matcher(string);
while (matcher.find()) {
String start = matcher.group(1);
String end = matcher.group(3);
String content = matcher.group(2);
processedString = processedString.replace(matcher.group(), processGradients(content, new Color(Integer.parseInt(start, 16)), new Color(Integer.parseInt(end, 16))));
}
return processedString;
}
/**
* Internal implementation of {@link String#valueOf}.
* Formats collections and doubles better.
*
* @param object The object to convert to string.
* @return The object stringified.
*/
public String internalToString(@Nullable final Object object) {
if (object == null) {
return "null";
}
if (object instanceof Integer) {
return ((Integer) object).toString();
} else if (object instanceof String) {
return (String) object;
} else if (object instanceof Double) {
return NumberUtils.format((Double) object);
} else if (object instanceof Collection<?>) {
Collection<?> c = (Collection<?>) object;
return c.stream().map(StringUtils::internalToString).collect(Collectors.joining(", "));
} else {
return String.valueOf(object);
}
}
/**
* Remove a string of characters from the start of a string.
*
* @param string The string to remove the prefix from.
* @param prefix The substring to remove.
* @return The string with the prefix removed.
*/
public String removePrefix(@NotNull final String string,
@NotNull final String prefix) {
if (string.startsWith(prefix)) {
return string.substring(prefix.length());
}
return string;
}
}

View File

@@ -0,0 +1,163 @@
package com.willfp.eco.util.config;
import com.willfp.eco.util.StringUtils;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import java.util.Objects;
public abstract class StaticBaseConfig extends PluginDependent implements ValueGetter {
/**
* The linked {@link YamlConfiguration} where values are physically stored.
*/
@Getter(AccessLevel.PUBLIC)
private final YamlConfiguration config;
/**
* The physical config file, as stored on disk.
*/
@Getter(AccessLevel.PROTECTED)
private final File configFile;
/**
* The full name of the config file (eg config.yml).
*/
private final String name;
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Does not automatically update.
*
* @param configName The name of the config
* @param plugin The plugin.
*/
protected StaticBaseConfig(@NotNull final String configName,
@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
this.name = configName + ".yml";
if (!new File(this.getPlugin().getDataFolder(), this.name).exists()) {
createFile();
}
this.configFile = new File(this.getPlugin().getDataFolder(), this.name);
this.config = YamlConfiguration.loadConfiguration(configFile);
}
private void createFile() {
this.getPlugin().saveResource(name, false);
}
/**
* Get an integer from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
@Override
public int getInt(@NotNull final String path) {
return config.getInt(path, 0);
}
/**
* Get an integer from config with a specified default (not found) value.
*
* @param path The key to fetch the value from.
* @param def The value to default to if not found.
* @return The found value, or the default.
*/
@Override
public int getInt(@NotNull final String path,
final int def) {
return config.getInt(path, def);
}
/**
* Get a list of integers from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<Integer> getInts(@NotNull final String path) {
return config.getIntegerList(path);
}
/**
* Get a boolean from config.
*
* @param path The key to fetch the value from.
* @return The found value, or false if not found.
*/
@Override
public boolean getBool(@NotNull final String path) {
return config.getBoolean(path, false);
}
/**
* Get a list of booleans from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<Boolean> getBools(@NotNull final String path) {
return config.getBooleanList(path);
}
/**
* Get a string from config.
*
* @param path The key to fetch the value from.
* @return The found value, or an empty string if not found.
*/
@Override
@NotNull
public String getString(@NotNull final String path) {
return StringUtils.translate(Objects.requireNonNull(config.getString(path, "")));
}
/**
* Get a list of strings from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<String> getStrings(@NotNull final String path) {
return config.getStringList(path);
}
/**
* Get a decimal from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
@Override
public double getDouble(@NotNull final String path) {
return config.getDouble(path, 0);
}
/**
* Get a list of decimals from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<Double> getDoubles(@NotNull final String path) {
return config.getDoubleList(path);
}
}

View File

@@ -0,0 +1,159 @@
package com.willfp.eco.util.display;
import lombok.experimental.UtilityClass;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
@UtilityClass
public class Display {
/**
* Registered display functions.
*/
private static final List<Map<String, Function<ItemStack, ItemStack>>> DISPLAY_FUNCTIONS = new ArrayList<>(10000);
/**
* Registered revert functions.
*/
private static final List<Function<ItemStack, ItemStack>> REVERT_FUNCTIONS = new ArrayList<>();
/**
* Registered finalize functions.
*/
public static final List<Function<ItemStack, ItemStack>> FINALIZE_FUNCTIONS = new ArrayList<>();
/**
* Registered finalize test functions.
*/
public static final List<Predicate<ItemStack>> FINALIZE_TEST_FUNCTIONS = new ArrayList<>();
/**
* Register display module.
*
* @param module The module.
*/
public void registerDisplayModule(@NotNull final DisplayModule module) {
int priority = module.getPriority();
if (priority > 9999) {
priority = 9999;
}
Function<ItemStack, ItemStack> function = module.getFunction();
Map<String, Function<ItemStack, ItemStack>> functions = DISPLAY_FUNCTIONS.get(priority);
if (functions == null) {
functions = new HashMap<>();
}
functions.remove(module.getId());
functions.put(module.getId(), function);
DISPLAY_FUNCTIONS.set(priority, functions);
}
/**
* Register revert function.
*
* @param function The function.
*/
public void registerRevertModule(@NotNull final Function<ItemStack, ItemStack> function) {
REVERT_FUNCTIONS.add(function);
}
/**
* Register finalize function.
*
* @param function The function.
*/
public void registerFinalizeModule(@NotNull final Function<ItemStack, ItemStack> function) {
FINALIZE_FUNCTIONS.add(function);
}
/**
* Register finalize test function.
*
* @param function The function.
*/
public void registerFinalizeTestModule(@NotNull final Predicate<ItemStack> function) {
FINALIZE_TEST_FUNCTIONS.add(function);
}
/**
* Display on ItemStacks.
*
* @param itemStack The item.
*/
public ItemStack display(@NotNull final ItemStack itemStack) {
for (Map<String, Function<ItemStack, ItemStack>> displayFunctions : DISPLAY_FUNCTIONS) {
if (displayFunctions == null) {
continue;
}
for (Function<ItemStack, ItemStack> displayFunction : displayFunctions.values()) {
displayFunction.apply(itemStack);
}
}
return itemStack;
}
/**
* Display on ItemStacks and then finalize.
*
* @param itemStack The item.
*/
public ItemStack displayAndFinalize(@NotNull final ItemStack itemStack) {
return finalize(display(itemStack));
}
/**
* Revert on ItemStacks.
*
* @param itemStack The item.
*/
public ItemStack revert(@NotNull final ItemStack itemStack) {
for (Function<ItemStack, ItemStack> displayFunction : REVERT_FUNCTIONS) {
displayFunction.apply(itemStack);
}
return itemStack;
}
/**
* Finalize an ItemStacks.
*
* @param itemStack The item.
*/
public ItemStack finalize(@NotNull final ItemStack itemStack) {
for (Function<ItemStack, ItemStack> function : FINALIZE_FUNCTIONS) {
function.apply(itemStack);
}
return itemStack;
}
/**
* Finalize an ItemStacks.
*
* @param itemStack The item.
*/
public boolean isFinalized(@NotNull final ItemStack itemStack) {
for (Predicate<ItemStack> function : FINALIZE_TEST_FUNCTIONS) {
if (function.test(itemStack)) {
return true;
}
}
return false;
}
static {
for (int i = 0; i < 10000; i++) {
DISPLAY_FUNCTIONS.add(null);
}
}
}

View File

@@ -0,0 +1,42 @@
package com.willfp.eco.util.display;
import lombok.Getter;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
public class DisplayModule {
/**
* Priority of the display module, where lower numbers are executed sooner.
*/
@Getter
private final int priority;
/**
* The function executed on display.
*/
@Getter
private final Function<ItemStack, ItemStack> function;
/**
* Function id for unregistration.
*/
@Getter
private final String id;
/**
* Create new display module.
*
* @param function The function.
* @param priority The priority.
* @param id The id.
*/
public DisplayModule(@NotNull final Function<ItemStack, ItemStack> function,
final int priority,
@NotNull final String id) {
this.function = function;
this.priority = priority;
this.id = id;
}
}

View File

@@ -1,6 +1,5 @@
package com.willfp.eco.util.drops.internal;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.Getter;
import lombok.Setter;
@@ -13,10 +12,9 @@ import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class FastCollatedDropQueue extends InternalDropQueue {
/**
@@ -24,7 +22,7 @@ public class FastCollatedDropQueue extends InternalDropQueue {
* <p>
* Cleared and updated every tick.
*/
private static final HashMap<Player, CollatedDrops> COLLATED_MAP = new HashMap<>();
private static final Map<Player, CollatedDrops> COLLATED_MAP = new ConcurrentHashMap<>();
/**
* Backend implementation of {@link AbstractDropQueue}
@@ -104,7 +102,7 @@ public class FastCollatedDropQueue extends InternalDropQueue {
}
}
public static class CollatedRunnable extends PluginDependent {
public static class CollatedRunnable {
/**
* The {@link BukkitTask} that the runnable represents.
*/
@@ -118,7 +116,6 @@ public class FastCollatedDropQueue extends InternalDropQueue {
*/
@ApiStatus.Internal
public CollatedRunnable(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
runnableTask = plugin.getScheduler().runTimer(() -> {
for (Map.Entry<Player, CollatedDrops> entry : COLLATED_MAP.entrySet()) {
new InternalDropQueue(entry.getKey())
@@ -126,6 +123,7 @@ public class FastCollatedDropQueue extends InternalDropQueue {
.addItems(entry.getValue().getDrops())
.addXP(entry.getValue().getXp())
.push();
COLLATED_MAP.remove(entry.getKey());
}
COLLATED_MAP.clear();
}, 0, 1);

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.util.drops.telekinesis;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -7,20 +8,20 @@ import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
public class EcoTelekinesisTests implements TelekinesisTests {
@UtilityClass
public final class TelekinesisUtils {
/**
* Set of tests that return if the player is telekinetic.
*/
private final Set<Function<Player, Boolean>> tests = new HashSet<>();
private static final Set<Function<Player, Boolean>> TESTS = new HashSet<>();
/**
* Register a new test to check against.
*
* @param test The test to register, where the boolean output is if the player is telekinetic.
*/
@Override
public void registerTest(@NotNull final Function<Player, Boolean> test) {
tests.add(test);
TESTS.add(test);
}
/**
@@ -31,9 +32,8 @@ public class EcoTelekinesisTests implements TelekinesisTests {
* @param player The player to test.
* @return If the player is telekinetic.
*/
@Override
public boolean testPlayer(@NotNull final Player player) {
for (Function<Player, Boolean> test : tests) {
for (Function<Player, Boolean> test : TESTS) {
if (test.apply(player)) {
return true;
}

Some files were not shown because too many files have changed in this diff Show More