forked from SlimefunGuguProject/Slimefun4
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Integration): Add Geyser Integration
- Loading branch information
1 parent
5604717
commit 5ca9e92
Showing
5 changed files
with
183 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
src/main/java/me/qscbm/slimefun4/integrations/GeyserIntegration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package me.qscbm.slimefun4.integrations; | ||
|
||
import io.github.bakedlibs.dough.config.Config; | ||
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; | ||
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; | ||
import me.qscbm.slimefun4.utils.NBTUtils; | ||
import org.bukkit.Material; | ||
import org.bukkit.inventory.ItemStack; | ||
import org.bukkit.inventory.meta.ItemMeta; | ||
import org.bukkit.inventory.meta.SkullMeta; | ||
|
||
import java.io.File; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class GeyserIntegration { | ||
public void register() { | ||
Slimefun.logger().info("开始加载自定义粘液科技Geyser支持"); | ||
|
||
Config config = new Config(new File("plugins/Geyser-Spigot/custom-skulls.yml")); | ||
List<String> l = config.getStringList("skin-hashes"); | ||
int successCount = 0; | ||
int errorCount = 0; | ||
for (SlimefunItem slimefunItem : Slimefun.getRegistry().getAllSlimefunItems()) { | ||
ItemStack itemStack = slimefunItem.getItem(); | ||
if (itemStack.getType() != Material.PLAYER_HEAD) { | ||
continue; | ||
} | ||
ItemMeta m = itemStack.getItemMeta(); | ||
if (!(m instanceof SkullMeta meta)) { | ||
errorCount++; | ||
continue; | ||
} | ||
String textureCode = NBTUtils.getTexture(meta); | ||
if (textureCode == null) { | ||
errorCount++; | ||
continue; | ||
} | ||
String[] ts = textureCode.split("/"); | ||
String hash = ts[ts.length - 1]; | ||
if (!l.contains(hash)) { | ||
l.add(hash); | ||
} | ||
successCount++; | ||
} | ||
String[] i = {"player-names", "player-uuids", "player-profiles"}; | ||
for (String t : i) { | ||
if (config.getStringList(t).isEmpty()) { | ||
config.setValue(t, new ArrayList<>()); | ||
} | ||
} | ||
config.setValue("skin-hashes", l); | ||
config.save(); | ||
Slimefun.logger().info("成功加载" + successCount + "个自定义头颅"); | ||
Slimefun.logger().info("加载失败" + errorCount + "个自定义头颅"); | ||
Slimefun.logger().warning("完成加载自定义粘液科技Geyser支持,如果不生效请重启服务器"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package me.qscbm.slimefun4.utils; | ||
|
||
import com.destroystokyo.paper.profile.ProfileProperty; | ||
import com.mojang.authlib.GameProfile; | ||
import com.mojang.authlib.properties.Property; | ||
import io.github.bakedlibs.dough.reflection.ReflectionUtils; | ||
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; | ||
import org.bukkit.Bukkit; | ||
import org.bukkit.inventory.meta.SkullMeta; | ||
|
||
import java.lang.reflect.Field; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.Base64; | ||
import java.util.Collection; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
public class NBTUtils { | ||
public static final String CRAFTBUKKIT_PACKAGE_NAME = Bukkit.getServer().getClass().getPackage().getName(); | ||
|
||
public static final String VERSION; | ||
|
||
private static final Class<?> CRAFT_SKULL_META_CLAZZ; | ||
|
||
private static final Field SKULL_PROFILE; | ||
|
||
private static final Class<?> RESOLVABLE_PROFILE; | ||
|
||
private static Method RESOLVABLE_PROFILE_GAME_PROFILE_GETTER = null; | ||
|
||
private static final Method PROPERTY_NAME_GETTER; | ||
private static final Method PROPERTY_VALUE_GETTER; | ||
|
||
static { | ||
String detectedVersion = CRAFTBUKKIT_PACKAGE_NAME.substring(CRAFTBUKKIT_PACKAGE_NAME.lastIndexOf('.') + 1); | ||
if (!detectedVersion.startsWith("v")) { | ||
// Paper or something... | ||
detectedVersion = VersionUtils.getBukkitVersion(); | ||
} | ||
VERSION = detectedVersion; | ||
try { | ||
CRAFT_SKULL_META_CLAZZ = Class.forName(CRAFTBUKKIT_PACKAGE_NAME + ".inventory." + "CraftMetaSkull"); | ||
SKULL_PROFILE = CRAFT_SKULL_META_CLAZZ.getDeclaredField("profile"); | ||
SKULL_PROFILE.setAccessible(true); | ||
} catch (ClassNotFoundException | NoSuchFieldException e) { | ||
throw new RuntimeException(e); | ||
} | ||
Class<?> resolvableProfile; | ||
try { | ||
resolvableProfile = Class.forName("net.minecraft.world.item.component.ResolvableProfile"); | ||
RESOLVABLE_PROFILE_GAME_PROFILE_GETTER = ReflectionUtils.getMethod(resolvableProfile, "f"); | ||
} catch (ClassNotFoundException e) { | ||
resolvableProfile = null; | ||
} | ||
RESOLVABLE_PROFILE = resolvableProfile; | ||
PROPERTY_NAME_GETTER = ReflectionUtils.getMethod(Property.class, "getName"); | ||
PROPERTY_VALUE_GETTER = ReflectionUtils.getMethod(Property.class, "getValue"); | ||
} | ||
|
||
public static String getTexture(SkullMeta skullMeta) { | ||
try { | ||
Object pro = SKULL_PROFILE.get(skullMeta); | ||
if (RESOLVABLE_PROFILE != null && RESOLVABLE_PROFILE.isInstance(pro)) { | ||
if (RESOLVABLE_PROFILE_GAME_PROFILE_GETTER != null) { | ||
pro = RESOLVABLE_PROFILE_GAME_PROFILE_GETTER.invoke(pro); | ||
} | ||
} | ||
|
||
if (pro == null) { | ||
return null; | ||
} | ||
GameProfile profile = (GameProfile) pro; | ||
Collection<Property> properties = profile.getProperties().values(); | ||
for (Property prop : properties) { | ||
String texture = null; | ||
if (PROPERTY_NAME_GETTER != null) { | ||
if ("textures".equals(PROPERTY_NAME_GETTER.invoke(prop))) { | ||
texture = new String(Base64.getDecoder().decode((String) PROPERTY_VALUE_GETTER.invoke(prop))); | ||
} | ||
} else { | ||
if ("textures".equals(prop.name())) { | ||
texture = new String(Base64.getDecoder().decode(prop.value())); | ||
} | ||
} | ||
return getMatch(texture, "\\{\"url\":\"(.*?)\"\\}"); | ||
} | ||
return null; | ||
} catch (IllegalAccessException | InvocationTargetException e) { | ||
Slimefun.logger().warning(e.getMessage()); | ||
return null; | ||
} | ||
} | ||
|
||
@SuppressWarnings("SameParameterValue") | ||
private static String getMatch(String string, String regex) { | ||
Pattern pattern = Pattern.compile(regex); | ||
Matcher matcher = pattern.matcher(string); | ||
if (matcher.find()) { | ||
return matcher.group(1); | ||
} else { | ||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters