mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@742968e0 [ci/skip] Increase outdated build delay to two weeks (#12063) Gale Changes: Dreeam-qwq/Gale@57be1e6f Updated Upstream (Paper) Purpur Changes: PurpurMC/Purpur@36a18d54 fix(mobs/ravager): add missing blocks to griefable list PurpurMC/Purpur@fdc28eed Updated Upstream (Paper) PurpurMC/Purpur@d8aadde1 [ci/skip] Update README.md (#1642) PurpurMC/Purpur@9680ad8e [ci/skip] clean up unsafe enchants diff
2035 lines
93 KiB
Diff
2035 lines
93 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Github Actions <no-reply@github.com>
|
|
Date: Thu, 16 Jan 2025 11:21:12 +0000
|
|
Subject: [PATCH] Purpur Server Paper Changes
|
|
|
|
Original license: MIT
|
|
Original project: https://github.com/PurpurMC/Purpur
|
|
|
|
Commit: 9680ad8e578abc81fd92f1bb2b30357eab103057
|
|
|
|
Patches listed below are removed in this patch, They exists in Gale or Leaf:
|
|
* "Rebrand.patch"
|
|
* "com/destroystokyo/paper/Metrics.java.patch"
|
|
- Rebrand
|
|
* "com/destroystokyo/paper/PaperVersionFetcher.java.patch"
|
|
- Rebrand
|
|
* "com/destroystokyo/paper/console/PaperConsole.java.patch"
|
|
- Rebrand
|
|
* "com/destroystokyo/paper/gui/RAMDetails.java.patch"
|
|
- Add 5 second tps average in /tps
|
|
* "io/papermc/paper/ServerBuildInfoImpl.java.patch"
|
|
- Rebrand
|
|
* "org/bukkit/craftbukkit/CraftServer.java.patch"
|
|
- Add 5 second tps average in /tps
|
|
* "org/bukkit/craftbukkit/legacy/CraftLegacy.java.patch"
|
|
- Logger settings (suppressing pointless logs)
|
|
* "org/bukkit/craftbukkit/scheduler/CraftScheduler.java.patch"
|
|
- Rebrand
|
|
* "org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch"
|
|
- Rebrand
|
|
* "org/bukkit/craftbukkit/util/Versioning.java.patch"
|
|
- Rebrand
|
|
* "org/spigotmc/TicksPerSecondCommand.java.patch"
|
|
- Add 5 second tps average in /tps
|
|
* "org/spigotmc/WatchdogThread.java.patch"
|
|
- Rebrand
|
|
|
|
diff --git a/src/log4jPlugins/java/org/purpurmc/purpur/gui/util/HighlightErrorConverter.java b/src/log4jPlugins/java/org/purpurmc/purpur/gui/util/HighlightErrorConverter.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ede7cb766079031a2c75f3846aa654e28daa5b76
|
|
--- /dev/null
|
|
+++ b/src/log4jPlugins/java/org/purpurmc/purpur/gui/util/HighlightErrorConverter.java
|
|
@@ -0,0 +1,85 @@
|
|
+package org.purpurmc.purpur.gui.util;
|
|
+
|
|
+import org.apache.logging.log4j.Level;
|
|
+import org.apache.logging.log4j.core.LogEvent;
|
|
+import org.apache.logging.log4j.core.config.Configuration;
|
|
+import org.apache.logging.log4j.core.config.plugins.Plugin;
|
|
+import org.apache.logging.log4j.core.layout.PatternLayout;
|
|
+import org.apache.logging.log4j.core.pattern.ConverterKeys;
|
|
+import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
|
|
+import org.apache.logging.log4j.core.pattern.PatternConverter;
|
|
+import org.apache.logging.log4j.core.pattern.PatternFormatter;
|
|
+import org.apache.logging.log4j.core.pattern.PatternParser;
|
|
+import org.apache.logging.log4j.util.PerformanceSensitive;
|
|
+
|
|
+import java.util.List;
|
|
+
|
|
+@Plugin(name = "highlightGUIError", category = PatternConverter.CATEGORY)
|
|
+@ConverterKeys({"highlightGUIError"})
|
|
+@PerformanceSensitive("allocation")
|
|
+public final class HighlightErrorConverter extends LogEventPatternConverter {
|
|
+ private static final String ERROR = "\u00A74\u00A7l"; // Bold Red
|
|
+ private static final String WARN = "\u00A7e\u00A7l"; // Bold Yellow
|
|
+
|
|
+ private final List<PatternFormatter> formatters;
|
|
+
|
|
+ private HighlightErrorConverter(List<PatternFormatter> formatters) {
|
|
+ super("highlightGUIError", null);
|
|
+ this.formatters = formatters;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void format(LogEvent event, StringBuilder toAppendTo) {
|
|
+ Level level = event.getLevel();
|
|
+ if (level.isMoreSpecificThan(Level.ERROR)) {
|
|
+ format(ERROR, event, toAppendTo);
|
|
+ return;
|
|
+ } else if (level.isMoreSpecificThan(Level.WARN)) {
|
|
+ format(WARN, event, toAppendTo);
|
|
+ return;
|
|
+ }
|
|
+ for (PatternFormatter formatter : formatters) {
|
|
+ formatter.format(event, toAppendTo);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void format(String style, LogEvent event, StringBuilder toAppendTo) {
|
|
+ int start = toAppendTo.length();
|
|
+ toAppendTo.append(style);
|
|
+ int end = toAppendTo.length();
|
|
+
|
|
+ for (PatternFormatter formatter : formatters) {
|
|
+ formatter.format(event, toAppendTo);
|
|
+ }
|
|
+
|
|
+ if (toAppendTo.length() == end) {
|
|
+ toAppendTo.setLength(start);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean handlesThrowable() {
|
|
+ for (final PatternFormatter formatter : formatters) {
|
|
+ if (formatter.handlesThrowable()) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public static HighlightErrorConverter newInstance(Configuration config, String[] options) {
|
|
+ if (options.length != 1) {
|
|
+ LOGGER.error("Incorrect number of options on highlightGUIError. Expected 1 received " + options.length);
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ if (options[0] == null) {
|
|
+ LOGGER.error("No pattern supplied on highlightGUIError");
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ PatternParser parser = PatternLayout.createPatternParser(config);
|
|
+ List<PatternFormatter> formatters = parser.parse(options[0]);
|
|
+ return new HighlightErrorConverter(formatters);
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
|
|
index 6bdc683b5ade408ee27f1d6636b4d60c8c89cb7c..bc6d3898d8784e50a0e2264bbb5bde63add61f4e 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
|
|
@@ -136,6 +136,10 @@ public class MobGoalHelper {
|
|
static {
|
|
// TODO these kinda should be checked on each release, in case obfuscation changes
|
|
deobfuscationMap.put("abstract_skeleton_1", "abstract_skeleton_melee");
|
|
+ // Purpur start - Add option to disable zombie aggressiveness towards villagers
|
|
+ deobfuscationMap.put("zombie_1", "zombie_attack_villager");
|
|
+ deobfuscationMap.put("drowned_1", "drowned_attack_villager");
|
|
+ // Purpur end - Add option to disable zombie aggressiveness towards villagers
|
|
|
|
ignored.add("goal_selector_1");
|
|
ignored.add("goal_selector_2");
|
|
diff --git a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java
|
|
index f0fce4113fb07c64adbec029d177c236cbdcbae8..94dc9f97de086e3ab51d1b000eb116cf868a75db 100644
|
|
--- a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java
|
|
+++ b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java
|
|
@@ -78,10 +78,10 @@ public class PaperPluginsCommand extends BukkitCommand {
|
|
this.setAliases(Arrays.asList("pl"));
|
|
}
|
|
|
|
- private static <T> List<Component> formatProviders(TreeMap<String, PluginProvider<T>> plugins) {
|
|
+ private static <T> List<Component> formatProviders(TreeMap<String, PluginProvider<T>> plugins, @NotNull CommandSender sender) { // Purpur - Improve output of plugins command
|
|
List<Component> components = new ArrayList<>(plugins.size());
|
|
for (PluginProvider<T> entry : plugins.values()) {
|
|
- components.add(formatProvider(entry));
|
|
+ components.add(formatProvider(entry, sender)); // Purpur - Improve output of plugins command
|
|
}
|
|
|
|
boolean isFirst = true;
|
|
@@ -109,7 +109,7 @@ public class PaperPluginsCommand extends BukkitCommand {
|
|
return formattedSublists;
|
|
}
|
|
|
|
- private static Component formatProvider(PluginProvider<?> provider) {
|
|
+ private static Component formatProvider(PluginProvider<?> provider, @NotNull CommandSender sender) { // Purpur - Improve output of plugins command
|
|
TextComponent.Builder builder = Component.text();
|
|
if (provider instanceof SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) {
|
|
builder.append(LEGACY_PLUGIN_STAR);
|
|
@@ -117,13 +117,65 @@ public class PaperPluginsCommand extends BukkitCommand {
|
|
|
|
String name = provider.getMeta().getName();
|
|
Component pluginName = Component.text(name, fromStatus(provider))
|
|
- .clickEvent(ClickEvent.runCommand("/version " + name));
|
|
+ // Purpur start - Improve output of plugins command
|
|
+ .clickEvent(ClickEvent.suggestCommand("/version " + name));
|
|
+
|
|
+ if (sender instanceof org.bukkit.entity.Player && sender.hasPermission("bukkit.command.version")) {
|
|
+ // Event components
|
|
+ String description = provider.getMeta().getDescription();
|
|
+ TextComponent.Builder hover = Component.text();
|
|
+ hover.append(Component.text("Version: ", NamedTextColor.WHITE)).append(Component.text(provider.getMeta().getVersion(), NamedTextColor.GREEN));
|
|
+
|
|
+ if (description != null) {
|
|
+ hover.append(Component.newline())
|
|
+ .append(Component.text("Description: ", NamedTextColor.WHITE))
|
|
+ .append(Component.text(description, NamedTextColor.GREEN));
|
|
+ }
|
|
+
|
|
+ if (provider.getMeta().getWebsite() != null) {
|
|
+ hover.append(Component.newline())
|
|
+ .append(Component.text("Website: ", NamedTextColor.WHITE))
|
|
+ .append(Component.text(provider.getMeta().getWebsite(), NamedTextColor.GREEN));
|
|
+ }
|
|
+
|
|
+ if (!provider.getMeta().getAuthors().isEmpty()) {
|
|
+ hover.append(Component.newline());
|
|
+ if (provider.getMeta().getAuthors().size() == 1) {
|
|
+ hover.append(Component.text("Author: "));
|
|
+ } else {
|
|
+ hover.append(Component.text("Authors: "));
|
|
+ }
|
|
+
|
|
+ hover.append(getAuthors(provider.getMeta()));
|
|
+ }
|
|
+
|
|
+ pluginName = pluginName.hoverEvent(hover.build());
|
|
+ }
|
|
+ // Purpur end - Improve output of plugins command
|
|
|
|
builder.append(pluginName);
|
|
|
|
return builder.build();
|
|
}
|
|
|
|
+ // Purpur start - Improve output of plugins command
|
|
+ @NotNull
|
|
+ private static TextComponent getAuthors(@NotNull final PluginMeta pluginMeta) {
|
|
+ TextComponent.Builder builder = Component.text();
|
|
+ List<String> authors = pluginMeta.getAuthors();
|
|
+
|
|
+ for (int i = 0; i < authors.size(); i++) {
|
|
+ if (i > 0) {
|
|
+ builder.append(Component.text(i < authors.size() - 1 ? ", " : " and ", NamedTextColor.WHITE));
|
|
+ }
|
|
+
|
|
+ builder.append(Component.text(authors.get(i), NamedTextColor.GREEN));
|
|
+ }
|
|
+
|
|
+ return builder.build();
|
|
+ }
|
|
+ // Purpur end - Improve output of plugins command
|
|
+
|
|
private static Component asPlainComponents(String strings) {
|
|
net.kyori.adventure.text.TextComponent.Builder builder = Component.text();
|
|
for (String string : strings.split("\n")) {
|
|
@@ -182,24 +234,24 @@ public class PaperPluginsCommand extends BukkitCommand {
|
|
}
|
|
}
|
|
|
|
- Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE);
|
|
+ //Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE); // Purpur - Improve output of plugins command
|
|
//.append(INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO)); TODO: Add docs
|
|
|
|
- sender.sendMessage(infoMessage);
|
|
+ //sender.sendMessage(infoMessage); // Purpur - Improve output of plugins command
|
|
|
|
- if (!paperPlugins.isEmpty()) {
|
|
- sender.sendMessage(PAPER_HEADER);
|
|
- }
|
|
+ //if (!paperPlugins.isEmpty()) { // Purpur - Improve output of plugins command
|
|
+ sender.sendMessage(PAPER_HEADER.append(Component.text(" (%s):".formatted(paperPlugins.size())))); // Purpur - Improve output of plugins command
|
|
+ //} // Purpur - Improve output of plugins command
|
|
|
|
- for (Component component : formatProviders(paperPlugins)) {
|
|
+ for (Component component : formatProviders(paperPlugins, sender)) { // Purpur - Improve output of plugins command
|
|
sender.sendMessage(component);
|
|
}
|
|
|
|
- if (!spigotPlugins.isEmpty()) {
|
|
- sender.sendMessage(BUKKIT_HEADER);
|
|
- }
|
|
+ //if (!spigotPlugins.isEmpty()) { // Purpur - Improve output of plugins command
|
|
+ sender.sendMessage(BUKKIT_HEADER.append(Component.text(" (%s):".formatted(spigotPlugins.size())))); // Purpur - Improve output of plugins command
|
|
+ //} // Purpur - Improve output of plugins command
|
|
|
|
- for (Component component : formatProviders(spigotPlugins)) {
|
|
+ for (Component component : formatProviders(spigotPlugins, sender)) { // Purpur - Improve output of plugins command
|
|
sender.sendMessage(component);
|
|
}
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
|
|
index 352d62385e56d5805510596ec9424e5d14336861..b4d4ad2dc7d719d72c0786791f803fbcf0982d1f 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
|
|
@@ -267,6 +267,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
|
|
for (final NodePath path : RemovedConfigurations.REMOVED_WORLD_PATHS) {
|
|
builder.addAction(path, TransformAction.remove());
|
|
}
|
|
+ org.purpurmc.purpur.configuration.transformation.VoidDamageHeightMigration.apply(builder, contextMap); // Purpur - Configurable void damage height and damage
|
|
builder.build().apply(node);
|
|
|
|
final ConfigurationTransformation.VersionedBuilder versionedBuilder = Transformations.versionedBuilder();
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
|
|
index d7c9acaffdcff5e35e026ae90a3e521bab13b074..a426ba82af695426952bb5e04fa721e6ccff2f89 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
|
|
@@ -398,6 +398,7 @@ public class WorldConfiguration extends ConfigurationPart {
|
|
public boolean useVanillaWorldScoreboardNameColoring = false;
|
|
}
|
|
|
|
+ @Setting(org.purpurmc.purpur.configuration.transformation.VoidDamageHeightMigration.ENVIRONMENT_KEY) // Purpur - Configurable void damage height and damage
|
|
public Environment environment;
|
|
|
|
public class Environment extends ConfigurationPart {
|
|
@@ -407,7 +408,9 @@ public class WorldConfiguration extends ConfigurationPart {
|
|
public boolean disableExplosionKnockback = false;
|
|
public boolean generateFlatBedrock = false;
|
|
public FrostedIce frostedIce;
|
|
+ @Setting(org.purpurmc.purpur.configuration.transformation.VoidDamageHeightMigration.VOID_DAMAGE_KEY) // Purpur - Configurable void damage height and damage
|
|
public DoubleOr.Disabled voidDamageAmount = new DoubleOr.Disabled(OptionalDouble.of(4));
|
|
+ @Setting(org.purpurmc.purpur.configuration.transformation.VoidDamageHeightMigration.VOID_DAMAGE_MIN_HEIGHT_OFFSET_KEY) // Purpur - Configurable void damage height and damage
|
|
public double voidDamageMinBuildHeightOffset = -64.0;
|
|
|
|
public class FrostedIce extends ConfigurationPart {
|
|
diff --git a/src/main/java/io/papermc/paper/logging/SysoutCatcher.java b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
|
index a8e813ca89b033f061e695288b3383bdcf128531..96a377a07d8396f893954a3ba97fbf88d73faf6d 100644
|
|
--- a/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
|
+++ b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
|
|
@@ -54,9 +54,9 @@ public final class SysoutCatcher {
|
|
final JavaPlugin plugin = JavaPlugin.getProvidingPlugin(clazz);
|
|
|
|
// Instead of just printing the message, send it to the plugin's logger
|
|
- plugin.getLogger().log(this.level, this.prefix + line);
|
|
+ plugin.getLogger().log(this.level, /*this.prefix +*/ line); // Purpur - Enhance SysoutCatcher - prefix not needed
|
|
|
|
- if (SysoutCatcher.SUPPRESS_NAGS) {
|
|
+ if (true || SysoutCatcher.SUPPRESS_NAGS) { // Purpur - Enhance SysoutCatcher - nagging is annoying
|
|
return;
|
|
}
|
|
if (SysoutCatcher.NAG_INTERVAL > 0 || SysoutCatcher.NAG_TIMEOUT > 0) {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
|
index 94ca0407303c4493ab4928b12ec6ecc75aaca549..f2d87c12dd19210ce7e2147fada5c10191008632 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
|
@@ -363,14 +363,26 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
|
|
|
@Override
|
|
public Location getLocation() {
|
|
+ // Purpur start - OfflinePlayer API
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().getLocation();
|
|
+ }
|
|
+ // Purpur end - OfflinePlayer API
|
|
+
|
|
CompoundTag data = this.getData();
|
|
if (data == null) {
|
|
return null;
|
|
}
|
|
|
|
- if (data.contains("Pos") && data.contains("Rotation")) {
|
|
- ListTag position = (ListTag) data.get("Pos");
|
|
- ListTag rotation = (ListTag) data.get("Rotation");
|
|
+ // Purpur start - OfflinePlayer API
|
|
+ //if (data.contains("Pos") && data.contains("Rotation")) {
|
|
+ ListTag position = data.getList("Pos", net.minecraft.nbt.Tag.TAG_DOUBLE);
|
|
+ ListTag rotation = data.getList("Rotation", net.minecraft.nbt.Tag.TAG_FLOAT);
|
|
+
|
|
+ if (position.isEmpty() && rotation.isEmpty()) {
|
|
+ return null;
|
|
+ }
|
|
+ // Purpur end - OfflinePlayer API
|
|
|
|
UUID uuid = new UUID(data.getLong("WorldUUIDMost"), data.getLong("WorldUUIDLeast"));
|
|
|
|
@@ -381,9 +393,9 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
|
rotation.getFloat(0),
|
|
rotation.getFloat(1)
|
|
);
|
|
- }
|
|
+ //} // Purpur - OfflinePlayer API
|
|
|
|
- return null;
|
|
+ //return null; // Purpur - OfflinePlayer API
|
|
}
|
|
|
|
@Override
|
|
@@ -626,4 +638,191 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
|
manager.save();
|
|
}
|
|
}
|
|
+
|
|
+ // Purpur start - OfflinePlayer API
|
|
+ @Override
|
|
+ public boolean getAllowFlight() {
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().getAllowFlight();
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return false;
|
|
+ if (!data.contains("abilities")) return false;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ return abilities.getByte("mayfly") == (byte) 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setAllowFlight(boolean flight) {
|
|
+ if (this.isOnline()) {
|
|
+ this.getPlayer().setAllowFlight(flight);
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return;
|
|
+ if (!data.contains("abilities")) return;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ abilities.putByte("mayfly", (byte) (flight ? 1 : 0));
|
|
+ data.put("abilities", abilities);
|
|
+ save(data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isFlying() {
|
|
+ if (this.isOnline()) {
|
|
+ return this.isFlying();
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return false;
|
|
+ if (!data.contains("abilities")) return false;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ return abilities.getByte("flying") == (byte) 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setFlying(boolean value) {
|
|
+ if (this.isOnline()) {
|
|
+ this.getPlayer().setFlying(value);
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return;
|
|
+ if (!data.contains("abilities")) return;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ abilities.putByte("mayfly", (byte) (value ? 1 : 0));
|
|
+ data.put("abilities", abilities);
|
|
+ save(data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setFlySpeed(float value) throws IllegalArgumentException {
|
|
+ if (value < -1f || value > 1f) throw new IllegalArgumentException("FlySpeed needs to be between -1 and 1");
|
|
+ if (this.isOnline()) {
|
|
+ this.getPlayer().setFlySpeed(value);
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return;
|
|
+ if (!data.contains("abilities")) return;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ abilities.putFloat("flySpeed", value);
|
|
+ data.put("abilities", abilities);
|
|
+ save(data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getFlySpeed() {
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().getFlySpeed();
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return 0;
|
|
+ if (!data.contains("abilities")) return 0;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ return abilities.getFloat("flySpeed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setWalkSpeed(float value) throws IllegalArgumentException {
|
|
+ if (value < -1f || value > 1f) throw new IllegalArgumentException("WalkSpeed needs to be between -1 and 1");
|
|
+ if (this.isOnline()) {
|
|
+ this.getPlayer().setWalkSpeed(value);
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return;
|
|
+ if (!data.contains("abilities")) return;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ abilities.putFloat("walkSpeed", value);
|
|
+ data.put("abilities", abilities);
|
|
+ save(data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getWalkSpeed() {
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().getWalkSpeed();
|
|
+ } else {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return 0;
|
|
+ if (!data.contains("abilities")) return 0;
|
|
+ CompoundTag abilities = data.getCompound("abilities");
|
|
+ return abilities.getFloat("walkSpeed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean teleportOffline(Location destination) {
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().teleport(destination);
|
|
+ } else {
|
|
+ return setLocation(destination);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean teleportOffline(Location destination, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause){
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().teleport(destination, cause);
|
|
+ } else {
|
|
+ return setLocation(destination);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(Location destination) {
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().teleportAsync(destination);
|
|
+ } else {
|
|
+ return java.util.concurrent.CompletableFuture.completedFuture(setLocation(destination));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(Location destination, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) {
|
|
+ if (this.isOnline()) {
|
|
+ return this.getPlayer().teleportAsync(destination, cause);
|
|
+ } else {
|
|
+ return java.util.concurrent.CompletableFuture.completedFuture(setLocation(destination));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private boolean setLocation(Location location) {
|
|
+ CompoundTag data = this.getData();
|
|
+ if (data == null) return false;
|
|
+ data.putLong("WorldUUIDMost", location.getWorld().getUID().getMostSignificantBits());
|
|
+ data.putLong("WorldUUIDLeast", location.getWorld().getUID().getLeastSignificantBits());
|
|
+ net.minecraft.nbt.ListTag position = new net.minecraft.nbt.ListTag();
|
|
+ position.add(net.minecraft.nbt.DoubleTag.valueOf(location.getX()));
|
|
+ position.add(net.minecraft.nbt.DoubleTag.valueOf(location.getY()));
|
|
+ position.add(net.minecraft.nbt.DoubleTag.valueOf(location.getZ()));
|
|
+ data.put("Pos", position);
|
|
+ net.minecraft.nbt.ListTag rotation = new net.minecraft.nbt.ListTag();
|
|
+ rotation.add(net.minecraft.nbt.FloatTag.valueOf(location.getYaw()));
|
|
+ rotation.add(net.minecraft.nbt.FloatTag.valueOf(location.getPitch()));
|
|
+ data.put("Rotation", rotation);
|
|
+ save(data);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Safely replaces player's .dat file with provided CompoundTag
|
|
+ * @param compoundTag
|
|
+ */
|
|
+ private void save(CompoundTag compoundTag) {
|
|
+ File playerDir = server.console.playerDataStorage.getPlayerDir();
|
|
+ try {
|
|
+ File tempFile = File.createTempFile(this.getUniqueId()+"-", ".dat", playerDir);
|
|
+ net.minecraft.nbt.NbtIo.writeCompressed(compoundTag, tempFile.toPath());
|
|
+ File playerDataFile = new File(playerDir, this.getUniqueId()+".dat");
|
|
+ File playerDataFileOld = new File(playerDir, this.getUniqueId()+".dat_old");
|
|
+ net.minecraft.Util.safeReplaceFile(playerDataFile.toPath(), tempFile.toPath(), playerDataFileOld.toPath());
|
|
+ } catch (java.io.IOException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ // Purpur end - OfflinePlayer API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index 5ad91693178b5645c98804ab04a56e85a28eb426..60389075b86a7c030e59fbc4c493a4f31012a66e 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -428,6 +428,20 @@ public final class CraftServer implements Server {
|
|
this.paperPluginManager = new io.papermc.paper.plugin.manager.PaperPluginManagerImpl(this, this.commandMap, pluginManager);
|
|
this.pluginManager.paperPluginManager = this.paperPluginManager;
|
|
// Paper end
|
|
+ // Purpur start - Language API
|
|
+ org.purpurmc.purpur.language.Language.setLanguage(new org.purpurmc.purpur.language.Language() {
|
|
+ private net.minecraft.locale.Language language = net.minecraft.locale.Language.getInstance();
|
|
+ @Override
|
|
+ public boolean has(@org.jetbrains.annotations.NotNull String key) {
|
|
+ return language.has(key);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public @org.jetbrains.annotations.NotNull String getOrDefault(@org.jetbrains.annotations.NotNull String key) {
|
|
+ return language.getOrDefault(key);
|
|
+ }
|
|
+ });
|
|
+ // Purpur end - Language API
|
|
|
|
CraftRegistry.setMinecraftRegistry(console.registryAccess());
|
|
|
|
@@ -1089,6 +1103,7 @@ public final class CraftServer implements Server {
|
|
org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot
|
|
this.console.paperConfigurations.reloadConfigs(this.console);
|
|
this.console.galeConfigurations.reloadConfigs(this.console); // Gale - Gale configuration
|
|
+ org.purpurmc.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur - Purpur config files
|
|
for (ServerLevel world : this.console.getAllLevels()) {
|
|
// world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty
|
|
world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean))
|
|
@@ -1104,6 +1119,7 @@ public final class CraftServer implements Server {
|
|
}
|
|
}
|
|
world.spigotConfig.init(); // Spigot
|
|
+ world.purpurConfig.init(); // Purpur - Purpur config files
|
|
}
|
|
|
|
Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper
|
|
@@ -1121,6 +1137,7 @@ public final class CraftServer implements Server {
|
|
org.spigotmc.SpigotConfig.registerCommands(); // Spigot
|
|
io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
|
|
this.spark.registerCommandBeforePlugins(this); // Paper - spark
|
|
+ org.purpurmc.purpur.PurpurConfig.registerCommands(); // Purpur - Purpur config files
|
|
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
|
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
|
|
|
@@ -1652,6 +1669,60 @@ public final class CraftServer implements Server {
|
|
return true;
|
|
}
|
|
|
|
+ // Purpur start - Added the ability to add combustible items
|
|
+ @Override
|
|
+ public void addFuel(org.bukkit.Material material, int burnTime) {
|
|
+ Preconditions.checkArgument(burnTime > 0, "BurnTime must be greater than 0");
|
|
+
|
|
+ net.minecraft.world.item.ItemStack itemStack = net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material));
|
|
+ MinecraftServer.getServer().fuelValues().values.put(itemStack.getItem(), burnTime);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void removeFuel(org.bukkit.Material material) {
|
|
+ net.minecraft.world.item.ItemStack itemStack = net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material));
|
|
+ MinecraftServer.getServer().fuelValues().values.keySet().removeIf(itemStack::is);
|
|
+ }
|
|
+ // Purpur end - Added the ability to add combustible items
|
|
+
|
|
+ // Purpur start - Debug Marker API
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration) {
|
|
+ sendBlockHighlight(location, duration, "", 0x6400FF00);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, int argb) {
|
|
+ sendBlockHighlight(location, duration, "", argb);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text) {
|
|
+ sendBlockHighlight(location, duration, text, 0x6400FF00);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text, int argb) {
|
|
+ this.worlds.forEach((name, world) -> world.sendBlockHighlight(location, duration, text, argb));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, org.bukkit.Color color, int transparency) {
|
|
+ sendBlockHighlight(location, duration, "", color, transparency);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text, org.bukkit.Color color, int transparency) {
|
|
+ if (transparency < 0 || transparency > 255) throw new IllegalArgumentException("transparency is outside of 0-255 range");
|
|
+ sendBlockHighlight(location, duration, text, transparency << 24 | color.asRGB());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void clearBlockHighlights() {
|
|
+ this.worlds.forEach((name, world) -> clearBlockHighlights());
|
|
+ }
|
|
+ // Purpur end - Debug Marker API
|
|
+
|
|
@Override
|
|
public List<Recipe> getRecipesFor(ItemStack result) {
|
|
Preconditions.checkArgument(result != null, "ItemStack cannot be null");
|
|
@@ -3069,6 +3140,18 @@ public final class CraftServer implements Server {
|
|
}
|
|
// Gale end - Gale configuration - API
|
|
|
|
+ // Purpur start - Purpur config files
|
|
+ @Override
|
|
+ public YamlConfiguration getPurpurConfig() {
|
|
+ return org.purpurmc.purpur.PurpurConfig.config;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public java.util.Properties getServerProperties() {
|
|
+ return getProperties().properties;
|
|
+ }
|
|
+ // Purpur end - Purpur config files
|
|
+
|
|
@Override
|
|
public void restart() {
|
|
org.spigotmc.RestartCommand.restart();
|
|
@@ -3361,4 +3444,18 @@ public final class CraftServer implements Server {
|
|
return MinecraftServer.lastTickOversleepTime;
|
|
}
|
|
// Gale end - YAPFA - last tick time - API
|
|
+
|
|
+ // Purpur start - Bring back server name
|
|
+ @Override
|
|
+ public String getServerName() {
|
|
+ return this.getProperties().serverName;
|
|
+ }
|
|
+ // Purpur end - Bring back server name
|
|
+
|
|
+ // Purpur start - Lagging threshold
|
|
+ @Override
|
|
+ public boolean isLagging() {
|
|
+ return getServer().lagging;
|
|
+ }
|
|
+ // Purpur end - Lagging threshold
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
index 284b58ece65d9cf6411a79abb748f1dfa52edc92..ba5797e9e518d7a1054bad0c7a1fb10b9eaf32bd 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
@@ -2373,6 +2373,50 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
return (this.getHandle().getDragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().getDragonFight());
|
|
}
|
|
|
|
+ // Purpur start - Add local difficulty api
|
|
+ public float getLocalDifficultyAt(Location location) {
|
|
+ return getHandle().getCurrentDifficultyAt(io.papermc.paper.util.MCUtil.toBlockPosition(location)).getEffectiveDifficulty();
|
|
+ }
|
|
+ // Purpur end - Add local difficulty api
|
|
+
|
|
+ // Purpur start - Debug Marker API
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration) {
|
|
+ sendBlockHighlight(location, duration, "", 0x6400FF00);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, int argb) {
|
|
+ sendBlockHighlight(location, duration, "", argb);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text) {
|
|
+ sendBlockHighlight(location, duration, text, 0x6400FF00);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text, int argb) {
|
|
+ net.minecraft.network.protocol.game.DebugPackets.sendGameTestAddMarker(getHandle(), io.papermc.paper.util.MCUtil.toBlockPosition(location), text, argb, duration);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, org.bukkit.Color color, int transparency) {
|
|
+ sendBlockHighlight(location, duration, "", color, transparency);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text, org.bukkit.Color color, int transparency) {
|
|
+ if (transparency < 0 || transparency > 255) throw new IllegalArgumentException("transparency is outside of 0-255 range");
|
|
+ sendBlockHighlight(location, duration, text, transparency << 24 | color.asRGB());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void clearBlockHighlights() {
|
|
+ net.minecraft.network.protocol.game.DebugPackets.sendGameTestClearPacket(getHandle());
|
|
+ }
|
|
+ // Purpur end - Debug Marker API
|
|
+
|
|
@Override
|
|
public Collection<GeneratedStructure> getStructures(int x, int z) {
|
|
return this.getStructures(x, z, struct -> true);
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
index d0becb56a9911ef4cc55ae8d7c47832f442ad52f..bdce5f9a589fedf8c7a59da9cde56056413dd723 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
@@ -176,6 +176,13 @@ public class Main {
|
|
.describedAs("Jar file");
|
|
// Paper end
|
|
|
|
+ // Purpur start - Purpur config files
|
|
+ acceptsAll(asList("purpur", "purpur-settings"), "File for purpur settings")
|
|
+ .withRequiredArg()
|
|
+ .ofType(File.class)
|
|
+ .defaultsTo(new File("purpur.yml"))
|
|
+ .describedAs("Yml file");
|
|
+ // Purpur end - Purpur config files
|
|
// Paper start
|
|
acceptsAll(asList("server-name"), "Name of the server")
|
|
.withRequiredArg()
|
|
@@ -259,7 +266,7 @@ public class Main {
|
|
System.setProperty(net.minecrell.terminalconsole.TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper
|
|
}
|
|
|
|
- if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) {
|
|
+ if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { // Purpur - Disable outdated build check
|
|
Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(Main.class.getPackage().getImplementationVendor()); // Paper
|
|
|
|
Calendar deadline = Calendar.getInstance();
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
|
|
index 1a2a05160ba51d9c75f1ae6ae61d944d81428722..a86b026f2f420637d125cf697bcd07bf314c98aa 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
|
|
@@ -16,8 +16,15 @@ import org.bukkit.entity.Bee;
|
|
|
|
public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> implements Beehive {
|
|
|
|
+ private final List<org.purpurmc.purpur.entity.StoredEntity<Bee>> storage = new ArrayList<>(); // Purpur - Stored Bee API
|
|
+
|
|
public CraftBeehive(World world, BeehiveBlockEntity tileEntity) {
|
|
super(world, tileEntity);
|
|
+ // Purpur start - load bees to be able to modify them individually - Stored Bee API
|
|
+ for(BeehiveBlockEntity.BeeData data : tileEntity.getStored()) {
|
|
+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(data, this));
|
|
+ }
|
|
+ // Purpur end - Stored Bee API
|
|
}
|
|
|
|
protected CraftBeehive(CraftBeehive state, Location location) {
|
|
@@ -76,14 +83,54 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
|
|
}
|
|
}
|
|
|
|
+ storage.clear(); // Purpur - Stored Bee API
|
|
return bees;
|
|
}
|
|
|
|
+ // Purpur start - Stored Bee API
|
|
+ @Override
|
|
+ public Bee releaseEntity(org.purpurmc.purpur.entity.StoredEntity<Bee> entity) {
|
|
+ ensureNoWorldGeneration();
|
|
+
|
|
+ if(!getEntities().contains(entity)) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ if(isPlaced()) {
|
|
+ BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getTileEntityFromWorld());
|
|
+ BeehiveBlockEntity.BeeData data = ((org.purpurmc.purpur.entity.PurpurStoredBee) entity).getHandle();
|
|
+
|
|
+ List<Entity> list = beehive.releaseBee(getHandle(), data, BeeReleaseStatus.BEE_RELEASED, true);
|
|
+
|
|
+ if (list.size() == 1) {
|
|
+ storage.remove(entity);
|
|
+
|
|
+ return (Bee) list.get(0).getBukkitEntity();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<org.purpurmc.purpur.entity.StoredEntity<Bee>> getEntities() {
|
|
+ return new ArrayList<>(storage);
|
|
+ }
|
|
+ // Purpur end - Stored Bee API
|
|
+
|
|
@Override
|
|
public void addEntity(Bee entity) {
|
|
Preconditions.checkArgument(entity != null, "Entity must not be null");
|
|
|
|
+ int length = this.getSnapshot().getStored().size(); // Purpur - Stored Bee API
|
|
this.getSnapshot().addOccupant(((CraftBee) entity).getHandle());
|
|
+
|
|
+ // Purpur start - check if new bee was added, and if yes, add to stored bees - Stored Bee API
|
|
+ List<BeehiveBlockEntity.BeeData> storedBeeData = this.getSnapshot().getStored();
|
|
+ if(length < storedBeeData.size()) {
|
|
+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(storedBeeData.getLast(), this));
|
|
+ }
|
|
+ // Purpur end - Stored Bee API
|
|
}
|
|
|
|
@Override
|
|
@@ -100,6 +147,7 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
|
|
@Override
|
|
public void clearEntities() {
|
|
getSnapshot().clearBees();
|
|
+ storage.clear(); // Purpur - Stored Bee API
|
|
}
|
|
// Paper end
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java b/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java
|
|
index c1759aeb3e6ad0e4eb66cba3da1b120dd1dce812..a663962e5181e89286caa18f537c1f5758b41623 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java
|
|
@@ -73,7 +73,7 @@ public class CraftConduit extends CraftBlockEntityState<ConduitBlockEntity> impl
|
|
public int getRange() {
|
|
this.ensureNoWorldGeneration();
|
|
ConduitBlockEntity conduit = (ConduitBlockEntity) this.getTileEntityFromWorld();
|
|
- return (conduit != null) ? ConduitBlockEntity.getRange(conduit.effectBlocks) : 0;
|
|
+ return (conduit != null) ? ConduitBlockEntity.getRange(conduit.effectBlocks, this.world.getHandle()) : 0; // Purpur - Conduit behavior configuration
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
|
|
index 4e56018b64d11f76c8da43fd8f85c6de72204e36..36cec3ed39807e85013e4e3b98c979d7af37ce58 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
|
|
@@ -21,7 +21,12 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co
|
|
|
|
@Override
|
|
public void sendMessage(String message) {
|
|
- this.sendRawMessage(message);
|
|
+ // Purpur start - Rebrand
|
|
+ String[] parts = message.split("\n");
|
|
+ for (String part : parts) {
|
|
+ this.sendRawMessage(part);
|
|
+ }
|
|
+ // Purpur end - Rebrand
|
|
}
|
|
|
|
@Override
|
|
@@ -91,7 +96,7 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co
|
|
// Paper start
|
|
@Override
|
|
public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) {
|
|
- this.sendRawMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(message));
|
|
+ this.sendMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(message)); // Purpur - Rebrand
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java
|
|
index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..3604d92c122b5c8be823098ce7b91e57e976589c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java
|
|
@@ -21,12 +21,12 @@ public class CraftEndermite extends CraftMonster implements Endermite {
|
|
|
|
@Override
|
|
public boolean isPlayerSpawned() {
|
|
- return false;
|
|
+ return getHandle().isPlayerSpawned(); // Purpur - Add back player spawned endermite API
|
|
}
|
|
|
|
@Override
|
|
public void setPlayerSpawned(boolean playerSpawned) {
|
|
- // Nop
|
|
+ getHandle().setPlayerSpawned(playerSpawned); // Purpur - Add back player spawned endermite API
|
|
}
|
|
// Paper start
|
|
@Override
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
index 659f0f9c7e45e5174f4736c4878a78d330b1d4ee..0d46585c0128cea7265870de5fe260681c65d7c3 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
@@ -90,6 +90,25 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
this.entityType = CraftEntityType.minecraftToBukkit(entity.getType());
|
|
}
|
|
|
|
+ // Purpur start - Fire Immunity API
|
|
+ @Override
|
|
+ public boolean isImmuneToFire() {
|
|
+ return getHandle().fireImmune();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setImmuneToFire(Boolean fireImmune) {
|
|
+ getHandle().immuneToFire = fireImmune;
|
|
+ }
|
|
+ // Purpur end - Fire Immunity API
|
|
+
|
|
+ // Purpur start - API for any mob to burn daylight
|
|
+ @Override
|
|
+ public boolean isInDaylight() {
|
|
+ return getHandle().isSunBurnTick();
|
|
+ }
|
|
+ // Purpur end - API for any mob to burn daylight
|
|
+
|
|
public static <T extends Entity> CraftEntity getEntity(CraftServer server, T entity) {
|
|
Preconditions.checkArgument(entity != null, "Unknown entity");
|
|
|
|
@@ -249,6 +268,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
boolean retainPassengers = flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS);
|
|
// Don't allow teleporting between worlds while keeping passengers
|
|
if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) {
|
|
+ if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, cause).callEvent()) // Purpur - Add EntityTeleportHinderedEvent
|
|
return false;
|
|
}
|
|
|
|
@@ -1333,4 +1353,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
}
|
|
}
|
|
// Paper end - broadcast hurt animation
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public org.bukkit.entity.Player getRider() {
|
|
+ net.minecraft.world.entity.player.Player rider = getHandle().getRider();
|
|
+ return rider != null ? (org.bukkit.entity.Player) rider.getBukkitEntity() : null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasRider() {
|
|
+ return getHandle().getRider() != null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return getHandle().isRidable();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isRidableInWater() {
|
|
+ return !getHandle().dismountsUnderwater();
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
|
index a396157548a5b3c3e86206c35789bb40346c701c..469b99bede578b03a1b711b4404a88bf85d7e7ca 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
|
|
@@ -281,6 +281,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
|
@Override
|
|
public void recalculatePermissions() {
|
|
this.perm.recalculatePermissions();
|
|
+ getHandle().canPortalInstant = hasPermission("purpur.portal.instant"); // Purpur - Add portal permission bypass
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java
|
|
index 63cae1a2e95d8da17c45c4404a8dd0ca6a413c39..464a3713845548473a357ea66c6147b10ff2cb16 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java
|
|
@@ -27,4 +27,17 @@ public class CraftIronGolem extends CraftGolem implements IronGolem {
|
|
public void setPlayerCreated(boolean playerCreated) {
|
|
this.getHandle().setPlayerCreated(playerCreated);
|
|
}
|
|
+
|
|
+ // Purpur start - Summoner API
|
|
+ @Override
|
|
+ @org.jetbrains.annotations.Nullable
|
|
+ public java.util.UUID getSummoner() {
|
|
+ return getHandle().getSummoner();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setSummoner(@org.jetbrains.annotations.Nullable java.util.UUID summoner) {
|
|
+ getHandle().setSummoner(summoner);
|
|
+ }
|
|
+ // Purpur end - Summoner API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
|
index 7a3d982b133f8cdaeb936cf40f92565f0f7f6dd0..8b0faa08411ee1f336641b161acd3412c886dc2b 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
|
|
@@ -151,4 +151,53 @@ public class CraftItem extends CraftEntity implements Item {
|
|
public String toString() {
|
|
return "CraftItem";
|
|
}
|
|
+
|
|
+ // Purpur start - Item entity immunities
|
|
+ @Override
|
|
+ public void setImmuneToCactus(boolean immuneToCactus) {
|
|
+ this.getHandle().immuneToCactus = immuneToCactus;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isImmuneToCactus() {
|
|
+ return this.getHandle().immuneToCactus;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setImmuneToExplosion(boolean immuneToExplosion) {
|
|
+ this.getHandle().immuneToExplosion = immuneToExplosion;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isImmuneToExplosion() {
|
|
+ return this.getHandle().immuneToExplosion;
|
|
+ }
|
|
+
|
|
+ // Purpur start - Fire Immunity API
|
|
+ @Override
|
|
+ public void setImmuneToFire(@org.jetbrains.annotations.Nullable Boolean immuneToFire) {
|
|
+ this.getHandle().immuneToFire = (immuneToFire != null && immuneToFire);
|
|
+ }
|
|
+ // Purpur end - Fire Immunity API
|
|
+
|
|
+ @Override
|
|
+ public void setImmuneToFire(boolean immuneToFire) {
|
|
+ this.setImmuneToFire((Boolean) immuneToFire); // Purpur - Fire Immunity API
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isImmuneToFire() {
|
|
+ return this.getHandle().immuneToFire;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setImmuneToLightning(boolean immuneToLightning) {
|
|
+ this.getHandle().immuneToLightning = immuneToLightning;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isImmuneToLightning() {
|
|
+ return this.getHandle().immuneToLightning;
|
|
+ }
|
|
+ // Purpur end - Item entity immunities
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
|
index 4f98d138a275a6c34528b7a5148ef265bc38d6b5..3a9d9b7526b2bf0fbd4e0d7886b3d849a6dcfee9 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
|
@@ -523,7 +523,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
|
net.minecraft.server.level.ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle();
|
|
getHandle().lastHurtByPlayer = entityPlayer;
|
|
getHandle().lastHurtByMob = entityPlayer;
|
|
- getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity
|
|
+ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : getHandle().level().purpurConfig.mobLastHurtByPlayerTime; // 100 value taken from EntityLiving#damageEntity // Purpur - Config for mob last hurt by player time
|
|
}
|
|
// Paper end
|
|
|
|
@@ -1211,4 +1211,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
|
return this.getHandle().canUseSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot));
|
|
}
|
|
// Paper end - Expose canUseSlot
|
|
+
|
|
+ // Purpur start - API for any mob to burn daylight
|
|
+ @Override
|
|
+ public boolean shouldBurnInDay() {
|
|
+ return this.getHandle().shouldBurnInDay();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setShouldBurnInDay(final boolean shouldBurnInDay) {
|
|
+ this.getHandle().setShouldBurnInDay(shouldBurnInDay);
|
|
+ }
|
|
+ // Purpur end - API for any mob to burn daylight
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
|
|
index 351f42842b780d053cd2e5bad9ae299449141b10..054d2c2b93c43faeeaf56f482eb7b9431a6190df 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
|
|
@@ -90,4 +90,16 @@ public class CraftLlama extends CraftChestedHorse implements Llama, com.destroys
|
|
return this.getHandle().caravanTail == null ? null : (Llama) this.getHandle().caravanTail.getBukkitEntity();
|
|
}
|
|
// Paper end
|
|
+
|
|
+ // Purpur start - Llama API
|
|
+ @Override
|
|
+ public boolean shouldJoinCaravan() {
|
|
+ return getHandle().shouldJoinCaravan;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setShouldJoinCaravan(boolean shouldJoinCaravan) {
|
|
+ getHandle().shouldJoinCaravan = shouldJoinCaravan;
|
|
+ }
|
|
+ // Purpur end - Llama API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
index baffa036078bfc38505f9008a54a5abff65704db..d84d716629d93e264bc40c565e9fedd1ce38722c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
@@ -591,10 +591,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
@Override
|
|
public void setPlayerListName(String name) {
|
|
+ // Purpur start - AFK API
|
|
+ setPlayerListName(name, false);
|
|
+ }
|
|
+ public void setPlayerListName(String name, boolean useMM) {
|
|
+ // Purpur end - AFK API
|
|
if (name == null) {
|
|
name = this.getName();
|
|
}
|
|
- this.getHandle().listName = name.equals(this.getName()) ? null : CraftChatMessage.fromStringOrNull(name);
|
|
+ this.getHandle().listName = name.equals(this.getName()) ? null : useMM ? io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(name)) : CraftChatMessage.fromStringOrNull(name); // Purpur - AFK API
|
|
if (this.getHandle().connection == null) return; // Paper - Updates are possible before the player has fully joined
|
|
for (ServerPlayer player : (List<ServerPlayer>) this.server.getHandle().players) {
|
|
if (player.getBukkitEntity().canSee(this)) {
|
|
@@ -1433,6 +1438,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
// Paper start - Teleport passenger API
|
|
// Don't allow teleporting between worlds while keeping passengers
|
|
if (ignorePassengers && entity.isVehicle() && location.getWorld() != this.getWorld()) {
|
|
+ if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, cause).callEvent()) // Purpur - Add EntityTeleportHinderedEvent
|
|
return false;
|
|
}
|
|
|
|
@@ -1454,6 +1460,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
}
|
|
|
|
if (entity.isVehicle() && !ignorePassengers) { // Paper - Teleport API
|
|
+ if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, cause).callEvent()) // Purpur - Add EntityTeleportHinderedEvent
|
|
return false;
|
|
}
|
|
|
|
@@ -2752,6 +2759,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
return this.getHandle().getAbilities().walkingSpeed * 2f;
|
|
}
|
|
|
|
+ // Purpur start - OfflinePlayer API
|
|
+ @Override
|
|
+ public boolean teleportOffline(@NotNull Location destination) {
|
|
+ return this.teleport(destination);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean teleportOffline(Location destination, PlayerTeleportEvent.TeleportCause cause) {
|
|
+ return this.teleport(destination, cause);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(@NotNull Location destination) {
|
|
+ return this.teleportAsync(destination);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(@NotNull Location destination, PlayerTeleportEvent.TeleportCause cause) {
|
|
+ return this.teleportAsync(destination, cause);
|
|
+ }
|
|
+ // Purpur end - OfflinePlayer API
|
|
+
|
|
private void validateSpeed(float value) {
|
|
Preconditions.checkArgument(value <= 1f && value >= -1f, "Speed value (%s) need to be between -1f and 1f", value);
|
|
}
|
|
@@ -3581,4 +3610,75 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
handle.containerMenu.broadcastChanges();
|
|
return new PaperPlayerGiveResult(leftovers.build(), drops.build());
|
|
}
|
|
+
|
|
+ // Purpur start - Purpur client support
|
|
+ @Override
|
|
+ public boolean usesPurpurClient() {
|
|
+ return getHandle().purpurClient;
|
|
+ }
|
|
+ // Purpur end - Purpur client support
|
|
+ // Purpur start - AFK API
|
|
+ @Override
|
|
+ public boolean isAfk() {
|
|
+ return getHandle().isAfk();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setAfk(boolean setAfk) {
|
|
+ getHandle().setAfk(setAfk);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void resetIdleTimer() {
|
|
+ getHandle().resetLastActionTime();
|
|
+ }
|
|
+ // Purpur end - AFK API
|
|
+
|
|
+ // Purpur start - Debug Marker API
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration) {
|
|
+ sendBlockHighlight(location, duration, "", 0x6400FF00);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, int argb) {
|
|
+ sendBlockHighlight(location, duration, "", argb);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text) {
|
|
+ sendBlockHighlight(location, duration, text, 0x6400FF00);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text, int argb) {
|
|
+ if (this.getHandle().connection == null) return;
|
|
+ this.getHandle().connection.send(new net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket(new net.minecraft.network.protocol.common.custom.GameTestAddMarkerDebugPayload(io.papermc.paper.util.MCUtil.toBlockPosition(location), argb, text, duration)));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, org.bukkit.Color color, int transparency) {
|
|
+ sendBlockHighlight(location, duration, "", color, transparency);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendBlockHighlight(Location location, int duration, String text, org.bukkit.Color color, int transparency) {
|
|
+ if (transparency < 0 || transparency > 255) throw new IllegalArgumentException("transparency is outside of 0-255 range");
|
|
+ sendBlockHighlight(location, duration, text, transparency << 24 | color.asRGB());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void clearBlockHighlights() {
|
|
+ if (this.getHandle().connection == null) return;
|
|
+ this.getHandle().connection.send(new net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket(new net.minecraft.network.protocol.common.custom.GameTestClearMarkersDebugPayload()));
|
|
+ }
|
|
+ // Purpur end - Debug Marker API
|
|
+
|
|
+ // Purpur start - Death screen API
|
|
+ @Override
|
|
+ public void sendDeathScreen(net.kyori.adventure.text.Component message) {
|
|
+ if (this.getHandle().connection == null) return;
|
|
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerCombatKillPacket(getEntityId(), io.papermc.paper.adventure.PaperAdventure.asVanilla(message)));
|
|
+ }
|
|
+ // Purpur end - Death screen API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
|
|
index 4ce2373ff71c3c1b8951646e057587a3ab09e145..997b8e5059569de4ee8e70127c5d6019ce53afe3 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
|
|
@@ -28,4 +28,17 @@ public class CraftSnowman extends CraftGolem implements Snowman, com.destroystok
|
|
public String toString() {
|
|
return "CraftSnowman";
|
|
}
|
|
+
|
|
+ // Purpur start - Summoner API
|
|
+ @Override
|
|
+ @org.jetbrains.annotations.Nullable
|
|
+ public java.util.UUID getSummoner() {
|
|
+ return getHandle().getSummoner();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setSummoner(@org.jetbrains.annotations.Nullable java.util.UUID summoner) {
|
|
+ getHandle().setSummoner(summoner);
|
|
+ }
|
|
+ // Purpur end - Summoner API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
|
index aaddce10e1d41531939d1e7f3d717b458ec1b7ab..d65a3bee4671e9e21769ba03f5e65c7312b23580 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
|
@@ -373,4 +373,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
|
|
getHandle().getGossips().gossips.clear();
|
|
}
|
|
// Paper end
|
|
+
|
|
+ // Purpur start - Lobotomize stuck villagers
|
|
+ @Override
|
|
+ public boolean isLobotomized() {
|
|
+ return getHandle().isLobotomized();
|
|
+ }
|
|
+ // Purpur end - Lobotomize stuck villagers
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java
|
|
index 7881c6253c1d652c0c0d54a9a8accdf0a1ff0f3e..fe8be71121324f64346174922c7bc7f5d3a9de69 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java
|
|
@@ -99,4 +99,17 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok
|
|
this.getHandle().makeInvulnerable();
|
|
}
|
|
// Paper end
|
|
+
|
|
+ // Purpur start - Summoner API
|
|
+ @Override
|
|
+ @org.jetbrains.annotations.Nullable
|
|
+ public java.util.UUID getSummoner() {
|
|
+ return getHandle().getSummoner();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setSummoner(@org.jetbrains.annotations.Nullable java.util.UUID summoner) {
|
|
+ getHandle().setSummoner(summoner);
|
|
+ }
|
|
+ // Purpur end - Summoner API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java
|
|
index c1b7f1281fbd41e765d2c1881763ca25b20e924d..53c620e717d39ef16f44c9697ac4809ac1fdfa6a 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java
|
|
@@ -145,4 +145,15 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
|
|
return this.getKey().hashCode();
|
|
}
|
|
}
|
|
+ // Purpur start - Configurable chance for wolves to spawn rabid
|
|
+ @Override
|
|
+ public boolean isRabid() {
|
|
+ return getHandle().isRabid();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setRabid(boolean isRabid) {
|
|
+ getHandle().setRabid(isRabid);
|
|
+ }
|
|
+ // Purpur end - Configurable chance for wolves to spawn rabid
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
index d7a52220e9525502163f5ee6afbadf2baaae6190..1b7fdbecf9c28732d5196236980e87fa737a0769 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
@@ -602,6 +602,15 @@ public class CraftEventFactory {
|
|
// Paper end
|
|
craftServer.getPluginManager().callEvent(event);
|
|
|
|
+ // Purpur start - Ridables
|
|
+ if (who != null) {
|
|
+ switch (action) {
|
|
+ case LEFT_CLICK_BLOCK, LEFT_CLICK_AIR -> who.processClick(InteractionHand.MAIN_HAND);
|
|
+ case RIGHT_CLICK_BLOCK, RIGHT_CLICK_AIR -> who.processClick(InteractionHand.OFF_HAND);
|
|
+ }
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
return event;
|
|
}
|
|
|
|
@@ -1131,7 +1140,7 @@ public class CraftEventFactory {
|
|
return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.LAVA, bukkitDamageSource, modifiers, modifierFunctions, cancelled);
|
|
} else if (source.getDirectBlock() != null) {
|
|
DamageCause cause;
|
|
- if (source.is(DamageTypes.CACTUS) || source.is(DamageTypes.SWEET_BERRY_BUSH) || source.is(DamageTypes.STALAGMITE) || source.is(DamageTypes.FALLING_STALACTITE) || source.is(DamageTypes.FALLING_ANVIL)) {
|
|
+ if (source.is(DamageTypes.CACTUS) || source.is(DamageTypes.SWEET_BERRY_BUSH) || source.is(DamageTypes.STALAGMITE) || source.is(DamageTypes.FALLING_STALACTITE) || source.is(DamageTypes.FALLING_ANVIL) || source.isStonecutter()) { // Purpur - Stonecutter damage
|
|
cause = DamageCause.CONTACT;
|
|
} else if (source.is(DamageTypes.HOT_FLOOR)) {
|
|
cause = DamageCause.HOT_FLOOR;
|
|
@@ -1191,6 +1200,7 @@ public class CraftEventFactory {
|
|
EntityDamageEvent event;
|
|
if (damager != null) {
|
|
event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, critical);
|
|
+ damager.processClick(InteractionHand.MAIN_HAND); // Purpur - Ridables
|
|
} else {
|
|
event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions);
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
|
index 1ce328bed5cf3d087a3f7dc9236153381d758493..364afc994443f6c64af4f9ebbe210da63e18681c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
|
@@ -145,8 +145,19 @@ public class CraftContainer extends AbstractContainerMenu {
|
|
case PLAYER:
|
|
case CHEST:
|
|
case ENDER_CHEST:
|
|
+ // Purpur start - Barrels and enderchests 6 rows
|
|
+ this.delegate = new ChestMenu(org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? net.minecraft.world.inventory.MenuType.GENERIC_9x6 : net.minecraft.world.inventory.MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9);
|
|
+ break;
|
|
case BARREL:
|
|
- this.delegate = new ChestMenu(net.minecraft.world.inventory.MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9);
|
|
+ this.delegate = new ChestMenu(switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
|
|
+ case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6;
|
|
+ case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5;
|
|
+ case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4;
|
|
+ case 2 -> net.minecraft.world.inventory.MenuType.GENERIC_9x2;
|
|
+ case 1 -> net.minecraft.world.inventory.MenuType.GENERIC_9x1;
|
|
+ default -> net.minecraft.world.inventory.MenuType.GENERIC_9x3;
|
|
+ }, windowId, bottom, top, top.getContainerSize() / 9);
|
|
+ // Purpur end - Barrels and enderchests 6 rows
|
|
break;
|
|
case DISPENSER:
|
|
case DROPPER:
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
|
index c6159c70f7a37b9bffe268b91905ce848d1d2927..8b4f8a475faafe3b8a479160888145c4aa603a27 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
|
@@ -84,7 +84,7 @@ public class CraftInventory implements Inventory {
|
|
|
|
@Override
|
|
public void setContents(ItemStack[] items) {
|
|
- Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize());
|
|
+ // Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize()); // Purpur - Barrels and enderchests 6 rows
|
|
|
|
for (int i = 0; i < this.getSize(); i++) {
|
|
if (i >= items.length) {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
|
|
index 792cb6adf0c7a6335cc5985fce8bed2e0f1149af..5734c5caffda79383ae30df20c3defb51b87f39e 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
|
|
@@ -19,6 +19,10 @@ public class CraftInventoryAnvil extends CraftResultInventory implements AnvilIn
|
|
private int repairCost;
|
|
private int repairCostAmount;
|
|
private int maximumRepairCost;
|
|
+ // Purpur start - Anvil API
|
|
+ private boolean bypassCost;
|
|
+ private boolean canDoUnsafeEnchants;
|
|
+ // Purpur end - Anvil API
|
|
|
|
public CraftInventoryAnvil(Location location, Container inventory, Container resultInventory) {
|
|
super(inventory, resultInventory);
|
|
@@ -27,6 +31,10 @@ public class CraftInventoryAnvil extends CraftResultInventory implements AnvilIn
|
|
this.repairCost = CraftInventoryAnvil.DEFAULT_REPAIR_COST;
|
|
this.repairCostAmount = CraftInventoryAnvil.DEFAULT_REPAIR_COST_AMOUNT;
|
|
this.maximumRepairCost = CraftInventoryAnvil.DEFAULT_MAXIMUM_REPAIR_COST;
|
|
+ // Purpur start - Anvil API
|
|
+ this.bypassCost = false;
|
|
+ this.canDoUnsafeEnchants = false;
|
|
+ // Purpur end - Anvil API
|
|
}
|
|
|
|
@Override
|
|
@@ -113,4 +121,30 @@ public class CraftInventoryAnvil extends CraftResultInventory implements AnvilIn
|
|
consumer.accept(cav);
|
|
}
|
|
}
|
|
+
|
|
+ // Purpur start - Anvil API
|
|
+ @Override
|
|
+ public boolean canBypassCost() {
|
|
+ this.syncWithArbitraryViewValue((cav) -> this.bypassCost = cav.canBypassCost());
|
|
+ return this.bypassCost;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setBypassCost(boolean bypassCost) {
|
|
+ this.bypassCost = bypassCost;
|
|
+ this.syncViews((cav) -> cav.setBypassCost(bypassCost));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canDoUnsafeEnchants() {
|
|
+ this.syncWithArbitraryViewValue((cav) -> this.canDoUnsafeEnchants = cav.canDoUnsafeEnchants());
|
|
+ return this.canDoUnsafeEnchants;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setDoUnsafeEnchants(boolean canDoUnsafeEnchants) {
|
|
+ this.canDoUnsafeEnchants = canDoUnsafeEnchants;
|
|
+ this.syncViews((cav) -> cav.setDoUnsafeEnchants(canDoUnsafeEnchants));
|
|
+ }
|
|
+ // Purpur end - Anvil API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
|
index 3799973696eabbdc992bee4ff24175fc28ec8d7c..ae68b1d72be45503acc8c7a52b20d95d7b651f06 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
|
@@ -666,4 +666,285 @@ public final class CraftItemStack extends ItemStack {
|
|
}
|
|
|
|
// Paper end - data component API
|
|
+
|
|
+ // Purpur start - ItemStack convenience methods
|
|
+ @Override
|
|
+ public String getDisplayName() {
|
|
+ return getItemMeta().getDisplayName();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setDisplayName(String name) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ itemMeta.setDisplayName(name);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasDisplayName() {
|
|
+ return hasItemMeta() && getItemMeta().hasDisplayName();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String getLocalizedName() {
|
|
+ return getItemMeta().getLocalizedName();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setLocalizedName(String name) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ itemMeta.setLocalizedName(name);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasLocalizedName() {
|
|
+ return hasItemMeta() && getItemMeta().hasLocalizedName();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasLore() {
|
|
+ return hasItemMeta() && getItemMeta().hasLore();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasEnchant(Enchantment ench) {
|
|
+ return hasItemMeta() && getItemMeta().hasEnchant(ench);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getEnchantLevel(Enchantment ench) {
|
|
+ return getItemMeta().getEnchantLevel(ench);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Map<Enchantment, Integer> getEnchants() {
|
|
+ return getItemMeta().getEnchants();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean addEnchant(Enchantment ench, int level, boolean ignoreLevelRestriction) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ boolean result = itemMeta.addEnchant(ench, level, ignoreLevelRestriction);
|
|
+ setItemMeta(itemMeta);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean removeEnchant(Enchantment ench) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ boolean result = itemMeta.removeEnchant(ench);
|
|
+ setItemMeta(itemMeta);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasEnchants() {
|
|
+ return hasItemMeta() && getItemMeta().hasEnchants();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasConflictingEnchant(Enchantment ench) {
|
|
+ return hasItemMeta() && getItemMeta().hasConflictingEnchant(ench);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setCustomModelData(Integer data) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ itemMeta.setCustomModelData(data);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getCustomModelData() {
|
|
+ return getItemMeta().getCustomModelData();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasCustomModelData() {
|
|
+ return hasItemMeta() && getItemMeta().hasCustomModelData();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasBlockData() {
|
|
+ return hasItemMeta() && ((org.bukkit.inventory.meta.BlockDataMeta) getItemMeta()).hasBlockData();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public org.bukkit.block.data.BlockData getBlockData(Material material) {
|
|
+ return ((org.bukkit.inventory.meta.BlockDataMeta) getItemMeta()).getBlockData(material);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setBlockData(org.bukkit.block.data.BlockData blockData) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ ((org.bukkit.inventory.meta.BlockDataMeta) itemMeta).setBlockData(blockData);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getRepairCost() {
|
|
+ return ((org.bukkit.inventory.meta.Repairable) getItemMeta()).getRepairCost();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setRepairCost(int cost) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ ((org.bukkit.inventory.meta.Repairable) itemMeta).setRepairCost(cost);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasRepairCost() {
|
|
+ return hasItemMeta() && ((org.bukkit.inventory.meta.Repairable) getItemMeta()).hasRepairCost();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isUnbreakable() {
|
|
+ return hasItemMeta() && getItemMeta().isUnbreakable();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setUnbreakable(boolean unbreakable) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ itemMeta.setUnbreakable(unbreakable);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasAttributeModifiers() {
|
|
+ return hasItemMeta() && getItemMeta().hasAttributeModifiers();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public com.google.common.collect.Multimap<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> getAttributeModifiers() {
|
|
+ return getItemMeta().getAttributeModifiers();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public com.google.common.collect.Multimap<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> getAttributeModifiers(org.bukkit.inventory.EquipmentSlot slot) {
|
|
+ return getItemMeta().getAttributeModifiers(slot);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public java.util.Collection<org.bukkit.attribute.AttributeModifier> getAttributeModifiers(org.bukkit.attribute.Attribute attribute) {
|
|
+ return getItemMeta().getAttributeModifiers(attribute);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean addAttributeModifier(org.bukkit.attribute.Attribute attribute, org.bukkit.attribute.AttributeModifier modifier) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ boolean result = itemMeta.addAttributeModifier(attribute, modifier);
|
|
+ setItemMeta(itemMeta);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setAttributeModifiers(com.google.common.collect.Multimap<org.bukkit.attribute.Attribute, org.bukkit.attribute.AttributeModifier> attributeModifiers) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ itemMeta.setAttributeModifiers(attributeModifiers);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean removeAttributeModifier(org.bukkit.attribute.Attribute attribute) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ boolean result = itemMeta.removeAttributeModifier(attribute);
|
|
+ setItemMeta(itemMeta);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean removeAttributeModifier(org.bukkit.inventory.EquipmentSlot slot) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ boolean result = itemMeta.removeAttributeModifier(slot);
|
|
+ setItemMeta(itemMeta);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean removeAttributeModifier(org.bukkit.attribute.Attribute attribute, org.bukkit.attribute.AttributeModifier modifier) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ boolean result = itemMeta.removeAttributeModifier(attribute, modifier);
|
|
+ setItemMeta(itemMeta);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasDamage() {
|
|
+ return hasItemMeta() && ((org.bukkit.inventory.meta.Damageable) getItemMeta()).hasDamage();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getDamage() {
|
|
+ return ((org.bukkit.inventory.meta.Damageable) getItemMeta()).getDamage();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setDamage(int damage) {
|
|
+ ItemMeta itemMeta = getItemMeta();
|
|
+ ((org.bukkit.inventory.meta.Damageable) itemMeta).setDamage(damage);
|
|
+ setItemMeta(itemMeta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void repair() {
|
|
+ repair(1);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean damage() {
|
|
+ return damage(1);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void repair(int amount) {
|
|
+ damage(-amount);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean damage(int amount) {
|
|
+ return damage(amount, false);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean damage(int amount, boolean ignoreUnbreaking) {
|
|
+ org.bukkit.inventory.meta.Damageable damageable = (org.bukkit.inventory.meta.Damageable) getItemMeta();
|
|
+ if (amount > 0) {
|
|
+ int unbreaking = getEnchantLevel(Enchantment.UNBREAKING);
|
|
+ int reduce = 0;
|
|
+ for (int i = 0; unbreaking > 0 && i < amount; ++i) {
|
|
+ if (reduceDamage(java.util.concurrent.ThreadLocalRandom.current(), unbreaking)) {
|
|
+ ++reduce;
|
|
+ }
|
|
+ }
|
|
+ amount -= reduce;
|
|
+ if (amount <= 0) {
|
|
+ return isBroke(damageable.getDamage());
|
|
+ }
|
|
+ }
|
|
+ int damage = damageable.getDamage() + amount;
|
|
+ damageable.setDamage(damage);
|
|
+ setItemMeta((ItemMeta) damageable);
|
|
+ return isBroke(damage);
|
|
+ }
|
|
+
|
|
+ private boolean isBroke(int damage) {
|
|
+ if (damage > getType().getMaxDurability()) {
|
|
+ if (getAmount() > 0) {
|
|
+ // ensure it "breaks"
|
|
+ setAmount(0);
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private boolean reduceDamage(java.util.Random random, int unbreaking) {
|
|
+ if (getType().isArmor()) {
|
|
+ return random.nextFloat() < 0.6F;
|
|
+ }
|
|
+ return random.nextInt(unbreaking + 1) > 0;
|
|
+ }
|
|
+ // Purpur end - ItemStack convenience methods
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
|
index 4864e2016cb1d377425297fd1c52b383632cb59e..953d64d128a53eb9ec2ff55140dde5cb80326044 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
|
@@ -36,6 +36,7 @@ public interface CraftRecipe extends Recipe {
|
|
stack = Ingredient.of(((RecipeChoice.MaterialChoice) bukkit).getChoices().stream().map((mat) -> CraftItemType.bukkitToMinecraft(mat)));
|
|
} else if (bukkit instanceof RecipeChoice.ExactChoice) {
|
|
stack = Ingredient.ofStacks(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> CraftItemStack.asNMSCopy(mat)).toList());
|
|
+ stack.predicate = ((RecipeChoice.ExactChoice) bukkit).getPredicate(); // Purpur - Add predicate to recipe's ExactChoice ingredient
|
|
// Paper start - support "empty" choices - legacy method that spigot might incorrectly call
|
|
// Their impl of Ingredient.of() will error, ingredients need at least one entry.
|
|
// Callers running into this exception may have passed an incorrect empty() recipe choice to a non-empty slot or
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java
|
|
index f86c95a13dff012de5db3e41ac261e9e8d44d9f3..1db0b790d824e419bb5fb6ab1f3003e120f9763b 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java
|
|
@@ -75,4 +75,26 @@ public class CraftAnvilView extends CraftInventoryView<AnvilMenu, AnvilInventory
|
|
this.setMaximumRepairCost(legacy.getMaximumRepairCost());
|
|
}
|
|
}
|
|
+
|
|
+ // Purpur start - Anvil API
|
|
+ @Override
|
|
+ public boolean canBypassCost() {
|
|
+ return this.container.bypassCost;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setBypassCost(boolean bypassCost) {
|
|
+ this.container.bypassCost = bypassCost;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canDoUnsafeEnchants() {
|
|
+ return this.container.canDoUnsafeEnchants;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setDoUnsafeEnchants(boolean canDoUnsafeEnchants) {
|
|
+ this.container.canDoUnsafeEnchants = canDoUnsafeEnchants;
|
|
+ }
|
|
+ // Purpur end - Anvil API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
|
index db8d8e2a07296d62c3097f02b03319e2e1ba9394..4ba4d52961b4ba61fe2db130ee4368ff358920d4 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
|
@@ -708,4 +708,32 @@ public class MaterialRerouting {
|
|
meta.setCanPlaceOn(materials);
|
|
}
|
|
// Paper end
|
|
+ // Purpur start - Adopt MaterialRerouting
|
|
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
|
|
+ public static void addFuel(Server server, Material material, int burnTime) {
|
|
+ server.addFuel(material, burnTime);
|
|
+ }
|
|
+
|
|
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
|
|
+ public static void removeFuel(Server server, Material material) {
|
|
+ server.removeFuel(material);
|
|
+ }
|
|
+
|
|
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
|
|
+ @RerouteStatic("org/bukkit/Bukkit")
|
|
+ public static void addFuel(Material material, int burnTime) {
|
|
+ Bukkit.addFuel(material, burnTime);
|
|
+ }
|
|
+
|
|
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
|
|
+ @RerouteStatic("org/bukkit/Bukkit")
|
|
+ public static void removeFuel(Material material) {
|
|
+ Bukkit.removeFuel(material);
|
|
+ }
|
|
+
|
|
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/commit/607d909efba516893072b782c0393c53d048210e)
|
|
+ public static BlockData getBlockData(ItemStack itemStack, Material material) {
|
|
+ return itemStack.getBlockData(MaterialRerouting.transformToBlockType(material));
|
|
+ }
|
|
+ // Purpur end - Adopt MaterialRerouting
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
|
|
index cf0920e5f84b35647882fb963e9972af4e8427e0..2949cd29c7fa707835044a4b61eae150df56296e 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
|
|
@@ -49,4 +49,10 @@ public class CraftMapRenderer extends MapRenderer {
|
|
}
|
|
}
|
|
|
|
+ // Purpur start - Explorer Map API
|
|
+ @Override
|
|
+ public boolean isExplorerMap() {
|
|
+ return this.worldMap.isExplorerMap;
|
|
+ }
|
|
+ // Purpur end - Explorer Map API
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
|
|
index b3169c551b8410f5861f9db0543c785439ecba7c..377b6bdc80019f0c824c8fd35a8f228315bafe9f 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
|
|
@@ -23,7 +23,15 @@ public final class CommandPermissions {
|
|
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "kick", "Allows the user to kick players", PermissionDefault.OP, commands);
|
|
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stop", "Allows the user to stop the server", PermissionDefault.OP, commands);
|
|
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands);
|
|
- DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands);
|
|
+ // Purpur start - Gamemode extra permissions
|
|
+ Permission gamemodeVanilla = DefaultPermissions.registerPermission(PREFIX + "gamemode", "Allows the user to change the gamemode", PermissionDefault.OP, commands);
|
|
+ for (net.minecraft.world.level.GameType gametype : net.minecraft.world.level.GameType.values()) {
|
|
+ Permission gamemodeSelf = DefaultPermissions.registerPermission(PREFIX + "gamemode." + gametype.getName(), "Allows the user to set " + gametype.getName() + " gamemode for self", PermissionDefault.OP);
|
|
+ Permission gamemodeOther = DefaultPermissions.registerPermission(PREFIX + "gamemode." + gametype.getName() + ".other", "Allows the user to set " + gametype.getName() + " gamemode for other players", PermissionDefault.OP);
|
|
+ gamemodeSelf.addParent(gamemodeOther, true);
|
|
+ gamemodeVanilla.addParent(gamemodeSelf, true);
|
|
+ }
|
|
+ // Purpur end - Gamemode extra permissions
|
|
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "experience", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands); // Paper - wrong permission; redirects are de-redirected and the root literal name is used, so xp -> experience
|
|
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "defaultgamemode", "Allows the user to change the default gamemode of the server", PermissionDefault.OP, commands);
|
|
DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "seed", "Allows the user to view the seed of the world", PermissionDefault.OP, commands);
|
|
diff --git a/src/main/java/org/purpurmc/purpur/configuration/transformation/VoidDamageHeightMigration.java b/src/main/java/org/purpurmc/purpur/configuration/transformation/VoidDamageHeightMigration.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..a04d23bd98075cd65a24d4de8d18281d1668480f
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/configuration/transformation/VoidDamageHeightMigration.java
|
|
@@ -0,0 +1,67 @@
|
|
+package org.purpurmc.purpur.configuration.transformation;
|
|
+
|
|
+import io.papermc.paper.configuration.Configurations;
|
|
+import io.papermc.paper.configuration.PaperConfigurations;
|
|
+import io.papermc.paper.configuration.type.number.DoubleOr;
|
|
+import java.util.OptionalDouble;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.purpurmc.purpur.PurpurConfig;
|
|
+import org.spongepowered.configurate.ConfigurateException;
|
|
+import org.spongepowered.configurate.ConfigurationNode;
|
|
+import org.spongepowered.configurate.NodePath;
|
|
+import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
|
+import org.spongepowered.configurate.transformation.TransformAction;
|
|
+
|
|
+import static org.spongepowered.configurate.NodePath.path;
|
|
+
|
|
+public class VoidDamageHeightMigration implements TransformAction {
|
|
+
|
|
+ public static boolean HAS_BEEN_REGISTERED = false;
|
|
+
|
|
+ public static final String ENVIRONMENT_KEY = "environment";
|
|
+ public static final String VOID_DAMAGE_KEY = "void-damage-amount";
|
|
+ public static final String VOID_DAMAGE_MIN_HEIGHT_OFFSET_KEY = "void-damage-min-build-height-offset";
|
|
+ public static final double DEFAULT_VOID_DAMAGE_HEIGHT = -64.0D;
|
|
+ public static final double DEFAULT_VOID_DAMAGE = 4.0D;
|
|
+
|
|
+ private final String worldName;
|
|
+
|
|
+ private VoidDamageHeightMigration(String worldName) {
|
|
+ this.worldName = PaperConfigurations.WORLD_DEFAULTS.equals(worldName) ? "default" : worldName;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Object @Nullable [] visitPath(final NodePath path, final ConfigurationNode value) throws ConfigurateException {
|
|
+ String purpurVoidDamageHeightPath = "world-settings." + this.worldName + ".gameplay-mechanics.void-damage-height";
|
|
+ ConfigurationNode voidDamageMinHeightOffsetNode = value.node(ENVIRONMENT_KEY, VOID_DAMAGE_MIN_HEIGHT_OFFSET_KEY);
|
|
+ if (PurpurConfig.config.contains(purpurVoidDamageHeightPath)) {
|
|
+ double purpurVoidDamageHeight = PurpurConfig.config.getDouble(purpurVoidDamageHeightPath);
|
|
+ if (purpurVoidDamageHeight != DEFAULT_VOID_DAMAGE_HEIGHT && (voidDamageMinHeightOffsetNode.empty() || voidDamageMinHeightOffsetNode.getDouble() == DEFAULT_VOID_DAMAGE_HEIGHT)) {
|
|
+ voidDamageMinHeightOffsetNode.raw(null);
|
|
+ voidDamageMinHeightOffsetNode.set(purpurVoidDamageHeight);
|
|
+ }
|
|
+ PurpurConfig.config.set(purpurVoidDamageHeightPath, null);
|
|
+ }
|
|
+
|
|
+ String purpurVoidDamagePath = "world-settings." + this.worldName + ".gameplay-mechanics.void-damage-dealt";
|
|
+ ConfigurationNode voidDamageNode = value.node(ENVIRONMENT_KEY, VOID_DAMAGE_KEY);
|
|
+ if (PurpurConfig.config.contains(purpurVoidDamagePath)) {
|
|
+ double purpurVoidDamage = PurpurConfig.config.getDouble(purpurVoidDamagePath);
|
|
+ if (purpurVoidDamage != DEFAULT_VOID_DAMAGE && (voidDamageNode.empty() || voidDamageNode.getDouble() == DEFAULT_VOID_DAMAGE)) {
|
|
+ voidDamageNode.raw(null);
|
|
+ voidDamageNode.set(new DoubleOr.Disabled(OptionalDouble.of(purpurVoidDamage)));
|
|
+ }
|
|
+ PurpurConfig.config.set(purpurVoidDamagePath, null);
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ public static void apply(final ConfigurationTransformation.Builder builder, final Configurations.ContextMap contextMap) {
|
|
+ if (PurpurConfig.version < 36) {
|
|
+ HAS_BEEN_REGISTERED = true;
|
|
+ builder.addAction(path(), new VoidDamageHeightMigration(contextMap.require(Configurations.WORLD_NAME)));
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
|
index d2a75850af9c6ad2aca66a5f994f1b587d73eac4..a056aa167887abef9e6d531a9edd2cda433567d2 100644
|
|
--- a/src/main/resources/log4j2.xml
|
|
+++ b/src/main/resources/log4j2.xml
|
|
@@ -2,7 +2,16 @@
|
|
<Configuration status="WARN" shutdownHook="disable">
|
|
<Appenders>
|
|
<Queue name="ServerGuiConsole">
|
|
- <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" />
|
|
+ <!-- Purpur start - copied from TerminalConsole -->
|
|
+ <PatternLayout>
|
|
+ <LoggerNamePatternSelector defaultPattern="%highlightGUIError{[%d{HH:mm:ss} %level]: [%logger] %stripAnsi{%msg}%n%xEx{full}}">
|
|
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
|
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
|
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
|
+ pattern="%highlightGUIError{[%d{HH:mm:ss} %level]: %stripAnsi{%msg}%n%xEx{full}}" />
|
|
+ </LoggerNamePatternSelector>
|
|
+ </PatternLayout>
|
|
+ <!-- Purpur end -->
|
|
</Queue>
|
|
<TerminalConsole name="TerminalConsole">
|
|
<PatternLayout>
|
|
diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
|
|
index 75ed5050f72c001d6eab117a2c0b352a413548bd..2764d4204d51a3615f27b8bfd7b6675294465155 100644
|
|
--- a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
|
|
+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
|
|
@@ -46,6 +46,7 @@ public class MinecraftCommandPermissionsTest {
|
|
Set<String> foundPerms = new HashSet<>();
|
|
for (CommandNode<CommandSourceStack> child : root.getChildren()) {
|
|
final String vanillaPerm = VanillaCommandWrapper.getPermission(child);
|
|
+ if (TO_SKIP.contains(vanillaPerm)) continue; // Purpur - Skip junit tests for purpur commands
|
|
if (!perms.contains(vanillaPerm)) {
|
|
missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command");
|
|
} else {
|
|
@@ -58,6 +59,25 @@ public class MinecraftCommandPermissionsTest {
|
|
}
|
|
|
|
private static final List<String> TO_SKIP = List.of(
|
|
+ // Purpur start - Skip junit tests for purpur commands
|
|
+ "minecraft.command.compass",
|
|
+ "minecraft.command.credits",
|
|
+ "minecraft.command.demo",
|
|
+ "minecraft.command.ping",
|
|
+ "minecraft.command.ram",
|
|
+ "minecraft.command.rambar",
|
|
+ "minecraft.command.tpsbar",
|
|
+ "minecraft.command.uptime",
|
|
+ "minecraft.command.debug",
|
|
+ "minecraft.command.gamemode.adventure",
|
|
+ "minecraft.command.gamemode.adventure.other",
|
|
+ "minecraft.command.gamemode.creative",
|
|
+ "minecraft.command.gamemode.creative.other",
|
|
+ "minecraft.command.gamemode.spectator",
|
|
+ "minecraft.command.gamemode.spectator.other",
|
|
+ "minecraft.command.gamemode.survival",
|
|
+ "minecraft.command.gamemode.survival.other",
|
|
+ // Purpur end - Skip junit tests for purpur commands
|
|
"minecraft.command.selector"
|
|
);
|
|
|