mirror of
https://github.com/Xiao-MoMi/Custom-Nameplates.git
synced 2025-12-19 15:09:23 +00:00
improve spectator mode
This commit is contained in:
@@ -61,11 +61,6 @@ public abstract class AbstractCNPlayer implements CNPlayer {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有处于激活状态的变量统筹起来并返回一个更新任务
|
||||
*
|
||||
* @return 更新任务
|
||||
*/
|
||||
@Override
|
||||
public List<Placeholder> activePlaceholdersToRefresh() {
|
||||
Placeholder[] activePlaceholders = activePlaceholders();
|
||||
|
||||
@@ -81,6 +81,14 @@ public interface CNPlayer {
|
||||
*/
|
||||
boolean isOnline();
|
||||
|
||||
/**
|
||||
*
|
||||
* Checks if the player is on spectator mode
|
||||
*
|
||||
* @return true if the player is on spectator mode, false otherwise
|
||||
*/
|
||||
boolean isSpectator();
|
||||
|
||||
/**
|
||||
* Returns the scale of the player.
|
||||
*
|
||||
|
||||
@@ -118,15 +118,15 @@ public abstract class AbstractTag implements Tag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerCrouching(boolean isCrouching) {
|
||||
public void onOpacityChange(boolean dark) {
|
||||
for (CNPlayer viewer : viewerArray) {
|
||||
onPlayerCrouching(viewer, isCrouching);
|
||||
onOpacityChange(viewer, dark);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerCrouching(CNPlayer viewer, boolean isCrouching) {
|
||||
Consumer<List<Object>> modifiers = CustomNameplates.getInstance().getPlatform().createOpacityModifier(isCrouching ? 64 : opacity());
|
||||
public void onOpacityChange(CNPlayer viewer, boolean dark) {
|
||||
Consumer<List<Object>> modifiers = CustomNameplates.getInstance().getPlatform().createOpacityModifier(dark ? 64 : opacity());
|
||||
Object packet = CustomNameplates.getInstance().getPlatform().updateTextDisplayPacket(entityID, List.of(modifiers));
|
||||
CustomNameplates.getInstance().getPacketSender().sendPacket(viewer, packet);
|
||||
}
|
||||
|
||||
@@ -150,20 +150,9 @@ public interface Tag {
|
||||
*/
|
||||
double getTextHeight(CNPlayer viewer);
|
||||
|
||||
/**
|
||||
* Updates the tag state when the player crouches.
|
||||
*
|
||||
* @param isCrouching true if the player is crouching, false otherwise
|
||||
*/
|
||||
void onPlayerCrouching(boolean isCrouching);
|
||||
void onOpacityChange(boolean dark);
|
||||
|
||||
/**
|
||||
* Updates the tag state when the player crouches for a specific viewer.
|
||||
*
|
||||
* @param viewer the player to update
|
||||
* @param isCrouching true if the player is crouching, false otherwise
|
||||
*/
|
||||
void onPlayerCrouching(CNPlayer viewer, boolean isCrouching);
|
||||
void onOpacityChange(CNPlayer viewer, boolean dark);
|
||||
|
||||
/**
|
||||
* Updates the tag scale when the player's scale changes.
|
||||
|
||||
@@ -112,4 +112,14 @@ public interface UnlimitedTagManager extends Reloadable {
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
void onPlayerAttributeSet(CNPlayer owner, CNPlayer viewer, double scale);
|
||||
|
||||
/**
|
||||
* Internal method for updating a player's game mode
|
||||
*
|
||||
* @param owner the player who owns the tags
|
||||
* @param viewer the player viewing the tags
|
||||
* @param isSpectator true if the player is a spectator, false otherwise
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
void onPlayerGameModeChange(CNPlayer owner, CNPlayer viewer, boolean isSpectator);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class Tracker {
|
||||
|
||||
private boolean isCrouching;
|
||||
private double scale;
|
||||
private boolean isSpectator;
|
||||
private final CNPlayer tracker;
|
||||
|
||||
private final CopyOnWriteArrayList<Integer> passengerIDs = new CopyOnWriteArrayList<>();
|
||||
@@ -54,6 +55,14 @@ public class Tracker {
|
||||
isCrouching = crouching;
|
||||
}
|
||||
|
||||
public boolean isSpectator() {
|
||||
return isSpectator;
|
||||
}
|
||||
|
||||
public void setSpectator(boolean spectator) {
|
||||
isSpectator = spectator;
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,10 @@ public class BubbleTag extends AbstractTag {
|
||||
return canShow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpacityChange(CNPlayer viewer, boolean dark) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canShow(CNPlayer viewer) {
|
||||
if (!viewer.isMet(owner, manager.viewBubbleRequirements())) {
|
||||
|
||||
@@ -63,7 +63,7 @@ public class NameTag extends AbstractTag implements RelationalFeature {
|
||||
owner.position().add(0,(1.8 + (affectedByCrouching() && tracker.isCrouching() && !owner.isFlying() ? -0.3 : 0) + renderer.hatOffset()) * (affectedByScaling() ? tracker.getScale() : 1),0),
|
||||
0f, 0f, 0d,
|
||||
0, 0, 0,
|
||||
component, config.backgroundColor(), config.opacity(), config.hasShadow(), config.isSeeThrough(), config.useDefaultBackgroundColor(),
|
||||
component, config.backgroundColor(), opacity(), config.hasShadow(), config.isSeeThrough(), config.useDefaultBackgroundColor(),
|
||||
config.alignment(), config.viewRange(), config.shadowRadius(), config.shadowStrength(),
|
||||
(affectedByScaling() ? scale(viewer).multiply(tracker.getScale()) : scale(viewer)),
|
||||
(affectedByScaling() ? translation(viewer).multiply(tracker.getScale()) : translation(viewer)),
|
||||
@@ -144,7 +144,7 @@ public class NameTag extends AbstractTag implements RelationalFeature {
|
||||
@Override
|
||||
public double getTextHeight(CNPlayer viewer) {
|
||||
String current = currentText.render(viewer);
|
||||
Tracker tracker = viewer.getTracker(owner);
|
||||
Tracker tracker = owner.getTracker(viewer);
|
||||
int lines = CustomNameplates.getInstance().getAdvanceManager().getLines(current, config.lineWidth());
|
||||
return ((lines * (9+1) + config.translation().y()) * config.scale().y() * (config.affectedByScaling() ? tracker.getScale() : 1)) / 40;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ public class NameTag extends AbstractTag implements RelationalFeature {
|
||||
|
||||
@Override
|
||||
public byte opacity() {
|
||||
return config.opacity();
|
||||
return owner.isSpectator() || (owner.isCrouching() && affectedByCrouching()) ? 64 : config.opacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -71,32 +71,23 @@ public class TagRendererImpl implements TagRenderer {
|
||||
HashSet<CNPlayer> playersToUpdatePassengers = new HashSet<>();
|
||||
for (Tag display : tags) {
|
||||
boolean canShow = display.canShow();
|
||||
// 能大众显示
|
||||
if (canShow) {
|
||||
// 当前大众显示
|
||||
if (display.isShown()) {
|
||||
for (CNPlayer nearby : owner.nearbyPlayers()) {
|
||||
// 如果已经展示了
|
||||
if (display.isShown(nearby)) {
|
||||
// 不满足条件就撤掉
|
||||
if (!display.canShow(nearby)) {
|
||||
display.hide(nearby);
|
||||
}
|
||||
} else {
|
||||
// 未展示,则检测条件,可以就上
|
||||
if (display.canShow(nearby)) {
|
||||
display.show(nearby);
|
||||
playersToUpdatePassengers.add(nearby);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新一下文字顺序,放在后面是为了防止已经被hide的玩家多收一个包
|
||||
display.tick();
|
||||
} else {
|
||||
// 之前隐藏,现在开始大众显示
|
||||
// 需要重置文字顺序
|
||||
display.init();
|
||||
// 更新一下文字顺序
|
||||
display.tick();
|
||||
display.show();
|
||||
for (CNPlayer nearby : owner.nearbyPlayers()) {
|
||||
@@ -107,8 +98,6 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 不能展示的情况
|
||||
// 如果已经展示了,就咔掉所有玩家
|
||||
if (display.isShown()) {
|
||||
display.hide();
|
||||
}
|
||||
@@ -264,15 +253,15 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
|
||||
public void handleEntityDataChange(CNPlayer another, boolean isCrouching) {
|
||||
Tracker properties = owner.getTracker(another);
|
||||
Tracker tracker = owner.getTracker(another);
|
||||
// should never be null
|
||||
if (properties == null) return;
|
||||
properties.setCrouching(isCrouching);
|
||||
if (tracker == null) return;
|
||||
tracker.setCrouching(isCrouching);
|
||||
for (Tag display : this.tags) {
|
||||
if (display.affectedByCrouching()) {
|
||||
if (display.isShown()) {
|
||||
if (display.isShown(another)) {
|
||||
display.onPlayerCrouching(another, isCrouching);
|
||||
display.onOpacityChange(another, isCrouching || tracker.isSpectator());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,11 +269,10 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
|
||||
public void handleAttributeChange(CNPlayer another, double scale) {
|
||||
boolean updatePassengers = false;
|
||||
Tracker properties = owner.getTracker(another);
|
||||
Tracker tracker = owner.getTracker(another);
|
||||
// should never be null
|
||||
if (properties == null) return;
|
||||
properties.setScale(scale);
|
||||
if (tracker == null) return;
|
||||
tracker.setScale(scale);
|
||||
for (Tag display : this.tags) {
|
||||
if (display.affectedByScaling()) {
|
||||
if (display.isShown()) {
|
||||
@@ -295,4 +283,18 @@ public class TagRendererImpl implements TagRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleGameModeChange(CNPlayer another, boolean isSpectator) {
|
||||
Tracker tracker = owner.getTracker(another);
|
||||
// can be null
|
||||
if (tracker == null) return;
|
||||
tracker.setSpectator(isSpectator);
|
||||
for (Tag display : this.tags) {
|
||||
if (display.isShown()) {
|
||||
if (display.isShown(another)) {
|
||||
display.onOpacityChange(another, isSpectator || tracker.isCrouching());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager, JoinQuitLis
|
||||
Tracker tracker = player.addPlayerToTracker(player);
|
||||
tracker.setScale(player.scale());
|
||||
tracker.setCrouching(player.isCrouching());
|
||||
tracker.setSpectator(player.isSpectator());
|
||||
plugin.getUnlimitedTagManager().onAddPlayer(player, player);
|
||||
((AbstractCNPlayer) player).setPreviewing(true);
|
||||
}
|
||||
@@ -179,6 +180,14 @@ public class UnlimitedTagManagerImpl implements UnlimitedTagManager, JoinQuitLis
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerGameModeChange(CNPlayer owner, CNPlayer viewer, boolean isSpectator) {
|
||||
TagRendererImpl controller = tagRenderers.get(owner.uuid());
|
||||
if (controller != null) {
|
||||
controller.handleGameModeChange(viewer, isSpectator);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
plugin.getConfigManager().saveResource("configs" + File.separator + "nameplate.yml");
|
||||
YamlDocument document = plugin.getConfigManager().loadData(new File(plugin.getDataDirectory().toFile(), "configs" + File.separator + "nameplate.yml"));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Requirements for sending the bubble
|
||||
sender-requirements:
|
||||
permission: bubbles.send
|
||||
'!gamemode': spectator
|
||||
potion-effect: "INVISIBILITY<0"
|
||||
|
||||
viewer-requirements:
|
||||
|
||||
@@ -20,6 +20,7 @@ package net.momirealms.customnameplates.bukkit;
|
||||
import net.momirealms.customnameplates.api.AbstractCNPlayer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.api.util.Vector3;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
@@ -96,6 +97,11 @@ public class BukkitCNPlayer extends AbstractCNPlayer {
|
||||
return player.isOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpectator() {
|
||||
return player.getGameMode() == GameMode.SPECTATOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> passengers() {
|
||||
return player.getPassengers().stream().map(Entity::getEntityId).collect(Collectors.toSet());
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitPlatform implements Platform {
|
||||
@@ -178,6 +179,29 @@ public class BukkitPlatform implements Platform {
|
||||
}
|
||||
}, "PacketPlayOutEntityDestroy", "ClientboundRemoveEntitiesPacket");
|
||||
|
||||
registerPacketConsumer((player, event, packet) -> {
|
||||
try {
|
||||
EnumSet<?> enums = (EnumSet<?>) Reflections.field$ClientboundPlayerInfoUpdatePacket$actions.get(packet);
|
||||
if (enums == null) return;
|
||||
if (!enums.contains(Reflections.enum$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_GAME_MODE)) return;
|
||||
List<Object> entries = (List<Object>) Reflections.field$ClientboundPlayerInfoUpdatePacket$entries.get(packet);
|
||||
for (Object entry : entries) {
|
||||
UUID uuid = (UUID) Reflections.field$ClientboundPlayerInfoUpdatePacket$Entry$profileId.get(entry);
|
||||
if (uuid == null) continue;
|
||||
Object gameType = Reflections.field$ClientboundPlayerInfoUpdatePacket$Entry$gameMode.get(entry);
|
||||
if (gameType == null) continue;
|
||||
int mode = (int) Reflections.method$GameType$getId.invoke(gameType);
|
||||
boolean isSpectator = mode == 3;
|
||||
CNPlayer another = CustomNameplates.getInstance().getPlayer(uuid);
|
||||
if (another != null) {
|
||||
CustomNameplates.getInstance().getUnlimitedTagManager().onPlayerGameModeChange(another, player, isSpectator);
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CustomNameplates.getInstance().getPluginLogger().severe("Failed to handle ClientboundPlayerInfoUpdatePacket", e);
|
||||
}
|
||||
}, "ClientboundPlayerInfoUpdatePacket");
|
||||
|
||||
// for cosmetic plugin compatibility
|
||||
registerPacketConsumer((player, event, packet) -> {
|
||||
try {
|
||||
|
||||
@@ -49,6 +49,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
|
||||
new DebugPerformanceCommand(this, plugin),
|
||||
new DebugWidthCommand(this, plugin),
|
||||
new DebugLinesCommand(this, plugin),
|
||||
new DebugTestCommand(this, plugin),
|
||||
new NameplatesEquipCommand(this, plugin),
|
||||
new NameplatesUnEquipCommand(this, plugin),
|
||||
new NameplatesListCommand(this, plugin),
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bukkit.command.feature;
|
||||
|
||||
import net.momirealms.customnameplates.bukkit.BukkitCustomNameplates;
|
||||
import net.momirealms.customnameplates.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customnameplates.common.command.CustomNameplatesCommandManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
|
||||
public class DebugTestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public DebugTestCommand(CustomNameplatesCommandManager<CommandSender> commandManager, BukkitCustomNameplates plugin) {
|
||||
super(commandManager, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.handler(context -> {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "debug_test";
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -741,4 +742,106 @@ public class Reflections {
|
||||
clazz$AttributeModifier, double.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundGameEventPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundGameEventPacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayOutGameStateChange")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundGameEventPacket$Type = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundGameEventPacket$Type"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayOutGameStateChange$a")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundGameEventPacket$event = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundGameEventPacket, clazz$ClientboundGameEventPacket$Type, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundGameEventPacket$param = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundGameEventPacket, float.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundGameEventPacket$Type$id = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundGameEventPacket$Type, int.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundPlayerInfoUpdatePacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundPlayerInfoUpdatePacket")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundPlayerInfoUpdatePacket$actions = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundPlayerInfoUpdatePacket, EnumSet.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundPlayerInfoUpdatePacket$entries = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundPlayerInfoUpdatePacket, List.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundPlayerInfoUpdatePacket$Action = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundPlayerInfoUpdatePacket$Action"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundPlayerInfoUpdatePacket$a")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Enum<?> enum$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_GAME_MODE;
|
||||
|
||||
|
||||
static {
|
||||
Enum<?> updateGameMode;
|
||||
try {
|
||||
updateGameMode = Enum.valueOf((Class<Enum>) clazz$ClientboundPlayerInfoUpdatePacket$Action, "UPDATE_GAME_MODE");
|
||||
} catch (Exception e) {
|
||||
updateGameMode = Enum.valueOf((Class<Enum>) clazz$ClientboundPlayerInfoUpdatePacket$Action, "c");
|
||||
}
|
||||
enum$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_GAME_MODE = updateGameMode;
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$ClientboundPlayerInfoUpdatePacket$Entry = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundPlayerInfoUpdatePacket$Entry"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundPlayerInfoUpdatePacket$b")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$GameType = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.GameType"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.EnumGamemode")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundPlayerInfoUpdatePacket$Entry$gameMode = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundPlayerInfoUpdatePacket$Entry, clazz$GameType, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundPlayerInfoUpdatePacket$Entry$profileId = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundPlayerInfoUpdatePacket$Entry, UUID.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$GameType$getId = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$GameType, new String[] { "getId", "a" }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -133,4 +133,12 @@ bubbles_list:
|
||||
enable: true
|
||||
permission: bubbles.command.list
|
||||
usage:
|
||||
- /bubbles list
|
||||
- /bubbles list
|
||||
|
||||
# A command to test some stuffs
|
||||
# Usage: [COMMAND]
|
||||
debug_test:
|
||||
enable: false
|
||||
permission: nameplates.command.debug.test
|
||||
usage:
|
||||
- /nameplates debug test
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=3.0.0-beta-1
|
||||
project_version=3.0.0-beta-2
|
||||
config_version=36
|
||||
project_group=net.momirealms
|
||||
|
||||
|
||||
Reference in New Issue
Block a user