feat(delta): /delta command, Display tracking budget, global delta config; rewrite README for Delta
Build Delta / Build paperclip jar (push) Failing after 4m52s
Build Delta / Build paperclip jar (push) Failing after 4m52s
This commit is contained in:
@@ -24,6 +24,9 @@ public final class PaperCommands {
|
||||
public static void registerCommands(final MinecraftServer server) {
|
||||
COMMANDS.put("paper", new PaperCommand("paper"));
|
||||
COMMANDS.put("mspt", new MSPTCommand("mspt"));
|
||||
// Delta start - /delta core command
|
||||
COMMANDS.put("delta", new me.sashegdev.delta.DeltaCommand("delta"));
|
||||
// Delta end
|
||||
|
||||
COMMANDS.forEach((s, command) -> {
|
||||
server.server.getCommandMap().register(s, "Paper", command);
|
||||
|
||||
@@ -220,6 +220,10 @@ public class GlobalConfiguration extends ConfigurationPart {
|
||||
@SuppressWarnings("unused") // used in postProcess
|
||||
public ChunkSystem chunkSystem;
|
||||
|
||||
// Delta start - custom core config (paper-global.yml section "delta")
|
||||
public me.sashegdev.delta.DeltaConfig delta;
|
||||
// Delta end
|
||||
|
||||
public class ChunkSystem extends ConfigurationPart {
|
||||
|
||||
public int ioThreads = -1;
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package me.sashegdev.delta;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* /delta — инспекция и настройка патчей Delta.
|
||||
*/
|
||||
public class DeltaCommand extends Command {
|
||||
|
||||
private static final List<String> SUBS = Arrays.asList("status", "displayrange", "reload", "help");
|
||||
|
||||
public DeltaCommand(String name) {
|
||||
super(name);
|
||||
setDescription("Delta core inspection and tuning");
|
||||
setPermission("delta.admin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) {
|
||||
if (!sender.hasPermission("delta.admin")) {
|
||||
sender.sendMessage(Component.text("No permission", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
String sub = args.length == 0 ? "status" : args[0].toLowerCase(Locale.ROOT);
|
||||
|
||||
switch (sub) {
|
||||
case "status" -> {
|
||||
var cfg = io.papermc.paper.configuration.GlobalConfiguration.get().delta;
|
||||
sender.sendMessage(header());
|
||||
sender.sendMessage(line("display range ", cfg.displayTrackingRangeEnabled
|
||||
? cfg.displayTrackingRange + " blocks" : "stock (disabled)"));
|
||||
sender.sendMessage(line("particle budget ", cfg.particleBudgetPerPlayerPerTick <= 0
|
||||
? "off" : cfg.particleBudgetPerPlayerPerTick + " pkts/player/tick"));
|
||||
sender.sendMessage(line("sound budget ", cfg.soundBudgetPerPlayerPerSecond <= 0
|
||||
? "off" : cfg.soundBudgetPerPlayerPerSecond + " pkts/player/sec"));
|
||||
sender.sendMessage(line("extended distance ", cfg.extendedParticleDistanceEnabled
|
||||
? cfg.extendedParticleDistance + " blocks" : "off"));
|
||||
sender.sendMessage(line("decoupled sound ", String.valueOf(cfg.decoupledSoundRangeEnabled)));
|
||||
if (sender instanceof Player p) {
|
||||
sender.sendMessage(line("your view distance", String.valueOf(p.getViewDistance())));
|
||||
}
|
||||
}
|
||||
case "displayrange" -> {
|
||||
var cfg = io.papermc.paper.configuration.GlobalConfiguration.get().delta;
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(line("display range ", cfg.displayTrackingRangeEnabled
|
||||
? cfg.displayTrackingRange + " blocks" : "stock (disabled)"));
|
||||
return true;
|
||||
}
|
||||
int value;
|
||||
try {
|
||||
value = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(Component.text("Not a number: " + args[1], NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
if (value <= 0) {
|
||||
cfg.displayTrackingRangeEnabled = false;
|
||||
sender.sendMessage(Component.text("Display range override disabled (stock Paper)", NamedTextColor.YELLOW));
|
||||
} else {
|
||||
cfg.displayTrackingRangeEnabled = true;
|
||||
cfg.displayTrackingRange = value;
|
||||
sender.sendMessage(Component.text("Display tracking range set to " + value + " blocks", NamedTextColor.GREEN));
|
||||
}
|
||||
io.papermc.paper.configuration.GlobalConfiguration.save();
|
||||
}
|
||||
case "reload" -> {
|
||||
io.papermc.paper.configuration.GlobalConfiguration.get().load();
|
||||
sender.sendMessage(Component.text("Delta config reloaded", NamedTextColor.GREEN));
|
||||
sender.sendMessage(line("display range ", DeltaTracking.describe()));
|
||||
}
|
||||
case "help" -> sender.sendMessage(Component.text(
|
||||
"/delta status | /delta displayrange <blocks|0> | /delta reload", NamedTextColor.YELLOW));
|
||||
default -> sender.sendMessage(Component.text("Unknown subcommand: " + sub, NamedTextColor.RED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||
if (!sender.hasPermission("delta.admin")) {
|
||||
return List.of();
|
||||
}
|
||||
if (args.length == 1) {
|
||||
String low = args[0].toLowerCase(Locale.ROOT);
|
||||
List<String> out = new ArrayList<>();
|
||||
for (String s : SUBS) {
|
||||
if (s.startsWith(low)) {
|
||||
out.add(s);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
if (args.length == 2 && args[0].equalsIgnoreCase("displayrange")) {
|
||||
return List.of("0", "48", "64", "96");
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private Component header() {
|
||||
return Component.text("---- Delta ----", NamedTextColor.DARK_PURPLE);
|
||||
}
|
||||
|
||||
private Component line(String key, String value) {
|
||||
return Component.text(key, NamedTextColor.GRAY).append(Component.text(value, NamedTextColor.WHITE));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package me.sashegdev.delta;
|
||||
|
||||
import io.papermc.paper.configuration.ConfigurationPart;
|
||||
|
||||
/**
|
||||
* Конфигурация Delta. Живёт в {@code paper-global.yml} в секции {@code delta}.
|
||||
* Все поля выключены по умолчанию, кроме Display-трекинга — он включается
|
||||
* только явно, чтобы стоковое поведение Paper осталось эталоном.
|
||||
*/
|
||||
public class Delta extends ConfigurationPart {
|
||||
|
||||
/** Резать дальность трекинга Display-сущностей (вместо стоковых 128). */
|
||||
public boolean displayTrackingRangeEnabled = false;
|
||||
public int displayTrackingRange = 64;
|
||||
|
||||
/** Потолок пакетов частиц на игрока за тик. 0 = выключено. */
|
||||
public int particleBudgetPerPlayerPerTick = 0;
|
||||
|
||||
/** Потолок пакетов звука на игрока за секунду. 0 = выключено. */
|
||||
public int soundBudgetPerPlayerPerSecond = 0;
|
||||
|
||||
/** Разрешить частицам/звукам уходить дальше стандартных 32/16 блоков. */
|
||||
public boolean extendedParticleDistanceEnabled = false;
|
||||
public double extendedParticleDistance = 128.0D;
|
||||
|
||||
/** Раздельные громкость и дальность звука (для DeltaSound). */
|
||||
public boolean decoupledSoundRangeEnabled = false;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package me.sashegdev.delta;
|
||||
|
||||
import io.papermc.paper.configuration.GlobalConfiguration;
|
||||
import net.minecraft.world.entity.Display;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
/**
|
||||
* Бюджет и дальность трекинга сущностей.
|
||||
*
|
||||
* <p>Вызывается из {@code ChunkMap.TrackedEntity#updatePlayer} — это единая
|
||||
* точка, где решается, полетит ли сущность клиенту. Display-сущности
|
||||
* (BlockDisplay/TextDisplay/ItemDisplay) не имеют коллизий и физики, поэтому
|
||||
* их можно безопасно резать по дальности: клиент их просто не увидит, но
|
||||
* серверное состояние останется корректным.
|
||||
*/
|
||||
public final class DeltaTracking {
|
||||
|
||||
private DeltaTracking() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return эффективную дальность трекинга с учётом Delta-конфига
|
||||
*/
|
||||
public static double adjustRange(final Entity entity, final double range) {
|
||||
if (!(entity instanceof Display)) {
|
||||
return range;
|
||||
}
|
||||
final DeltaConfig cfg = delta();
|
||||
if (cfg == null || !cfg.displayTrackingRangeEnabled) {
|
||||
return range;
|
||||
}
|
||||
final int configured = cfg.displayTrackingRange;
|
||||
return configured <= 0 ? range : Math.min(range, configured);
|
||||
}
|
||||
|
||||
private static DeltaConfig delta() {
|
||||
try {
|
||||
return GlobalConfiguration.get().delta;
|
||||
} catch (Throwable t) {
|
||||
// конфиг ещё не инициализирован (например, очень ранний вызов)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String describe() {
|
||||
final DeltaConfig cfg = delta();
|
||||
if (cfg == null) {
|
||||
return "config not loaded";
|
||||
}
|
||||
if (!cfg.displayTrackingRangeEnabled) {
|
||||
return "display tracking: stock (disabled)";
|
||||
}
|
||||
return "display tracking: " + cfg.displayTrackingRange + " blocks";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user