mirror of
https://github.com/Xiao-MoMi/Custom-Nameplates.git
synced 2026-01-03 14:12:24 +00:00
TTF
This commit is contained in:
@@ -25,7 +25,6 @@ dependencies {
|
||||
tasks {
|
||||
shadowJar {
|
||||
archiveClassifier = ""
|
||||
archiveFileName = "CustomNameplates-${rootProject.properties["project_version"]}.jar"
|
||||
relocate ("net.kyori", "net.momirealms.customnameplates.libraries")
|
||||
relocate("dev.dejvokep", "net.momirealms.customnameplates.libraries")
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ dependencies {
|
||||
compileOnly("com.github.ben-manes.caffeine:caffeine:${rootProject.properties["caffeine_version"]}")
|
||||
// COMMONS IO
|
||||
compileOnly("commons-io:commons-io:${rootProject.properties["commons_io_version"]}")
|
||||
// lwjgl
|
||||
implementation("org.lwjgl:lwjgl-freetype:3.3.4")
|
||||
// TTF
|
||||
compileOnly("org.lwjgl:lwjgl-freetype:${rootProject.properties["lwjgl_version"]}")
|
||||
compileOnly("org.lwjgl:lwjgl:${rootProject.properties["lwjgl_version"]}")
|
||||
}
|
||||
@@ -49,13 +49,23 @@ import net.momirealms.customnameplates.api.placeholder.Placeholder;
|
||||
import net.momirealms.customnameplates.api.placeholder.PlayerPlaceholder;
|
||||
import net.momirealms.customnameplates.api.placeholder.SharedPlaceholder;
|
||||
import net.momirealms.customnameplates.api.util.CharacterUtils;
|
||||
import net.momirealms.customnameplates.backend.util.FreeTypeUtils;
|
||||
import net.momirealms.customnameplates.common.util.Tuple;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.lwjgl.util.freetype.FT_Face;
|
||||
import org.lwjgl.util.freetype.FT_GlyphSlot;
|
||||
import org.lwjgl.util.freetype.FT_Vector;
|
||||
import org.lwjgl.util.freetype.FreeType;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
@@ -768,16 +778,115 @@ public class AdvanceManagerImpl implements AdvanceManager {
|
||||
|
||||
File ttfCache = new File(plugin.getDataDirectory().toFile(), "tmp" + File.separator + id + ".tmp");
|
||||
if (!ttfCache.exists()) {
|
||||
File ttfFile = new File(plugin.getDataDirectory().toFile(), "font" + File.separator + path);
|
||||
if (!ttfFile.exists()) {
|
||||
plugin.getPluginLogger().warn(ttfFile.getAbsolutePath() + " not found");
|
||||
File ttf = new File(plugin.getDataDirectory().toFile(), "font" + File.separator + path);
|
||||
if (!ttf.exists()) {
|
||||
plugin.getPluginLogger().warn(ttf.getAbsolutePath() + " not found");
|
||||
return;
|
||||
}
|
||||
if (!ttfFile.getName().endsWith(".ttf")) {
|
||||
plugin.getPluginLogger().warn(ttfFile.getAbsolutePath() + " is not a .ttf");
|
||||
if (!ttf.getName().endsWith(".ttf")) {
|
||||
plugin.getPluginLogger().warn(ttf.getAbsolutePath() + " is not a .ttf");
|
||||
return;
|
||||
}
|
||||
try (InputStream inputStream = new FileInputStream(ttf)) {
|
||||
ByteBuffer byteBuffer = null;
|
||||
FT_Face fT_Face = null;
|
||||
try {
|
||||
ttfCache.getParentFile().mkdirs();
|
||||
ttfCache.createNewFile();
|
||||
YamlDocument yml = plugin.getConfigManager().loadData(ttfCache);
|
||||
byteBuffer = FreeTypeUtils.readResource(inputStream);
|
||||
byteBuffer.flip();
|
||||
synchronized(FreeTypeUtils.LOCK) {
|
||||
MemoryStack ms1 = MemoryStack.stackPush();
|
||||
try {
|
||||
PointerBuffer pointerBuffer = ms1.mallocPointer(1);
|
||||
FreeTypeUtils.checkFatalError(FreeType.FT_New_Memory_Face(FreeTypeUtils.initialize(), byteBuffer, 0L, pointerBuffer), "Initializing font face");
|
||||
fT_Face = FT_Face.create(pointerBuffer.get());
|
||||
} catch (Throwable t1) {
|
||||
try {
|
||||
ms1.close();
|
||||
} catch (Throwable t2) {
|
||||
t1.addSuppressed(t2);
|
||||
}
|
||||
throw t1;
|
||||
}
|
||||
ms1.close();
|
||||
|
||||
String string = FreeType.FT_Get_Font_Format(fT_Face);
|
||||
if (!"TrueType".equals(string)) {
|
||||
throw new IOException("Font is not in TTF format, was " + string);
|
||||
}
|
||||
|
||||
FreeTypeUtils.checkFatalError(FreeType.FT_Select_Charmap(fT_Face, FreeType.FT_ENCODING_UNICODE), "Find unicode charmap");
|
||||
Set<Integer> codePoints = new HashSet<>(1_000);
|
||||
|
||||
int pixelWidth = Math.round(size * oversample);
|
||||
int pixelHeight = Math.round(size * oversample);
|
||||
FreeType.FT_Set_Pixel_Sizes(fT_Face, pixelWidth, pixelHeight);
|
||||
|
||||
MemoryStack ms2 = MemoryStack.stackPush();
|
||||
try {
|
||||
FT_Vector fT_Vector = FreeTypeUtils.setShift(FT_Vector.malloc(ms2), 0, 0);
|
||||
FreeType.FT_Set_Transform(fT_Face, null, fT_Vector);
|
||||
} catch (Throwable t1) {
|
||||
try {
|
||||
ms2.close();
|
||||
} catch (Throwable t2) {
|
||||
t1.addSuppressed(t2);
|
||||
}
|
||||
throw t1;
|
||||
}
|
||||
ms2.close();
|
||||
|
||||
MemoryStack ms3 = MemoryStack.stackPush();
|
||||
try {
|
||||
IntBuffer intBuffer = ms3.mallocInt(1);
|
||||
for (long l = FreeType.FT_Get_First_Char(fT_Face, intBuffer); intBuffer.get(0) != 0; l = FreeType.FT_Get_Next_Char(fT_Face, l, intBuffer)) {
|
||||
codePoints.add((int) l);
|
||||
}
|
||||
} catch (Throwable t1) {
|
||||
try {
|
||||
ms3.close();
|
||||
} catch (Throwable t2) {
|
||||
t1.addSuppressed(t2);
|
||||
}
|
||||
throw t1;
|
||||
}
|
||||
ms3.close();
|
||||
|
||||
for (int skippedCodePoint : skippCodePoints) {
|
||||
codePoints.remove(skippedCodePoint);
|
||||
}
|
||||
for (int codePoint : codePoints) {
|
||||
int i = FreeType.FT_Get_Char_Index(fT_Face, codePoint);
|
||||
if (i != 0) {
|
||||
FreeTypeUtils.checkFatalError(FreeType.FT_Load_Glyph(fT_Face, i, 4194312), "Loading glyph");
|
||||
FT_GlyphSlot fT_GlyphSlot = Objects.requireNonNull(fT_Face.glyph(), "Glyph not initialized");
|
||||
float advance = FreeTypeUtils.getAdvance(fT_GlyphSlot.advance());
|
||||
char[] theCharacter = Character.toChars(codePoint);
|
||||
String unicode = CharacterUtils.char2Unicode(theCharacter);
|
||||
yml.set(unicode, (advance) / oversample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yml.save(ttfCache);
|
||||
} catch (Exception e) {
|
||||
synchronized(FreeTypeUtils.LOCK) {
|
||||
if (fT_Face != null) {
|
||||
FreeType.FT_Done_Face(fT_Face);
|
||||
}
|
||||
}
|
||||
MemoryUtil.memFree(byteBuffer);
|
||||
throw e;
|
||||
}
|
||||
|
||||
// free resources
|
||||
MemoryUtil.memFree(byteBuffer);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
registerCharacterFontData(id, ttfCache, (properties) -> {
|
||||
@@ -916,6 +1025,7 @@ public class AdvanceManagerImpl implements AdvanceManager {
|
||||
public void disable() {
|
||||
this.unload();
|
||||
this.charFontWidthDataMap.clear();
|
||||
FreeTypeUtils.release();
|
||||
}
|
||||
|
||||
private void loadTemplates() {
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.backend.util;
|
||||
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.lwjgl.util.freetype.FT_Vector;
|
||||
import org.lwjgl.util.freetype.FreeType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
|
||||
public class FreeTypeUtils {
|
||||
|
||||
public static final Object LOCK = new Object();
|
||||
private static long freeType = 0L;
|
||||
|
||||
public FreeTypeUtils() {
|
||||
}
|
||||
|
||||
public static long initialize() {
|
||||
synchronized(LOCK) {
|
||||
if (freeType == 0L) {
|
||||
MemoryStack memoryStack = MemoryStack.stackPush();
|
||||
try {
|
||||
PointerBuffer pointerBuffer = memoryStack.mallocPointer(1);
|
||||
checkFatalError(FreeType.FT_Init_FreeType(pointerBuffer), "Initializing FreeType library");
|
||||
freeType = pointerBuffer.get();
|
||||
} catch (Throwable t1) {
|
||||
try {
|
||||
memoryStack.close();
|
||||
} catch (Throwable t2) {
|
||||
t1.addSuppressed(t2);
|
||||
}
|
||||
throw t1;
|
||||
}
|
||||
memoryStack.close();
|
||||
}
|
||||
return freeType;
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkFatalError(int code, String description) {
|
||||
if (code != 0) {
|
||||
String var10002 = getErrorMessage(code);
|
||||
throw new IllegalStateException("FreeType error: " + var10002 + " (" + description + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getErrorMessage(int code) {
|
||||
String string = FreeType.FT_Error_String(code);
|
||||
return string != null ? string : "Unrecognized error: 0x" + Integer.toHexString(code);
|
||||
}
|
||||
|
||||
public static FT_Vector setShift(FT_Vector vec, float x, float y) {
|
||||
long xShift = Math.round(x * 64.0F);
|
||||
long yShift = Math.round(y * 64.0F);
|
||||
return vec.set(xShift, yShift);
|
||||
}
|
||||
|
||||
public static float getAdvance(FT_Vector vec) {
|
||||
return (float) vec.x() / 64.0F;
|
||||
}
|
||||
|
||||
public static void release() {
|
||||
synchronized(LOCK) {
|
||||
if (freeType != 0L) {
|
||||
FreeType.FT_Done_Library(freeType);
|
||||
freeType = 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ByteBuffer readResource(InputStream inputStream) throws IOException {
|
||||
ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream);
|
||||
if (readableByteChannel instanceof SeekableByteChannel seekableByteChannel) {
|
||||
return readResource(readableByteChannel, (int)seekableByteChannel.size() + 1);
|
||||
} else {
|
||||
return readResource(readableByteChannel, 8192);
|
||||
}
|
||||
}
|
||||
|
||||
private static ByteBuffer readResource(ReadableByteChannel channel, int bufSize) throws IOException {
|
||||
ByteBuffer byteBuffer = MemoryUtil.memAlloc(bufSize);
|
||||
try {
|
||||
while(channel.read(byteBuffer) != -1) {
|
||||
if (!byteBuffer.hasRemaining()) {
|
||||
byteBuffer = MemoryUtil.memRealloc(byteBuffer, byteBuffer.capacity() * 2);
|
||||
}
|
||||
}
|
||||
return byteBuffer;
|
||||
} catch (IOException e) {
|
||||
MemoryUtil.memFree(byteBuffer);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ dependencies {
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
archiveFileName = "CustomNameplates-bukkit-${rootProject.properties["project_version"]}.jar"
|
||||
archiveFileName = "CustomNameplates-Bukkit-${rootProject.properties["project_version"]}.jar"
|
||||
destinationDirectory.set(file("$rootDir/target"))
|
||||
relocate("net.kyori", "net.momirealms.customnameplates.libraries")
|
||||
relocate("org.incendo", "net.momirealms.customnameplates.libraries")
|
||||
@@ -62,7 +62,6 @@ tasks {
|
||||
relocate("com.github.benmanes.caffeine", "net.momirealms.customnameplates.libraries.caffeine")
|
||||
relocate("net.objecthunter.exp4j", "net.momirealms.customnameplates.libraries.exp4j")
|
||||
relocate("redis.clients.jedis", "net.momirealms.customnameplates.libraries.jedis")
|
||||
relocate("org.apache.commons.io", "net.momirealms.customnameplates.libraries.commons.io")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import net.momirealms.customnameplates.backend.placeholder.PlaceholderManagerImp
|
||||
import net.momirealms.customnameplates.backend.storage.StorageManagerImpl;
|
||||
import net.momirealms.customnameplates.bukkit.command.BukkitCommandManager;
|
||||
import net.momirealms.customnameplates.bukkit.compatibility.NameplatesExpansion;
|
||||
import net.momirealms.customnameplates.bukkit.compatibility.cosmetic.MagicCosmeticsHook;
|
||||
import net.momirealms.customnameplates.bukkit.requirement.BukkitRequirementManager;
|
||||
import net.momirealms.customnameplates.bukkit.scheduler.BukkitSchedulerAdapter;
|
||||
import net.momirealms.customnameplates.common.dependency.Dependency;
|
||||
@@ -116,7 +117,8 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
|
||||
Dependency.MONGODB_DRIVER_CORE, Dependency.MONGODB_DRIVER_SYNC, Dependency.MONGODB_DRIVER_BSON,
|
||||
Dependency.HIKARI_CP,
|
||||
Dependency.BYTE_BUDDY,
|
||||
Dependency.COMMONS_IO
|
||||
Dependency.COMMONS_IO,
|
||||
Dependency.LWJGL, Dependency.LWJGL_NATIVES, Dependency.LWJGL_FREETYPE, Dependency.LWJGL_FREETYPE_NATIVES
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -173,6 +175,12 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||
new NameplatesExpansion(this).register();
|
||||
}
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("MagicCosmetics")) {
|
||||
try {
|
||||
Bukkit.getPluginManager().registerEvents(new MagicCosmeticsHook(this), this.getBootstrap());
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
boolean downloadFromPolymart = polymart.equals("1");
|
||||
boolean downloadFromBBB = buildByBit.equals("true");
|
||||
|
||||
@@ -27,6 +27,8 @@ package net.momirealms.customnameplates.common.dependency;
|
||||
|
||||
import net.momirealms.customnameplates.common.dependency.relocation.Relocation;
|
||||
import net.momirealms.customnameplates.common.plugin.CustomNameplatesProperties;
|
||||
import net.momirealms.customnameplates.common.util.Architecture;
|
||||
import net.momirealms.customnameplates.common.util.Platform;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
@@ -282,7 +284,48 @@ public enum Dependency {
|
||||
"maven",
|
||||
"commons-io",
|
||||
Relocation.of("commons", "org{}apache{}commons")
|
||||
);
|
||||
),
|
||||
LWJGL(
|
||||
"org{}lwjgl",
|
||||
"lwjgl",
|
||||
"maven",
|
||||
"lwjgl"
|
||||
),
|
||||
LWJGL_NATIVES(
|
||||
"org{}lwjgl",
|
||||
"lwjgl",
|
||||
"maven",
|
||||
"lwjgl-natives-" + getNativesPath(),
|
||||
"-natives-" + getNativesPath()
|
||||
) {
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return Dependency.LWJGL.getVersion();
|
||||
}
|
||||
},
|
||||
LWJGL_FREETYPE(
|
||||
"org{}lwjgl",
|
||||
"lwjgl-freetype",
|
||||
"maven",
|
||||
"lwjgl-freetype"
|
||||
) {
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return Dependency.LWJGL.getVersion();
|
||||
}
|
||||
},
|
||||
LWJGL_FREETYPE_NATIVES(
|
||||
"org{}lwjgl",
|
||||
"lwjgl-freetype",
|
||||
"maven",
|
||||
"lwjgl-freetype-natives-" + getNativesPath(),
|
||||
"-natives-" + getNativesPath()
|
||||
) {
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return Dependency.LWJGL.getVersion();
|
||||
}
|
||||
};
|
||||
|
||||
private final List<Relocation> relocations;
|
||||
private final String repo;
|
||||
@@ -367,4 +410,12 @@ public enum Dependency {
|
||||
public String getRepo() {
|
||||
return repo;
|
||||
}
|
||||
|
||||
private static String getNativesPath() {
|
||||
String base = Platform.get().getNativePath();
|
||||
if (Architecture.get() != Architecture.X64) {
|
||||
base += "-" + Architecture.get().getNativePath();
|
||||
}
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ public final class Relocation {
|
||||
return new Relocation(pattern.replace("{}", "."), RELOCATION_PREFIX + id);
|
||||
}
|
||||
|
||||
public static Relocation of(String id, String pattern, String prefix) {
|
||||
return new Relocation(pattern.replace("{}", "."), prefix.replace("{}", ".") + "." + RELOCATION_PREFIX + id);
|
||||
}
|
||||
|
||||
private final String pattern;
|
||||
private final String relocatedPattern;
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) <2024> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.common.util;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum Architecture {
|
||||
|
||||
X64(true),
|
||||
X86(false),
|
||||
ARM64(true),
|
||||
ARM32(false),
|
||||
PPC64LE(true),
|
||||
RISCV64(true);
|
||||
|
||||
static final Architecture current;
|
||||
final boolean is64Bit;
|
||||
|
||||
Architecture(boolean is64Bit) {
|
||||
this.is64Bit = is64Bit;
|
||||
}
|
||||
|
||||
public String getNativePath() {
|
||||
return name().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
public static Architecture get() {
|
||||
return current;
|
||||
}
|
||||
|
||||
static {
|
||||
String osArch = System.getProperty("os.arch");
|
||||
boolean is64Bit = osArch.contains("64") || osArch.startsWith("armv8");
|
||||
if (!osArch.startsWith("arm") && !osArch.startsWith("aarch")) {
|
||||
if (osArch.startsWith("ppc")) {
|
||||
if (!"ppc64le".equals(osArch)) {
|
||||
throw new UnsupportedOperationException("Only PowerPC 64 LE is supported.");
|
||||
}
|
||||
current = PPC64LE;
|
||||
} else if (osArch.startsWith("riscv")) {
|
||||
if (!"riscv64".equals(osArch)) {
|
||||
throw new UnsupportedOperationException("Only RISC-V 64 is supported.");
|
||||
}
|
||||
current = RISCV64;
|
||||
} else {
|
||||
current = is64Bit ? X64 : X86;
|
||||
}
|
||||
} else {
|
||||
current = is64Bit ? ARM64 : ARM32;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2024> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.common.util;
|
||||
|
||||
public class OSUtils {
|
||||
|
||||
public static String getOSName() {
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
return "windows";
|
||||
} else if (os.contains("mac")) {
|
||||
return "macos";
|
||||
} else if (os.contains("nux") || os.contains("nix")) {
|
||||
return "linux";
|
||||
} else if (os.contains("freebsd")) {
|
||||
return "freebsd";
|
||||
} else {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) <2024> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.common.util;
|
||||
|
||||
public enum Platform {
|
||||
|
||||
FREEBSD("FreeBSD", "freebsd"),
|
||||
LINUX("Linux", "linux"),
|
||||
MACOS("macOS", "macos"),
|
||||
WINDOWS("Windows", "windows");
|
||||
|
||||
private static final Platform current;
|
||||
private final String name;
|
||||
private final String nativePath;
|
||||
|
||||
Platform(String name, String nativePath) {
|
||||
this.name = name;
|
||||
this.nativePath = nativePath;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getNativePath() {
|
||||
return nativePath;
|
||||
}
|
||||
|
||||
public static Platform get() {
|
||||
return current;
|
||||
}
|
||||
|
||||
static {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.startsWith("Windows")) {
|
||||
current = WINDOWS;
|
||||
} else if (osName.startsWith("FreeBSD")) {
|
||||
current = FREEBSD;
|
||||
} else if (!osName.startsWith("Linux") && !osName.startsWith("SunOS") && !osName.startsWith("Unix")) {
|
||||
if (!osName.startsWith("Mac OS X") && !osName.startsWith("Darwin")) {
|
||||
throw new LinkageError("Unknown platform: " + osName);
|
||||
}
|
||||
current = MACOS;
|
||||
} else {
|
||||
current = LINUX;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,5 @@ jedis=${jedis_version}
|
||||
h2-driver=${h2_driver_version}
|
||||
sqlite-driver=${sqlite_driver_version}
|
||||
byte-buddy=${byte_buddy_version}
|
||||
commons-io=${commons_io_version}
|
||||
commons-io=${commons_io_version}
|
||||
lwjgl=${lwjgl_version}
|
||||
@@ -38,6 +38,8 @@ dependencies {
|
||||
compileOnly("org.geysermc.geyser:api:2.4.2-SNAPSHOT")
|
||||
// Floodgate
|
||||
compileOnly("org.geysermc.floodgate:api:2.2.3-SNAPSHOT")
|
||||
// Cosmetics
|
||||
compileOnly("com.github.FrancoBM12:API-MagicCosmetics:2.2.9")
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.bukkit.compatibility.cosmetic;
|
||||
|
||||
import com.francobm.magicosmetics.api.Cosmetic;
|
||||
import com.francobm.magicosmetics.api.CosmeticType;
|
||||
import com.francobm.magicosmetics.cache.PlayerData;
|
||||
import com.francobm.magicosmetics.cache.cosmetics.Hat;
|
||||
import com.francobm.magicosmetics.events.*;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.api.feature.tag.TagRenderer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MagicCosmeticsHook implements Listener {
|
||||
|
||||
private final CustomNameplates plugin;
|
||||
|
||||
public MagicCosmeticsHook(CustomNameplates plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onChangeCos(CosmeticChangeEquipEvent event) {
|
||||
final Cosmetic cosmetic = event.getNewCosmetic();
|
||||
final Player player = event.getPlayer();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
CNPlayer cnPlayer = plugin.getPlayer(player.getUniqueId());
|
||||
if (cnPlayer != null) {
|
||||
TagRenderer renderer = plugin.getUnlimitedTagManager().getTagRender(cnPlayer);
|
||||
if (renderer != null) {
|
||||
renderer.hatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onEnterBlackListWorld(PlayerChangeBlacklistEvent event) {
|
||||
var player = event.getPlayer();
|
||||
CNPlayer cnPlayer = plugin.getPlayer(player.getUniqueId());
|
||||
if (cnPlayer != null) {
|
||||
TagRenderer renderer = plugin.getUnlimitedTagManager().getTagRender(cnPlayer);
|
||||
if (renderer != null) {
|
||||
if (event.isInWorldBlacklist()) {
|
||||
renderer.hatOffset(0);
|
||||
} else {
|
||||
PlayerData playerData = PlayerData.getPlayer(player);
|
||||
if (playerData != null) {
|
||||
final Cosmetic cosmetic = playerData.getHat();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
renderer.hatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onEquip(CosmeticEquipEvent event) {
|
||||
final Cosmetic cosmetic = event.getCosmetic();
|
||||
final Player player = event.getPlayer();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
CNPlayer cnPlayer = plugin.getPlayer(player.getUniqueId());
|
||||
if (cnPlayer != null) {
|
||||
TagRenderer renderer = plugin.getUnlimitedTagManager().getTagRender(cnPlayer);
|
||||
if (renderer != null) {
|
||||
renderer.hatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onUnEquip(CosmeticUnEquipEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (event.getCosmeticType() == CosmeticType.HAT) {
|
||||
CNPlayer cnPlayer = plugin.getPlayer(player.getUniqueId());
|
||||
if (cnPlayer != null) {
|
||||
TagRenderer renderer = plugin.getUnlimitedTagManager().getTagRender(cnPlayer);
|
||||
if (renderer != null) {
|
||||
renderer.hatOffset(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onDataLoaded(PlayerDataLoadEvent event) {
|
||||
for (Cosmetic cosmetic : event.getEquippedCosmetics()) {
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
PlayerData playerData = event.getPlayerData();
|
||||
plugin.getScheduler().asyncLater(() -> {
|
||||
CNPlayer cnPlayer = plugin.getPlayer(playerData.getUniqueId());
|
||||
if (cnPlayer != null) {
|
||||
TagRenderer renderer = plugin.getUnlimitedTagManager().getTagRender(cnPlayer);
|
||||
if (renderer != null) {
|
||||
renderer.hatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
}
|
||||
}
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ placeholder_api_version=2.11.6
|
||||
vault_version=1.7
|
||||
guava_version=33.2.0-jre
|
||||
commons_io_version=2.17.0
|
||||
lwjgl_version=3.3.4
|
||||
|
||||
# Proxy settings
|
||||
#systemProp.socks.proxyHost=127.0.0.1
|
||||
|
||||
Reference in New Issue
Block a user