add remapped patches as a test
This commit is contained in:
parent
0a44692ef6
commit
bee74680e6
2618 changed files with 479913 additions and 0 deletions
|
@ -0,0 +1,16 @@
|
|||
--- a/net/minecraft/CrashReport.java
|
||||
+++ b/net/minecraft/CrashReport.java
|
||||
@@ -33,9 +33,10 @@
|
||||
private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0];
|
||||
private final SystemReport systemReport = new SystemReport();
|
||||
|
||||
- public CrashReport(String s, Throwable throwable) {
|
||||
- this.title = s;
|
||||
- this.exception = throwable;
|
||||
+ public CrashReport(String title, Throwable exception) {
|
||||
+ this.title = title;
|
||||
+ this.exception = exception;
|
||||
+ this.systemReport.setDetail("CraftBukkit Information", new org.bukkit.craftbukkit.CraftCrashReport()); // CraftBukkit
|
||||
}
|
||||
|
||||
public String getTitle() {
|
|
@ -0,0 +1,24 @@
|
|||
--- a/net/minecraft/advancements/AdvancementHolder.java
|
||||
+++ b/net/minecraft/advancements/AdvancementHolder.java
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.advancement.CraftAdvancement;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+// CraftBukkit end
|
||||
|
||||
public record AdvancementHolder(ResourceLocation id, Advancement value) {
|
||||
|
||||
@@ -44,4 +45,10 @@
|
||||
public String toString() {
|
||||
return this.id.toString();
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public final org.bukkit.advancement.Advancement toBukkit() {
|
||||
+ return new CraftAdvancement(this);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/advancements/AdvancementTree.java
|
||||
+++ b/net/minecraft/advancements/AdvancementTree.java
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size());
|
||||
+ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload
|
||||
}
|
||||
|
||||
private boolean tryInsert(AdvancementHolder advancementholder) {
|
|
@ -0,0 +1,23 @@
|
|||
--- a/net/minecraft/commands/CommandSource.java
|
||||
+++ b/net/minecraft/commands/CommandSource.java
|
||||
@@ -26,6 +22,13 @@
|
||||
public boolean shouldInformAdmins() {
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ @Override
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) {
|
||||
+ throw new UnsupportedOperationException("Not supported yet.");
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
};
|
||||
|
||||
void sendSystemMessage(Component component);
|
||||
@@ -39,4 +42,6 @@
|
||||
default boolean alwaysAccepts() {
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); // CraftBukkit
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
--- a/net/minecraft/commands/CommandSourceStack.java
|
||||
+++ b/net/minecraft/commands/CommandSourceStack.java
|
||||
@@ -44,6 +43,7 @@
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+import com.mojang.brigadier.tree.CommandNode; // CraftBukkit
|
||||
|
||||
public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, SharedSuggestionProvider {
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
private final Vec2 rotation;
|
||||
private final CommandSigningContext signingContext;
|
||||
private final TaskChainer chatMessageChainer;
|
||||
+ public volatile CommandNode currentCommand; // CraftBukkit
|
||||
|
||||
public CommandSourceStack(CommandSource commandsource, Vec3 vec3, Vec2 vec2, ServerLevel serverlevel, int i, String s, Component component, MinecraftServer minecraftserver, @Nullable Entity entity) {
|
||||
this(commandsource, vec3, vec2, serverlevel, i, s, component, minecraftserver, entity, false, CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(minecraftserver));
|
||||
@@ -170,11 +170,24 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public boolean hasPermission(int i) {
|
||||
- return this.permissionLevel >= i;
|
||||
+ public boolean hasPermission(int level) {
|
||||
+ // CraftBukkit start
|
||||
+ CommandNode currentCommand = this.currentCommand;
|
||||
+ if (currentCommand != null) {
|
||||
+ return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ return this.permissionLevel >= level;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public boolean hasPermission(int i, String bukkitPermission) {
|
||||
+ // World is null when loading functions
|
||||
+ return ((getLevel() == null || !getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public Vec3 getPosition() {
|
||||
return this.worldPosition;
|
||||
}
|
||||
@@ -307,8 +320,8 @@
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
|
||||
- if (serverplayer != this.source && this.server.getPlayerList().isOp(serverplayer.getGameProfile())) {
|
||||
- serverplayer.sendSystemMessage(mutablecomponent);
|
||||
+ if (entityplayer != this.source && entityplayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit
|
||||
+ entityplayer.sendSystemMessage(ichatmutablecomponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,4 +413,10 @@
|
||||
public boolean isSilent() {
|
||||
return this.silent;
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender() {
|
||||
+ return source.getBukkitSender(this);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -135,6 +134,14 @@
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import com.google.common.base.Joiner;
|
||||
+import java.util.Collection;
|
||||
+import java.util.LinkedHashSet;
|
||||
+import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
+import org.bukkit.event.server.ServerCommandEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class Commands {
|
||||
|
||||
private static final ThreadLocal<ExecutionContext<CommandSourceStack>> CURRENT_EXECUTION_CONTEXT = new ThreadLocal();
|
||||
@@ -146,7 +153,8 @@
|
||||
public static final int LEVEL_OWNERS = 4;
|
||||
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher();
|
||||
|
||||
- public Commands(Commands.CommandSelection commands_commandselection, CommandBuildContext commandbuildcontext) {
|
||||
+ public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
|
||||
+ this(); // CraftBukkit
|
||||
AdvancementCommands.register(this.dispatcher);
|
||||
AttributeCommand.register(this.dispatcher, commandbuildcontext);
|
||||
ExecuteCommand.register(this.dispatcher, commandbuildcontext);
|
||||
@@ -247,6 +255,11 @@
|
||||
PublishCommand.register(this.dispatcher);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ }
|
||||
+
|
||||
+ public Commands() {
|
||||
+ // CraftBukkkit end
|
||||
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
|
||||
}
|
||||
|
||||
@@ -257,18 +270,64 @@
|
||||
return new ParseResults(commandcontextbuilder1, parseresults.getReader(), parseresults.getExceptions());
|
||||
}
|
||||
|
||||
- public void performPrefixedCommand(CommandSourceStack commandsourcestack, String s) {
|
||||
+ // CraftBukkit start
|
||||
+ public void dispatchServerCommand(CommandSourceStack sender, String command) {
|
||||
+ Joiner joiner = Joiner.on(" ");
|
||||
+ if (command.startsWith("/")) {
|
||||
+ command = command.substring(1);
|
||||
+ }
|
||||
+
|
||||
+ ServerCommandEvent event = new ServerCommandEvent(sender.getBukkitSender(), command);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ command = event.getCommand();
|
||||
+
|
||||
+ String[] args = command.split(" ");
|
||||
+
|
||||
+ String cmd = args[0];
|
||||
+ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length());
|
||||
+ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length());
|
||||
+
|
||||
+ // Block disallowed commands
|
||||
+ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op")
|
||||
+ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip")
|
||||
+ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Handle vanilla commands;
|
||||
+ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) {
|
||||
+ args[0] = "minecraft:" + args[0];
|
||||
+ }
|
||||
+
|
||||
+ String newCommand = joiner.join(args);
|
||||
+ this.performPrefixedCommand(sender, newCommand, newCommand);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s) {
|
||||
+ // CraftBukkit start
|
||||
+ this.performPrefixedCommand(commandlistenerwrapper, s, s);
|
||||
+ }
|
||||
+
|
||||
+ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s, String label) {
|
||||
s = s.startsWith("/") ? s.substring(1) : s;
|
||||
- this.performCommand(this.dispatcher.parse(s, commandsourcestack), s);
|
||||
+ this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public void performCommand(ParseResults<CommandSourceStack> parseresults, String s) {
|
||||
CommandSourceStack commandsourcestack = (CommandSourceStack) parseresults.getContext().getSource();
|
||||
|
||||
- commandsourcestack.getServer().getProfiler().push(() -> {
|
||||
+ public void performCommand(ParseResults<CommandSourceStack> parseresults, String s, String label) { // CraftBukkit
|
||||
+ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseresults.getContext().getSource();
|
||||
+
|
||||
+ commandlistenerwrapper.getServer().getProfiler().push(() -> {
|
||||
return "/" + s;
|
||||
});
|
||||
- ContextChain contextchain = finishParsing(parseresults, s, commandsourcestack);
|
||||
+ ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit
|
||||
|
||||
try {
|
||||
if (contextchain != null) {
|
||||
@@ -302,7 +362,7 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- private static ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseresults, String s, CommandSourceStack commandsourcestack) {
|
||||
+ private static ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseresults, String s, CommandSourceStack commandlistenerwrapper, String label) { // CraftBukkit
|
||||
try {
|
||||
validateParseResults(parseresults);
|
||||
return (ContextChain) ContextChain.tryFlatten(parseresults.getContext().build(s)).orElseThrow(() -> {
|
||||
@@ -312,8 +372,8 @@
|
||||
commandsourcestack.sendFailure(ComponentUtils.fromMessage(commandsyntaxexception.getRawMessage()));
|
||||
if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) {
|
||||
int i = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor());
|
||||
- MutableComponent mutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((style) -> {
|
||||
- return style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + s));
|
||||
+ MutableComponent ichatmutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((chatmodifier) -> {
|
||||
+ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, label)); // CraftBukkit
|
||||
});
|
||||
|
||||
if (i > 10) {
|
||||
@@ -371,13 +431,38 @@
|
||||
|
||||
}
|
||||
|
||||
- public void sendCommands(ServerPlayer serverplayer) {
|
||||
- Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newHashMap();
|
||||
+ public void sendCommands(ServerPlayer player) {
|
||||
+ // CraftBukkit start
|
||||
+ // Register Vanilla commands into builtRoot as before
|
||||
+ Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues
|
||||
+ RootCommandNode vanillaRoot = new RootCommandNode();
|
||||
+
|
||||
+ RootCommandNode<CommandSourceStack> vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot();
|
||||
+ map.put(vanilla, vanillaRoot);
|
||||
+ this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map);
|
||||
+
|
||||
+ // Now build the global commands in a second pass
|
||||
RootCommandNode<SharedSuggestionProvider> rootcommandnode = new RootCommandNode();
|
||||
|
||||
map.put(this.dispatcher.getRoot(), rootcommandnode);
|
||||
- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, serverplayer.createCommandSourceStack(), map);
|
||||
- serverplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode));
|
||||
+ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), map);
|
||||
+
|
||||
+ Collection<String> bukkit = new LinkedHashSet<>();
|
||||
+ for (CommandNode node : rootcommandnode.getChildren()) {
|
||||
+ bukkit.add(node.getName());
|
||||
+ }
|
||||
+
|
||||
+ PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit));
|
||||
+ event.getPlayer().getServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ // Remove labels that were removed during the event
|
||||
+ for (String orig : bukkit) {
|
||||
+ if (!event.getCommands().contains(orig)) {
|
||||
+ rootcommandnode.removeCommand(orig);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ player.connection.send(new ClientboundCommandsPacket(rootcommandnode));
|
||||
}
|
||||
|
||||
private void fillUsableCommands(CommandNode<CommandSourceStack> commandnode, CommandNode<SharedSuggestionProvider> commandnode1, CommandSourceStack commandsourcestack, Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map) {
|
|
@ -0,0 +1,23 @@
|
|||
--- a/net/minecraft/commands/arguments/EntityArgument.java
|
||||
+++ b/net/minecraft/commands/arguments/EntityArgument.java
|
||||
@@ -93,11 +93,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public EntitySelector parse(StringReader stringreader) throws CommandSyntaxException {
|
||||
+ public EntitySelector parse(StringReader reader) throws CommandSyntaxException {
|
||||
+ // CraftBukkit start
|
||||
+ return parse(reader, false);
|
||||
+ }
|
||||
+
|
||||
+ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException {
|
||||
+ // CraftBukkit end
|
||||
boolean flag = false;
|
||||
- EntitySelectorParser entityselectorparser = new EntitySelectorParser(stringreader);
|
||||
- EntitySelector entityselector = entityselectorparser.parse();
|
||||
+ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader);
|
||||
+ EntitySelector entityselector = argumentparserselector.parse(overridePermissions); // CraftBukkit
|
||||
|
||||
if (entityselector.getMaxResults() > 1 && this.single) {
|
||||
if (this.playersOnly) {
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/commands/arguments/blocks/BlockStateParser.java
|
||||
+++ b/net/minecraft/commands/arguments/blocks/BlockStateParser.java
|
||||
@@ -68,7 +68,7 @@
|
||||
private final StringReader reader;
|
||||
private final boolean forTesting;
|
||||
private final boolean allowNbt;
|
||||
- private final Map<Property<?>, Comparable<?>> properties = Maps.newHashMap();
|
||||
+ private final Map<Property<?>, Comparable<?>> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable
|
||||
private final Map<String, String> vagueProperties = Maps.newHashMap();
|
||||
private ResourceLocation id = new ResourceLocation("");
|
||||
@Nullable
|
|
@ -0,0 +1,13 @@
|
|||
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
@@ -93,8 +91,8 @@
|
||||
return this.usesSelector;
|
||||
}
|
||||
|
||||
- private void checkPermissions(CommandSourceStack commandsourcestack) throws CommandSyntaxException {
|
||||
- if (this.usesSelector && !commandsourcestack.hasPermission(2)) {
|
||||
+ private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException {
|
||||
+ if (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit
|
||||
throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
|
||||
+++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
|
||||
@@ -204,8 +204,10 @@
|
||||
};
|
||||
}
|
||||
|
||||
- protected void parseSelector() throws CommandSyntaxException {
|
||||
- this.usesSelectors = true;
|
||||
+ // CraftBukkit start
|
||||
+ protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException {
|
||||
+ this.usesSelectors = !overridePermissions;
|
||||
+ // CraftBukkit end
|
||||
this.suggestions = this::suggestSelector;
|
||||
if (!this.reader.canRead()) {
|
||||
throw EntitySelectorParser.ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader);
|
||||
@@ -463,6 +465,12 @@
|
||||
}
|
||||
|
||||
public EntitySelector parse() throws CommandSyntaxException {
|
||||
+ // CraftBukkit start
|
||||
+ return parse(false);
|
||||
+ }
|
||||
+
|
||||
+ public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException {
|
||||
+ // CraftBukkit end
|
||||
this.startPosition = this.reader.getCursor();
|
||||
this.suggestions = this::suggestNameOrSelector;
|
||||
if (this.reader.canRead() && this.reader.peek() == '@') {
|
||||
@@ -471,7 +479,7 @@
|
||||
}
|
||||
|
||||
this.reader.skip();
|
||||
- this.parseSelector();
|
||||
+ this.parseSelector(overridePermissions); // CraftBukkit
|
||||
} else {
|
||||
this.parseNameOrUUID();
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
--- a/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
+++ b/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
@@ -33,6 +33,10 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.block.CauldronLevelChangeEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public interface CauldronInteraction {
|
||||
|
||||
Map<String, CauldronInteraction.InteractionMap> INTERACTIONS = new Object2ObjectArrayMap();
|
||||
@@ -47,6 +53,8 @@
|
||||
CauldronInteraction SHULKER_BOX;
|
||||
CauldronInteraction BANNER;
|
||||
CauldronInteraction DYED_ITEM;
|
||||
+ */
|
||||
+ // CraftBukkit end
|
||||
|
||||
static CauldronInteraction.InteractionMap newInteractionMap(String s) {
|
||||
Object2ObjectOpenHashMap<Item, CauldronInteraction> object2objectopenhashmap = new Object2ObjectOpenHashMap();
|
||||
@@ -70,15 +78,20 @@
|
||||
if (PotionUtils.getPotion(itemstack) != Potions.WATER) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
- if (!level.isClientSide) {
|
||||
+ if (!world.isClientSide) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.WATER_CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Item item = itemstack.getItem();
|
||||
|
||||
- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
- player.awardStat(Stats.USE_CAULDRON);
|
||||
- player.awardStat(Stats.ITEM_USED.get(item));
|
||||
- level.setBlockAndUpdate(blockpos, Blocks.WATER_CAULDRON.defaultBlockState());
|
||||
- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos);
|
||||
+ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
+ entityhuman.awardStat(Stats.USE_CAULDRON);
|
||||
+ entityhuman.awardStat(Stats.ITEM_USED.get(item));
|
||||
+ // world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit
|
||||
+ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition);
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
@@ -92,29 +105,39 @@
|
||||
return (Integer) blockstate1.getValue(LayeredCauldronBlock.LEVEL) == 3;
|
||||
}, SoundEvents.BUCKET_FILL);
|
||||
});
|
||||
- map1.put(Items.GLASS_BOTTLE, (blockstate, level, blockpos, player, interactionhand, itemstack) -> {
|
||||
- if (!level.isClientSide) {
|
||||
+ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ if (!world.isClientSide) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Item item = itemstack.getItem();
|
||||
|
||||
- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)));
|
||||
- player.awardStat(Stats.USE_CAULDRON);
|
||||
- player.awardStat(Stats.ITEM_USED.get(item));
|
||||
- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos);
|
||||
- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos);
|
||||
+ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)));
|
||||
+ entityhuman.awardStat(Stats.USE_CAULDRON);
|
||||
+ entityhuman.awardStat(Stats.ITEM_USED.get(item));
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit
|
||||
+ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition);
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
});
|
||||
- map1.put(Items.POTION, (blockstate, level, blockpos, player, interactionhand, itemstack) -> {
|
||||
- if ((Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) {
|
||||
- if (!level.isClientSide) {
|
||||
- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
- player.awardStat(Stats.USE_CAULDRON);
|
||||
- player.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
|
||||
- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.cycle(LayeredCauldronBlock.LEVEL));
|
||||
- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos);
|
||||
+ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) {
|
||||
+ if (!world.isClientSide) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata.cycle(LayeredCauldronBlock.LEVEL), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
+ entityhuman.awardStat(Stats.USE_CAULDRON);
|
||||
+ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem()));
|
||||
+ // world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit
|
||||
+ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition);
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
@@ -188,14 +211,19 @@
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
if (!level.isClientSide) {
|
||||
- Item item = itemstack.getItem();
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.changeLevel(blockState, level, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ Item item = emptyStack.getItem();
|
||||
|
||||
player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, itemstack1));
|
||||
player.awardStat(Stats.USE_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(item));
|
||||
- level.setBlockAndUpdate(blockpos, Blocks.CAULDRON.defaultBlockState());
|
||||
- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos);
|
||||
+ // world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit
|
||||
+ level.playSound((Player) null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, pos);
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
@@ -204,14 +232,19 @@
|
||||
|
||||
static InteractionResult emptyBucket(Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, ItemStack itemstack, BlockState blockstate, SoundEvent soundevent) {
|
||||
if (!level.isClientSide) {
|
||||
- Item item = itemstack.getItem();
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.changeLevel(state, level, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ Item item = filledStack.getItem();
|
||||
|
||||
player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.BUCKET)));
|
||||
player.awardStat(Stats.FILL_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(item));
|
||||
- level.setBlockAndUpdate(blockpos, blockstate);
|
||||
- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos);
|
||||
+ // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit
|
||||
+ level.playSound((Player) null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, pos);
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
@@ -236,22 +266,28 @@
|
||||
FILL_POWDER_SNOW = (blockstate, level, blockpos, player, interactionhand, itemstack) -> {
|
||||
return emptyBucket(level, blockpos, player, interactionhand, itemstack, (BlockState) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW);
|
||||
};
|
||||
- SHULKER_BOX = (blockstate, level, blockpos, player, interactionhand, itemstack) -> {
|
||||
+ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ // CraftBukkit end
|
||||
Block block = Block.byItem(itemstack.getItem());
|
||||
|
||||
if (!(block instanceof ShulkerBoxBlock)) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
- if (!level.isClientSide) {
|
||||
+ if (!world.isClientSide) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack itemstack1 = new ItemStack(Blocks.SHULKER_BOX);
|
||||
|
||||
if (itemstack.hasTag()) {
|
||||
itemstack1.setTag(itemstack.getTag().copy());
|
||||
}
|
||||
|
||||
- player.setItemInHand(interactionhand, itemstack1);
|
||||
- player.awardStat(Stats.CLEAN_SHULKER_BOX);
|
||||
- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos);
|
||||
+ entityhuman.setItemInHand(enumhand, itemstack1);
|
||||
+ entityhuman.awardStat(Stats.CLEAN_SHULKER_BOX);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
@@ -261,7 +297,12 @@
|
||||
if (BannerBlockEntity.getPatternCount(itemstack) <= 0) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
- if (!level.isClientSide) {
|
||||
+ if (!world.isClientSide) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ItemStack itemstack1 = itemstack.copyWithCount(1);
|
||||
|
||||
BannerBlockEntity.removeLastPattern(itemstack1);
|
||||
@@ -277,8 +318,8 @@
|
||||
player.drop(itemstack1, false);
|
||||
}
|
||||
|
||||
- player.awardStat(Stats.CLEAN_BANNER);
|
||||
- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos);
|
||||
+ entityhuman.awardStat(Stats.CLEAN_BANNER);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
@@ -295,10 +336,15 @@
|
||||
if (!dyeableleatheritem.hasCustomColor(itemstack)) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
- if (!level.isClientSide) {
|
||||
- dyeableleatheritem.clearColor(itemstack);
|
||||
- player.awardStat(Stats.CLEAN_ARMOR);
|
||||
- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos);
|
||||
+ if (!world.isClientSide) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ idyeable.clearColor(itemstack);
|
||||
+ entityhuman.awardStat(Stats.CLEAN_ARMOR);
|
||||
+ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
|
@ -0,0 +1,58 @@
|
|||
--- a/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java
|
||||
@@ -7,6 +6,13 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.world.entity.Entity;
|
||||
+import net.minecraft.world.entity.projectile.Projectile;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class AbstractProjectileDispenseBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -20,9 +25,38 @@
|
||||
Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING);
|
||||
Projectile projectile = this.getProjectile(serverlevel, position, itemstack);
|
||||
|
||||
- projectile.shoot((double) direction.getStepX(), (double) ((float) direction.getStepY() + 0.1F), (double) direction.getStepZ(), this.getPower(), this.getUncertainty());
|
||||
- serverlevel.addFreshEntity(projectile);
|
||||
- itemstack.shrink(1);
|
||||
+ // CraftBukkit start
|
||||
+ // iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty());
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.getPower(), this.getUncertainty());
|
||||
+ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity());
|
||||
+ // CraftBukkit end
|
||||
+ worldserver.addFreshEntity(iprojectile);
|
||||
+ // itemstack.shrink(1); // CraftBukkit - Handled during event processing
|
||||
return itemstack;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
@@ -12,6 +12,11 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -52,13 +56,41 @@
|
||||
d4 = 0.0D;
|
||||
}
|
||||
|
||||
- Object object = this.isChestBoat ? new ChestBoat(serverlevel, d1, d2 + d4, d3) : new Boat(serverlevel, d1, d2 + d4, d3);
|
||||
+ // Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
|
||||
- EntityType.createDefaultStackConfig(serverlevel, itemstack, (Player) null).accept(object);
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Boat object = this.isChestBoat ? new ChestBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()) : new Boat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ());
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ EntityType.createDefaultStackConfig(worldserver, itemstack, (Player) null).accept(object);
|
||||
((Boat) object).setVariant(this.type);
|
||||
- ((Boat) object).setYRot(direction.toYRot());
|
||||
- serverlevel.addFreshEntity((Entity) object);
|
||||
- itemstack.shrink(1);
|
||||
+ ((Boat) object).setYRot(enumdirection.toYRot());
|
||||
+ if (!worldserver.addFreshEntity((Entity) object)) itemstack.grow(1); // CraftBukkit
|
||||
+ // itemstack.shrink(1); // CraftBukkit - handled during event processing
|
||||
return itemstack;
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
@@ -6,9 +6,23 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.util.CraftVector;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private boolean dropper;
|
||||
+
|
||||
+ public DefaultDispenseItemBehavior(boolean dropper) {
|
||||
+ this.dropper = dropper;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public DefaultDispenseItemBehavior() {}
|
||||
|
||||
@Override
|
||||
@@ -26,16 +39,27 @@
|
||||
Position position = DispenserBlock.getDispensePosition(blocksource);
|
||||
ItemStack itemstack1 = itemstack.split(1);
|
||||
|
||||
- spawnItem(blocksource.level(), itemstack1, 6, direction, position);
|
||||
+ // CraftBukkit start
|
||||
+ if (!spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, sourceblock, dropper)) {
|
||||
+ itemstack.grow(1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
- public static void spawnItem(Level level, ItemStack itemstack, int i, Direction direction, Position position) {
|
||||
- double d0 = position.x();
|
||||
- double d1 = position.y();
|
||||
- double d2 = position.z();
|
||||
+ public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, IPosition position) {
|
||||
+ // CraftBukkit start
|
||||
+ ItemEntity entityitem = prepareItem(level, stack, speed, facing, position);
|
||||
+ level.addFreshEntity(entityitem);
|
||||
+ }
|
||||
|
||||
- if (direction.getAxis() == Direction.Axis.Y) {
|
||||
+ private static ItemEntity prepareItem(Level world, ItemStack itemstack, int i, Direction enumdirection, IPosition iposition) {
|
||||
+ // CraftBukkit end
|
||||
+ double d0 = iposition.x();
|
||||
+ double d1 = iposition.y();
|
||||
+ double d2 = iposition.z();
|
||||
+
|
||||
+ if (enumdirection.getAxis() == Direction.Axis.Y) {
|
||||
d1 -= 0.125D;
|
||||
} else {
|
||||
d1 -= 0.15625D;
|
||||
@@ -44,12 +68,48 @@
|
||||
ItemEntity itementity = new ItemEntity(level, d0, d1, d2, itemstack);
|
||||
double d3 = level.random.nextDouble() * 0.1D + 0.2D;
|
||||
|
||||
- itementity.setDeltaMovement(level.random.triangle((double) direction.getStepX() * d3, 0.0172275D * (double) i), level.random.triangle(0.2D, 0.0172275D * (double) i), level.random.triangle((double) direction.getStepZ() * d3, 0.0172275D * (double) i));
|
||||
- level.addFreshEntity(itementity);
|
||||
+ entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i));
|
||||
+ // CraftBukkit start
|
||||
+ return entityitem;
|
||||
}
|
||||
|
||||
- protected void playSound(BlockSource blocksource) {
|
||||
- blocksource.level().levelEvent(1000, blocksource.pos(), 0);
|
||||
+ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper
|
||||
+ public static boolean spawnItem(Level world, ItemStack itemstack, int i, Direction enumdirection, SourceBlock sourceblock, boolean dropper) {
|
||||
+ if (itemstack.isEmpty()) return true;
|
||||
+ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock);
|
||||
+ ItemEntity entityitem = prepareItem(world, itemstack, i, enumdirection, iposition);
|
||||
+
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity()));
|
||||
+
|
||||
+ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ } else {
|
||||
+ world.addFreshEntity(entityitem);
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ world.addFreshEntity(entityitem);
|
||||
+
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
protected void playAnimation(BlockSource blocksource, Direction direction) {
|
|
@ -0,0 +1,687 @@
|
|||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -76,6 +79,17 @@
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.TreeType;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.craftbukkit.util.DummyGeneratorAccess;
|
||||
+import org.bukkit.event.block.BlockDispenseArmorEvent;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+import org.bukkit.event.block.BlockFertilizeEvent;
|
||||
+import org.bukkit.event.world.StructureGrowEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public interface DispenseItemBehavior {
|
||||
|
||||
@@ -218,6 +215,33 @@
|
||||
Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING);
|
||||
EntityType entitytype = ((SpawnEggItem) itemstack.getItem()).getType(itemstack.getTag());
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ ServerLevel worldserver = sourceblock.level();
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
try {
|
||||
entitytype.spawn(blocksource.level(), itemstack, (Player) null, blocksource.pos().relative(direction), MobSpawnType.DISPENSER, direction != Direction.UP, false);
|
||||
} catch (Exception exception) {
|
||||
@@ -225,8 +249,9 @@
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- itemstack.shrink(1);
|
||||
- blocksource.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blocksource.pos());
|
||||
+ // itemstack.shrink(1); // Handled during event processing
|
||||
+ // CraftBukkit end
|
||||
+ sourceblock.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, sourceblock.pos());
|
||||
return itemstack;
|
||||
}
|
||||
};
|
||||
@@ -250,10 +270,42 @@
|
||||
}, serverlevel, itemstack, (Player) null);
|
||||
ArmorStand armorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(serverlevel, itemstack.getTag(), consumer, blockpos, MobSpawnType.DISPENSER, false, false);
|
||||
|
||||
- if (armorstand != null) {
|
||||
- itemstack.shrink(1);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ Consumer<ArmorStand> consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> {
|
||||
+ entityarmorstand.setYRot(enumdirection.toYRot());
|
||||
+ }, worldserver, itemstack, (Player) null);
|
||||
+ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.DISPENSER, false, false);
|
||||
+
|
||||
+ if (entityarmorstand != null) {
|
||||
+ // itemstack.shrink(1); // CraftBukkit - Handled during event processing
|
||||
+ }
|
||||
+
|
||||
return itemstack;
|
||||
}
|
||||
});
|
||||
@@ -273,8 +324,35 @@
|
||||
});
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ Level world = sourceblock.level();
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS);
|
||||
- itemstack.shrink(1);
|
||||
+ // itemstack.shrink(1); // CraftBukkit - handled above
|
||||
this.setSuccess(true);
|
||||
return itemstack;
|
||||
} else {
|
||||
@@ -302,7 +379,35 @@
|
||||
abstracthorse = (AbstractHorse) iterator1.next();
|
||||
} while (!abstracthorse.isArmor(itemstack) || abstracthorse.isWearingArmor() || !abstracthorse.isTamed());
|
||||
|
||||
- abstracthorse.getSlot(401).set(itemstack.split(1));
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ Level world = sourceblock.level();
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
this.setSuccess(true);
|
||||
return itemstack;
|
||||
}
|
||||
@@ -345,25 +449,79 @@
|
||||
return super.execute(blocksource, itemstack);
|
||||
}
|
||||
|
||||
- abstractchestedhorse = (AbstractChestedHorse) iterator1.next();
|
||||
- } while (!abstractchestedhorse.isTamed() || !abstractchestedhorse.getSlot(499).set(itemstack));
|
||||
+ entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next();
|
||||
+ // CraftBukkit start
|
||||
+ } while (!entityhorsechestedabstract.isTamed());
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ Level world = sourceblock.level();
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
|
||||
- itemstack.shrink(1);
|
||||
+ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // itemstack.shrink(1); // CraftBukkit - handled above
|
||||
this.setSuccess(true);
|
||||
return itemstack;
|
||||
}
|
||||
});
|
||||
DispenserBlock.registerBehavior(Items.FIREWORK_ROCKET, new DefaultDispenseItemBehavior() {
|
||||
@Override
|
||||
- @Override
|
||||
- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) {
|
||||
- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING);
|
||||
- Vec3 vec3 = DispenseItemBehavior.getEntityPokingOutOfBlockPos(blocksource, EntityType.FIREWORK_ROCKET, direction);
|
||||
- FireworkRocketEntity fireworkrocketentity = new FireworkRocketEntity(blocksource.level(), itemstack, vec3.x(), vec3.y(), vec3.z(), true);
|
||||
+ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) {
|
||||
+ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING);
|
||||
+ // CraftBukkit start
|
||||
+ ServerLevel worldserver = sourceblock.level();
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
|
||||
- fireworkrocketentity.shoot((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ(), 0.5F, 1.0F);
|
||||
- blocksource.level().addFreshEntity(fireworkrocketentity);
|
||||
- itemstack.shrink(1);
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(sourceblock, EntityType.FIREWORK_ROCKET, enumdirection);
|
||||
+ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(sourceblock.level(), itemstack, vec3d.x(), vec3d.y(), vec3d.z(), true);
|
||||
+
|
||||
+ entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F);
|
||||
+ sourceblock.level().addFreshEntity(entityfireworks);
|
||||
+ // itemstack.shrink(1); // Handled during event processing
|
||||
+ // CraftBukkit end
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@@ -389,10 +544,39 @@
|
||||
double d5 = randomsource.triangle((double) direction.getStepZ(), 0.11485000000000001D);
|
||||
SmallFireball smallfireball = new SmallFireball(serverlevel, d0, d1, d2, d3, d4, d5);
|
||||
|
||||
- serverlevel.addFreshEntity((Entity) Util.make(smallfireball, (smallfireball1) -> {
|
||||
- smallfireball1.setItem(itemstack);
|
||||
- }));
|
||||
- itemstack.shrink(1);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ SmallFireball entitysmallfireball = new SmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ());
|
||||
+ entitysmallfireball.setItem(itemstack1);
|
||||
+ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity());
|
||||
+
|
||||
+ worldserver.addFreshEntity(entitysmallfireball);
|
||||
+ // itemstack.shrink(1); // Handled during event processing
|
||||
+ // CraftBukkit end
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@@ -430,9 +612,51 @@
|
||||
BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING));
|
||||
ServerLevel serverlevel = blocksource.level();
|
||||
|
||||
- if (dispensiblecontaineritem.emptyContents((Player) null, serverlevel, blockpos, (BlockHitResult) null)) {
|
||||
- dispensiblecontaineritem.checkExtraContent((Player) null, serverlevel, itemstack, blockpos);
|
||||
- return new ItemStack(Items.BUCKET);
|
||||
+ // CraftBukkit start
|
||||
+ int x = blockposition.getX();
|
||||
+ int y = blockposition.getY();
|
||||
+ int z = blockposition.getZ();
|
||||
+ IBlockData iblockdata = worldserver.getBlockState(blockposition);
|
||||
+ if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid((Player) null, worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) {
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) {
|
||||
+ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, itemstack, blockposition);
|
||||
+ // CraftBukkit start - Handle stacked buckets
|
||||
+ Item item = Items.BUCKET;
|
||||
+ itemstack.shrink(1);
|
||||
+ if (itemstack.isEmpty()) {
|
||||
+ itemstack.setItem(Items.BUCKET);
|
||||
+ itemstack.setCount(1);
|
||||
+ } else if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) {
|
||||
+ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item));
|
||||
+ }
|
||||
+ return itemstack;
|
||||
+ // CraftBukkit end
|
||||
} else {
|
||||
return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack);
|
||||
}
|
||||
@@ -460,8 +683,8 @@
|
||||
Block block = blockstate.getBlock();
|
||||
|
||||
if (block instanceof BucketPickup) {
|
||||
- BucketPickup bucketpickup = (BucketPickup) block;
|
||||
- ItemStack itemstack1 = bucketpickup.pickupBlock((Player) null, serverlevel, blockpos, blockstate);
|
||||
+ BucketPickup ifluidsource = (BucketPickup) block;
|
||||
+ ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit
|
||||
|
||||
if (itemstack1.isEmpty()) {
|
||||
return super.execute(blocksource, itemstack);
|
||||
@@ -469,6 +692,32 @@
|
||||
serverlevel.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos);
|
||||
Item item = itemstack1.getItem();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata); // From above
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
itemstack.shrink(1);
|
||||
if (itemstack.isEmpty()) {
|
||||
return new ItemStack(item);
|
||||
@@ -491,18 +739,46 @@
|
||||
protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) {
|
||||
ServerLevel serverlevel = blocksource.level();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
this.setSuccess(true);
|
||||
Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockpos = blocksource.pos().relative(direction);
|
||||
BlockState blockstate = serverlevel.getBlockState(blockpos);
|
||||
|
||||
- if (BaseFireBlock.canBePlacedAt(serverlevel, blockpos, direction)) {
|
||||
- serverlevel.setBlockAndUpdate(blockpos, BaseFireBlock.getState(serverlevel, blockpos));
|
||||
- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos);
|
||||
- } else if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) {
|
||||
- if (blockstate.getBlock() instanceof TntBlock) {
|
||||
- TntBlock.explode(serverlevel, blockpos);
|
||||
- serverlevel.removeBlock(blockpos, false);
|
||||
+ if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) {
|
||||
+ // CraftBukkit start - Ignition by dispensing flint and steel
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, sourceblock.pos()).isCancelled()) {
|
||||
+ worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition));
|
||||
+ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ } else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) {
|
||||
+ if (iblockdata.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, sourceblock.pos())) { // CraftBukkit - TNTPrimeEvent
|
||||
+ TntBlock.explode(worldserver, blockposition);
|
||||
+ worldserver.removeBlock(blockposition, false);
|
||||
} else {
|
||||
this.setSuccess(false);
|
||||
}
|
||||
@@ -523,30 +798,108 @@
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) {
|
||||
this.setSuccess(true);
|
||||
- ServerLevel serverlevel = blocksource.level();
|
||||
- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING));
|
||||
+ ServerLevel worldserver = sourceblock.level();
|
||||
+ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING));
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
|
||||
- if (!BoneMealItem.growCrop(itemstack, serverlevel, blockpos) && !BoneMealItem.growWaterPlant(itemstack, serverlevel, blockpos, (Direction) null)) {
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ worldserver.captureTreeGeneration = true;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (!BoneMealItem.growCrop(itemstack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(itemstack, worldserver, blockposition, (Direction) null)) {
|
||||
this.setSuccess(false);
|
||||
} else if (!serverlevel.isClientSide) {
|
||||
serverlevel.levelEvent(1505, blockpos, 0);
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ worldserver.captureTreeGeneration = false;
|
||||
+ if (worldserver.capturedBlockStates.size() > 0) {
|
||||
+ TreeType treeType = SaplingBlock.treeType;
|
||||
+ SaplingBlock.treeType = null;
|
||||
+ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld());
|
||||
+ List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values());
|
||||
+ worldserver.capturedBlockStates.clear();
|
||||
+ StructureGrowEvent structureEvent = null;
|
||||
+ if (treeType != null) {
|
||||
+ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
|
||||
+ }
|
||||
|
||||
+ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks);
|
||||
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
|
||||
+
|
||||
+ if (!fertilizeEvent.isCancelled()) {
|
||||
+ for (org.bukkit.block.BlockState blockstate : blocks) {
|
||||
+ blockstate.update(true);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
return itemstack;
|
||||
}
|
||||
});
|
||||
DispenserBlock.registerBehavior(Blocks.TNT, new DefaultDispenseItemBehavior() {
|
||||
@Override
|
||||
- @Override
|
||||
- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) {
|
||||
- ServerLevel serverlevel = blocksource.level();
|
||||
- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING));
|
||||
- PrimedTnt primedtnt = new PrimedTnt(serverlevel, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, (LivingEntity) null);
|
||||
+ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) {
|
||||
+ ServerLevel worldserver = sourceblock.level();
|
||||
+ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING));
|
||||
+ // CraftBukkit start
|
||||
+ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null);
|
||||
|
||||
- serverlevel.addFreshEntity(primedtnt);
|
||||
- serverlevel.playSound((Player) null, primedtnt.getX(), primedtnt.getY(), primedtnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- serverlevel.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockpos);
|
||||
- itemstack.shrink(1);
|
||||
+ ItemStack itemstack1 = itemstack.split(1);
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ itemstack.grow(1);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ itemstack.grow(1);
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null);
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ worldserver.addFreshEntity(entitytntprimed);
|
||||
+ worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition);
|
||||
+ // itemstack.shrink(1); // CraftBukkit - handled above
|
||||
return itemstack;
|
||||
}
|
||||
});
|
||||
@@ -573,14 +924,15 @@
|
||||
Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockpos = blocksource.pos().relative(direction);
|
||||
|
||||
- if (serverlevel.isEmptyBlock(blockpos) && WitherSkullBlock.canSpawnMob(serverlevel, blockpos, itemstack)) {
|
||||
- serverlevel.setBlock(blockpos, (BlockState) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(direction)), 3);
|
||||
- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos);
|
||||
- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
|
||||
if (blockentity instanceof SkullBlockEntity) {
|
||||
WitherSkullBlock.checkSpawn(serverlevel, blockpos, (SkullBlockEntity) blockentity);
|
||||
}
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
itemstack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
@@ -599,11 +973,29 @@
|
||||
BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING));
|
||||
CarvedPumpkinBlock carvedpumpkinblock = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN;
|
||||
|
||||
- if (serverlevel.isEmptyBlock(blockpos) && carvedpumpkinblock.canSpawnGolem(serverlevel, blockpos)) {
|
||||
- if (!serverlevel.isClientSide) {
|
||||
- serverlevel.setBlock(blockpos, carvedpumpkinblock.defaultBlockState(), 3);
|
||||
- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
}
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
itemstack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
@@ -649,10 +1046,34 @@
|
||||
BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING));
|
||||
BlockState blockstate = serverlevel.getBlockState(blockpos);
|
||||
|
||||
- if (blockstate.is(BlockTags.BEEHIVES, (blockbehaviour_blockstatebase) -> {
|
||||
- return blockbehaviour_blockstatebase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbehaviour_blockstatebase.getBlock() instanceof BeehiveBlock;
|
||||
- }) && (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) {
|
||||
- ((BeehiveBlock) blockstate.getBlock()).releaseBeesAndResetHoneyLevel(serverlevel, blockstate, blockpos, (Player) null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> {
|
||||
+ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock;
|
||||
+ }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) {
|
||||
+ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(worldserver, iblockdata, blockposition, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED);
|
||||
this.setSuccess(true);
|
||||
return this.takeLiquid(blocksource, itemstack, new ItemStack(Items.HONEY_BOTTLE));
|
||||
} else if (serverlevel.getFluidState(blockpos).is(FluidTags.WATER)) {
|
|
@ -0,0 +1,84 @@
|
|||
--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
@@ -21,21 +21,47 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
|
||||
|
||||
public ShearsDispenseItemBehavior() {}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) {
|
||||
- ServerLevel serverlevel = blocksource.level();
|
||||
+ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) {
|
||||
+ ServerLevel worldserver = sourceblock.level();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
|
||||
if (!serverlevel.isClientSide()) {
|
||||
BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING));
|
||||
|
||||
- this.setSuccess(tryShearBeehive(serverlevel, blockpos) || tryShearLivingEntity(serverlevel, blockpos));
|
||||
- if (this.isSuccess() && itemstack.hurt(1, serverlevel.getRandom(), (ServerPlayer) null)) {
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (!worldserver.isClientSide()) {
|
||||
+ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING));
|
||||
+
|
||||
+ this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition, bukkitBlock, craftItem)); // CraftBukkit
|
||||
+ if (this.isSuccess() && itemstack.hurt(1, worldserver.getRandom(), (ServerPlayer) null)) {
|
||||
itemstack.setCount(0);
|
||||
}
|
||||
}
|
||||
@@ -63,8 +91,8 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
- private static boolean tryShearLivingEntity(ServerLevel serverlevel, BlockPos blockpos) {
|
||||
- List<LivingEntity> list = serverlevel.getEntitiesOfClass(LivingEntity.class, new AABB(blockpos), EntitySelector.NO_SPECTATORS);
|
||||
+ private static boolean tryShearLivingEntity(ServerLevel worldserver, BlockPos blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args
|
||||
+ List<LivingEntity> list = worldserver.getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS);
|
||||
Iterator iterator = list.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -73,9 +101,14 @@
|
||||
if (livingentity instanceof Shearable) {
|
||||
Shearable shearable = (Shearable) livingentity;
|
||||
|
||||
- if (shearable.readyForShearing()) {
|
||||
- shearable.shear(SoundSource.BLOCKS);
|
||||
- serverlevel.gameEvent((Entity) null, GameEvent.SHEAR, blockpos);
|
||||
+ if (ishearable.readyForShearing()) {
|
||||
+ // CraftBukkit start
|
||||
+ if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ ishearable.shear(SoundSource.BLOCKS);
|
||||
+ worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
@@ -10,6 +10,12 @@
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -27,6 +32,30 @@
|
||||
BlockPos blockpos = blocksource.pos().relative(direction);
|
||||
Direction direction1 = blocksource.level().isEmptyBlock(blockpos.below()) ? direction : Direction.UP;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(sourceblock.level(), sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ sourceblock.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ return itemstack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
try {
|
||||
this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(blocksource.level(), blockpos, direction, itemstack, direction1)).consumesAction());
|
||||
} catch (Exception exception) {
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -105,6 +105,7 @@
|
||||
private volatile Component delayedDisconnect;
|
||||
@Nullable
|
||||
BandwidthDebugMonitor bandwidthDebugMonitor;
|
||||
+ public String hostname = ""; // CraftBukkit - add field
|
||||
|
||||
public Connection(PacketFlow packetflow) {
|
||||
this.receiving = packetflow;
|
|
@ -0,0 +1,43 @@
|
|||
--- a/net/minecraft/network/FriendlyByteBuf.java
|
||||
+++ b/net/minecraft/network/FriendlyByteBuf.java
|
||||
@@ -81,6 +81,8 @@
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit
|
||||
+
|
||||
public class FriendlyByteBuf extends ByteBuf {
|
||||
|
||||
public static final int DEFAULT_NBT_QUOTA = 2097152;
|
||||
@@ -584,7 +586,7 @@
|
||||
try {
|
||||
NbtIo.writeAnyTag((Tag) tag, new ByteBufOutputStream(this));
|
||||
return this;
|
||||
- } catch (IOException ioexception) {
|
||||
+ } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception
|
||||
throw new EncoderException(ioexception);
|
||||
}
|
||||
}
|
||||
@@ -611,8 +613,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public FriendlyByteBuf writeItem(ItemStack itemstack) {
|
||||
- if (itemstack.isEmpty()) {
|
||||
+ public FriendlyByteBuf writeItem(ItemStack stack) {
|
||||
+ if (stack.isEmpty() || stack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
|
||||
this.writeBoolean(false);
|
||||
} else {
|
||||
this.writeBoolean(true);
|
||||
@@ -641,6 +643,11 @@
|
||||
ItemStack itemstack = new ItemStack(item, b0);
|
||||
|
||||
itemstack.setTag(this.readNbt());
|
||||
+ // CraftBukkit start
|
||||
+ if (itemstack.getTag() != null) {
|
||||
+ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return itemstack;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
--- a/net/minecraft/network/chat/Component.java
|
||||
+++ b/net/minecraft/network/chat/Component.java
|
||||
@@ -34,9 +34,23 @@
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
+// CraftBukkit start
|
||||
+import java.util.stream.Stream;
|
||||
+// CraftBukkit end
|
||||
|
||||
-public interface Component extends Message, FormattedText {
|
||||
+public interface Component extends Message, FormattedText, Iterable<Component> { // CraftBukkit
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ default Stream<Component> stream() {
|
||||
+ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)});
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ default Iterator<Component> iterator() {
|
||||
+ return this.stream().iterator();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
Style getStyle();
|
||||
|
||||
ComponentContents getContents();
|
|
@ -0,0 +1,32 @@
|
|||
--- a/net/minecraft/network/chat/TextColor.java
|
||||
+++ b/net/minecraft/network/chat/TextColor.java
|
||||
@@ -16,15 +16,18 @@
|
||||
|
||||
private static final String CUSTOM_COLOR_PREFIX = "#";
|
||||
public static final Codec<TextColor> CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize);
|
||||
- private static final Map<ChatFormatting, TextColor> LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (chatformatting) -> {
|
||||
- return new TextColor(chatformatting.getColor(), chatformatting.getName());
|
||||
+ private static final Map<ChatFormatting, TextColor> LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> {
|
||||
+ return new TextColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit
|
||||
}));
|
||||
private static final Map<String, TextColor> NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((textcolor) -> {
|
||||
return textcolor.name;
|
||||
}, Function.identity()));
|
||||
private final int value;
|
||||
@Nullable
|
||||
- private final String name;
|
||||
+ public final String name;
|
||||
+ // CraftBukkit start
|
||||
+ @Nullable
|
||||
+ public final ChatFormatting format;
|
||||
|
||||
private TextColor(int i, String s) {
|
||||
this.value = i & 16777215;
|
||||
@@ -35,6 +40,7 @@
|
||||
this.value = i & 16777215;
|
||||
this.name = null;
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
|
@ -0,0 +1,47 @@
|
|||
--- a/net/minecraft/network/protocol/PacketUtils.java
|
||||
+++ b/net/minecraft/network/protocol/PacketUtils.java
|
||||
@@ -4,8 +4,14 @@
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.network.PacketListener;
|
||||
-import net.minecraft.server.RunningOnDifferentThreadException;
|
||||
+import net.minecraft.server.CancelledPacketHandleException;
|
||||
+import org.slf4j.Logger;
|
||||
+
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.network.ServerCommonPacketListenerImpl;
|
||||
+// CraftBukkit end
|
||||
import net.minecraft.util.thread.BlockableEventLoop;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -19,10 +24,11 @@
|
||||
ensureRunningOnSameThread(packet, t0, (BlockableEventLoop) serverlevel.getServer());
|
||||
}
|
||||
|
||||
- public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T t0, BlockableEventLoop<?> blockableeventloop) throws RunningOnDifferentThreadException {
|
||||
- if (!blockableeventloop.isSameThread()) {
|
||||
- blockableeventloop.executeIfPossible(() -> {
|
||||
- if (t0.shouldHandleMessage(packet)) {
|
||||
+ public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T processor, BlockableEventLoop<?> executor) throws CancelledPacketHandleException {
|
||||
+ if (!executor.isSameThread()) {
|
||||
+ executor.executeIfPossible(() -> {
|
||||
+ if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) return; // CraftBukkit, MC-142590
|
||||
+ if (processor.shouldHandleMessage(packet)) {
|
||||
try {
|
||||
packet.handle(t0);
|
||||
} catch (Exception exception) {
|
||||
@@ -59,7 +65,11 @@
|
||||
}
|
||||
|
||||
});
|
||||
- throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD;
|
||||
+ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD;
|
||||
+ // CraftBukkit start - SPIGOT-5477, MC-142590
|
||||
+ } else if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) {
|
||||
+ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
--- a/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
||||
+++ b/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
||||
@@ -12,7 +12,7 @@
|
||||
public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implements Packet<ServerCommonPacketListener> {
|
||||
|
||||
private static final int MAX_PAYLOAD_SIZE = 32767;
|
||||
- private static final Map<ResourceLocation, FriendlyByteBuf.Reader<? extends CustomPacketPayload>> KNOWN_TYPES = ImmutableMap.builder().put(BrandPayload.ID, BrandPayload::new).build();
|
||||
+ private static final Map<ResourceLocation, FriendlyByteBuf.a<? extends CustomPacketPayload>> KNOWN_TYPES = ImmutableMap.<ResourceLocation, FriendlyByteBuf.a<? extends CustomPacketPayload>>builder().build(); // CraftBukkit - no special handling
|
||||
|
||||
public ServerboundCustomPayloadPacket(FriendlyByteBuf friendlybytebuf) {
|
||||
this(readPayload(friendlybytebuf.readResourceLocation(), friendlybytebuf));
|
||||
@@ -24,12 +24,13 @@
|
||||
return (CustomPacketPayload) (friendlybytebuf_reader != null ? (CustomPacketPayload) friendlybytebuf_reader.apply(friendlybytebuf) : readUnknownPayload(resourcelocation, friendlybytebuf));
|
||||
}
|
||||
|
||||
- private static DiscardedPayload readUnknownPayload(ResourceLocation resourcelocation, FriendlyByteBuf friendlybytebuf) {
|
||||
- int i = friendlybytebuf.readableBytes();
|
||||
+ private static UnknownPayload readUnknownPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { // CraftBukkit
|
||||
+ int i = packetdataserializer.readableBytes();
|
||||
|
||||
if (i >= 0 && i <= 32767) {
|
||||
- friendlybytebuf.skipBytes(i);
|
||||
- return new DiscardedPayload(resourcelocation);
|
||||
+ // CraftBukkit start
|
||||
+ return new UnknownPayload(minecraftkey, packetdataserializer.readBytes(i));
|
||||
+ // CraftBukkit end
|
||||
} else {
|
||||
throw new IllegalArgumentException("Payload may not be larger than 32767 bytes");
|
||||
}
|
||||
@@ -46,4 +45,14 @@
|
||||
public void handle(ServerCommonPacketListener servercommonpacketlistener) {
|
||||
servercommonpacketlistener.handleCustomPayload(this);
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public record UnknownPayload(ResourceLocation id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload {
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(FriendlyByteBuf packetdataserializer) {
|
||||
+ packetdataserializer.writeBytes(data);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
--- a/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java
|
||||
@@ -26,15 +26,17 @@
|
||||
this.warningTime = friendlybytebuf.readVarInt();
|
||||
}
|
||||
|
||||
- public ClientboundInitializeBorderPacket(WorldBorder worldborder) {
|
||||
- this.newCenterX = worldborder.getCenterX();
|
||||
- this.newCenterZ = worldborder.getCenterZ();
|
||||
- this.oldSize = worldborder.getSize();
|
||||
- this.newSize = worldborder.getLerpTarget();
|
||||
- this.lerpTime = worldborder.getLerpRemainingTime();
|
||||
- this.newAbsoluteMaxSize = worldborder.getAbsoluteMaxSize();
|
||||
- this.warningBlocks = worldborder.getWarningBlocks();
|
||||
- this.warningTime = worldborder.getWarningTime();
|
||||
+ public ClientboundInitializeBorderPacket(WorldBorder worldBorder) {
|
||||
+ // CraftBukkit start - multiply out nether border
|
||||
+ this.newCenterX = worldBorder.getCenterX() * worldBorder.world.dimensionType().coordinateScale();
|
||||
+ this.newCenterZ = worldBorder.getCenterZ() * worldBorder.world.dimensionType().coordinateScale();
|
||||
+ // CraftBukkit end
|
||||
+ this.oldSize = worldBorder.getSize();
|
||||
+ this.newSize = worldBorder.getLerpTarget();
|
||||
+ this.lerpTime = worldBorder.getLerpRemainingTime();
|
||||
+ this.newAbsoluteMaxSize = worldBorder.getAbsoluteMaxSize();
|
||||
+ this.warningBlocks = worldBorder.getWarningBlocks();
|
||||
+ this.warningTime = worldBorder.getWarningTime();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,25 @@
|
|||
--- a/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
|
||||
@@ -30,14 +30,18 @@
|
||||
short short0 = (Short) shortiterator.next();
|
||||
|
||||
this.positions[j] = short0;
|
||||
- this.states[j] = levelchunksection.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0));
|
||||
+ this.states[j] = (section != null) ? section.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- public ClientboundSectionBlocksUpdatePacket(FriendlyByteBuf friendlybytebuf) {
|
||||
- this.sectionPos = SectionPos.of(friendlybytebuf.readLong());
|
||||
- int i = friendlybytebuf.readVarInt();
|
||||
+ // CraftBukkit start - Add constructor
|
||||
+ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionposition, ShortSet shortset, IBlockData[] states) {
|
||||
+ this.sectionPos = sectionposition;
|
||||
+ this.positions = shortset.toShortArray();
|
||||
+ this.states = states;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
this.positions = new short[i];
|
||||
this.states = new BlockState[i];
|
|
@ -0,0 +1,17 @@
|
|||
--- a/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java
|
||||
@@ -9,9 +9,11 @@
|
||||
private final double newCenterX;
|
||||
private final double newCenterZ;
|
||||
|
||||
- public ClientboundSetBorderCenterPacket(WorldBorder worldborder) {
|
||||
- this.newCenterX = worldborder.getCenterX();
|
||||
- this.newCenterZ = worldborder.getCenterZ();
|
||||
+ public ClientboundSetBorderCenterPacket(WorldBorder worldBorder) {
|
||||
+ // CraftBukkit start - multiply out nether border
|
||||
+ this.newCenterX = worldBorder.getCenterX() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0);
|
||||
+ this.newCenterZ = worldBorder.getCenterZ() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public ClientboundSetBorderCenterPacket(FriendlyByteBuf friendlybytebuf) {
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
--- a/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
+++ b/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
@@ -146,6 +148,13 @@
|
||||
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - add method from above
|
||||
+ public <T> void markDirty(EntityDataAccessor<T> datawatcherobject) {
|
||||
+ this.getItem(datawatcherobject).setDirty(true);
|
||||
+ this.isDirty = true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public boolean isDirty() {
|
||||
return this.isDirty;
|
||||
}
|
||||
@@ -235,6 +244,18 @@
|
||||
return this.itemsById.isEmpty();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void refresh(ServerPlayer to) {
|
||||
+ if (!this.isEmpty()) {
|
||||
+ List<SynchedEntityData.DataValue<?>> list = this.getNonDefaultValues();
|
||||
+
|
||||
+ if (list != null) {
|
||||
+ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public static class DataItem<T> {
|
||||
|
||||
final EntityDataAccessor<T> accessor;
|
|
@ -0,0 +1,96 @@
|
|||
--- a/net/minecraft/server/Bootstrap.java
|
||||
+++ b/net/minecraft/server/Bootstrap.java
|
||||
@@ -41,6 +44,23 @@
|
||||
|
||||
public static void bootStrap() {
|
||||
if (!Bootstrap.isBootstrapped) {
|
||||
+ // CraftBukkit start
|
||||
+ String name = Bootstrap.class.getSimpleName();
|
||||
+ switch (name) {
|
||||
+ case "DispenserRegistry":
|
||||
+ break;
|
||||
+ case "Bootstrap":
|
||||
+ System.err.println("***************************************************************************");
|
||||
+ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***");
|
||||
+ System.err.println("***************************************************************************");
|
||||
+ break;
|
||||
+ default:
|
||||
+ System.err.println("**********************************************************************");
|
||||
+ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***");
|
||||
+ System.err.println("**********************************************************************");
|
||||
+ break;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Bootstrap.isBootstrapped = true;
|
||||
Instant instant = Instant.now();
|
||||
|
||||
@@ -61,6 +81,69 @@
|
||||
wrapStreams();
|
||||
Bootstrap.bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis());
|
||||
}
|
||||
+ // CraftBukkit start - easier than fixing the decompile
|
||||
+ BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}");
|
||||
+ BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}");
|
||||
+ BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}");
|
||||
+ BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}");
|
||||
+ BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}");
|
||||
+ BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}");
|
||||
+ BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}");
|
||||
+ BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}");
|
||||
+ BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}");
|
||||
+ BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}");
|
||||
+ BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}");
|
||||
+ BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}");
|
||||
+ BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}");
|
||||
+ BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}");
|
||||
+ BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}");
|
||||
+ BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}");
|
||||
+ ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign");
|
||||
+
|
||||
+ BlockStateData.register(1440, "{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}", new String[]{"{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}"});
|
||||
+
|
||||
+ ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard");
|
||||
+ ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals");
|
||||
+ ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit");
|
||||
+ ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit");
|
||||
+ ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew");
|
||||
+ ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot");
|
||||
+ ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide");
|
||||
+ ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand");
|
||||
+
|
||||
+ ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton");
|
||||
+ ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton");
|
||||
+ ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner");
|
||||
+ ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal");
|
||||
+ ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door");
|
||||
+ ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door");
|
||||
+ ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door");
|
||||
+ ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door");
|
||||
+ ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door");
|
||||
+ ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit");
|
||||
+ ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped");
|
||||
+ ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot");
|
||||
+ ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds");
|
||||
+ ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup");
|
||||
+ ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath");
|
||||
+ ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion");
|
||||
+ ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow");
|
||||
+ ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow");
|
||||
+ ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion");
|
||||
+ ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield");
|
||||
+ ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra");
|
||||
+ ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat");
|
||||
+ ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat");
|
||||
+ ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat");
|
||||
+ ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat");
|
||||
+ ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat");
|
||||
+ ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying");
|
||||
+ ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell");
|
||||
+ ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget");
|
||||
+ ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book");
|
||||
+
|
||||
+ ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow";
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
--- a/net/minecraft/server/Main.java
|
||||
+++ b/net/minecraft/server/Main.java
|
||||
@@ -60,6 +60,14 @@
|
||||
import net.minecraft.world.level.storage.WorldData;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import com.google.common.base.Charsets;
|
||||
+import java.io.InputStreamReader;
|
||||
+import java.util.concurrent.atomic.AtomicReference;
|
||||
+import net.minecraft.SharedConstants;
|
||||
+import org.bukkit.configuration.file.YamlConfiguration;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class Main {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -67,8 +75,9 @@
|
||||
public Main() {}
|
||||
|
||||
@DontObfuscate
|
||||
- public static void main(String[] astring) {
|
||||
+ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring)
|
||||
SharedConstants.tryDetectVersion();
|
||||
+ /* CraftBukkit start - Replace everything
|
||||
OptionParser optionparser = new OptionParser();
|
||||
OptionSpec<Void> optionspec = optionparser.accepts("nogui");
|
||||
OptionSpec<Void> optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits");
|
||||
@@ -93,15 +102,18 @@
|
||||
optionparser.printHelpOn(System.err);
|
||||
return;
|
||||
}
|
||||
+ */ // CraftBukkit end
|
||||
|
||||
Path path = (Path) optionset.valueOf(optionspec13);
|
||||
|
||||
+ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit
|
||||
+
|
||||
if (path != null) {
|
||||
writePidFile(path);
|
||||
}
|
||||
|
||||
CrashReport.preload();
|
||||
- if (optionset.has(optionspec12)) {
|
||||
+ if (optionset.has("jfrProfile")) { // CraftBukkit
|
||||
JvmProfiler.INSTANCE.start(Environment.SERVER);
|
||||
}
|
||||
|
||||
@@ -109,13 +121,26 @@
|
||||
Bootstrap.validate();
|
||||
Util.startTimerHackThread();
|
||||
Path path1 = Paths.get("server.properties");
|
||||
- DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path1);
|
||||
+ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support
|
||||
|
||||
dedicatedserversettings.forceSave();
|
||||
Path path2 = Paths.get("eula.txt");
|
||||
Eula eula = new Eula(path2);
|
||||
|
||||
- if (optionset.has(optionspec1)) {
|
||||
+ if (optionset.has("initSettings")) { // CraftBukkit
|
||||
+ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present
|
||||
+ File configFile = (File) optionset.valueOf("bukkit-settings");
|
||||
+ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||
+ configuration.options().copyDefaults(true);
|
||||
+ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8)));
|
||||
+ configuration.save(configFile);
|
||||
+
|
||||
+ File commandFile = (File) optionset.valueOf("commands-settings");
|
||||
+ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile);
|
||||
+ commandsConfiguration.options().copyDefaults(true);
|
||||
+ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8)));
|
||||
+ commandsConfiguration.save(commandFile);
|
||||
+ // CraftBukkit end
|
||||
Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath());
|
||||
return;
|
||||
}
|
||||
@@ -125,11 +150,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
- File file = new File((String) optionset.valueOf(optionspec8));
|
||||
+ File file = (File) optionset.valueOf("universe"); // CraftBukkit
|
||||
Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file);
|
||||
- String s = (String) Optional.ofNullable((String) optionset.valueOf(optionspec9)).orElse(dedicatedserversettings.getProperties().levelName);
|
||||
- LevelStorageSource levelstoragesource = LevelStorageSource.createDefault(file.toPath());
|
||||
- LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess = levelstoragesource.validateAndCreateAccess(s);
|
||||
+ // CraftBukkit start
|
||||
+ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName);
|
||||
+ LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath());
|
||||
+ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD);
|
||||
+ // CraftBukkit end
|
||||
Dynamic dynamic;
|
||||
|
||||
if (levelstoragesource_levelstorageaccess.hasWorldData()) {
|
||||
@@ -170,13 +197,31 @@
|
||||
}
|
||||
|
||||
Dynamic<?> dynamic1 = dynamic;
|
||||
- boolean flag = optionset.has(optionspec6);
|
||||
+ boolean flag = optionset.has("safeMode"); // CraftBukkit
|
||||
|
||||
if (flag) {
|
||||
Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded");
|
||||
}
|
||||
|
||||
- PackRepository packrepository = ServerPacksSource.createPackRepository(levelstoragesource_levelstorageaccess);
|
||||
+ PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession);
|
||||
+ // CraftBukkit start
|
||||
+ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit");
|
||||
+ if (!bukkitDataPackFolder.exists()) {
|
||||
+ bukkitDataPackFolder.mkdirs();
|
||||
+ }
|
||||
+ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta");
|
||||
+ try {
|
||||
+ com.google.common.io.Files.write("{\n"
|
||||
+ + " \"pack\": {\n"
|
||||
+ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n"
|
||||
+ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n"
|
||||
+ + " }\n"
|
||||
+ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8);
|
||||
+ } catch (java.io.IOException ex) {
|
||||
+ throw new RuntimeException("Could not initialize Bukkit datapack", ex);
|
||||
+ }
|
||||
+ AtomicReference<WorldLoader.a> worldLoader = new AtomicReference<>();
|
||||
+ // CraftBukkit end
|
||||
|
||||
WorldStem worldstem;
|
||||
|
||||
@@ -184,8 +229,9 @@
|
||||
WorldLoader.InitConfig worldloader_initconfig = loadOrCreateConfig(dedicatedserversettings.getProperties(), dynamic1, flag, packrepository);
|
||||
|
||||
worldstem = (WorldStem) Util.blockUntilDone((executor) -> {
|
||||
- return WorldLoader.load(worldloader_initconfig, (worldloader_dataloadcontext) -> {
|
||||
- Registry<LevelStem> registry = worldloader_dataloadcontext.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
|
||||
+ return WorldLoader.load(worldloader_c, (worldloader_a) -> {
|
||||
+ worldLoader.set(worldloader_a); // CraftBukkit
|
||||
+ Registry<LevelStem> iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
if (dynamic1 != null) {
|
||||
LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic1, worldloader_dataloadcontext.dataConfiguration(), registry, worldloader_dataloadcontext.datapackWorldgen());
|
||||
@@ -197,16 +243,16 @@
|
||||
WorldOptions worldoptions;
|
||||
WorldDimensions worlddimensions;
|
||||
|
||||
- if (optionset.has(optionspec2)) {
|
||||
- levelsettings = MinecraftServer.DEMO_SETTINGS;
|
||||
+ if (optionset.has("demo")) { // CraftBukkit
|
||||
+ worldsettings = MinecraftServer.DEMO_SETTINGS;
|
||||
worldoptions = WorldOptions.DEMO_OPTIONS;
|
||||
worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_dataloadcontext.datapackWorldgen());
|
||||
} else {
|
||||
DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties();
|
||||
|
||||
- levelsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_dataloadcontext.dataConfiguration());
|
||||
- worldoptions = optionset.has(optionspec3) ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions;
|
||||
- worlddimensions = dedicatedserverproperties.createDimensions(worldloader_dataloadcontext.datapackWorldgen());
|
||||
+ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration());
|
||||
+ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit
|
||||
+ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen());
|
||||
}
|
||||
|
||||
WorldDimensions.Complete worlddimensions_complete = worlddimensions.bake(registry);
|
||||
@@ -246,6 +303,7 @@
|
||||
|
||||
return dedicatedserver1;
|
||||
});
|
||||
+ /* CraftBukkit start
|
||||
Thread thread = new Thread("Server Shutdown Thread") {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -255,6 +312,7 @@
|
||||
|
||||
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER));
|
||||
Runtime.getRuntime().addShutdownHook(thread);
|
||||
+ */ // CraftBukkit end
|
||||
} catch (Exception exception1) {
|
||||
Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1);
|
||||
}
|
||||
@@ -290,10 +348,10 @@
|
||||
return new WorldLoader.InitConfig(worldloader_packconfig, Commands.CommandSelection.DEDICATED, dedicatedserverproperties.functionPermissionLevel);
|
||||
}
|
||||
|
||||
- private static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, Registry<LevelStem> registry) {
|
||||
- Main.LOGGER.info("Forcing world upgrade!");
|
||||
- WorldUpgrader worldupgrader = new WorldUpgrader(levelstoragesource_levelstorageaccess, datafixer, registry, flag);
|
||||
- Component component = null;
|
||||
+ public static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, boolean eraseCache, BooleanSupplier upgradeWorld, Registry<LevelStem> dimesions) {
|
||||
+ Main.LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit
|
||||
+ WorldUpgrader worldupgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache);
|
||||
+ Component ichatbasecomponent = null;
|
||||
|
||||
while (!worldupgrader.isFinished()) {
|
||||
Component component1 = worldupgrader.getStatus();
|
|
@ -0,0 +1,682 @@
|
|||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -151,6 +150,23 @@
|
||||
import net.minecraft.world.level.levelgen.WorldOptions;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
+import net.minecraft.world.level.storage.WorldData;
|
||||
+import net.minecraft.world.level.storage.loot.LootDataManager;
|
||||
+import org.slf4j.Logger;
|
||||
+
|
||||
+// CraftBukkit start
|
||||
+import com.mojang.serialization.Dynamic;
|
||||
+import com.mojang.serialization.Lifecycle;
|
||||
+import java.util.Random;
|
||||
+import jline.console.ConsoleReader;
|
||||
+import joptsimple.OptionSet;
|
||||
+import net.minecraft.nbt.NbtException;
|
||||
+import net.minecraft.nbt.ReportedNbtException;
|
||||
+import net.minecraft.server.bossevents.CustomBossEvents;
|
||||
+import net.minecraft.server.dedicated.DedicatedServer;
|
||||
+import net.minecraft.server.dedicated.DedicatedServerProperties;
|
||||
+import net.minecraft.world.level.levelgen.WorldDimensions;
|
||||
+import net.minecraft.world.level.levelgen.presets.WorldPresets;
|
||||
import net.minecraft.world.level.storage.CommandStorage;
|
||||
import net.minecraft.world.level.storage.DerivedLevelData;
|
||||
import net.minecraft.world.level.storage.DimensionDataStorage;
|
||||
@@ -163,7 +180,11 @@
|
||||
import net.minecraft.world.level.storage.loot.LootDataManager;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
-import org.slf4j.Logger;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.craftbukkit.CraftServer;
|
||||
+import org.bukkit.craftbukkit.Main;
|
||||
+import org.bukkit.event.server.ServerLoadEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, CommandSource, AutoCloseable {
|
||||
|
||||
@@ -171,7 +192,7 @@
|
||||
public static final String VANILLA_BRAND = "vanilla";
|
||||
private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F;
|
||||
private static final int TICK_STATS_SPAN = 100;
|
||||
- private static final long OVERLOADED_THRESHOLD_NANOS = 20L * TimeUtil.NANOSECONDS_PER_SECOND / 20L;
|
||||
+ private static final long OVERLOADED_THRESHOLD_NANOS = 30L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; // CraftBukkit
|
||||
private static final int OVERLOADED_TICKS_THRESHOLD = 20;
|
||||
private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND;
|
||||
private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100;
|
||||
@@ -254,7 +275,20 @@
|
||||
protected final WorldData worldData;
|
||||
private volatile boolean isSaving;
|
||||
|
||||
- public static <S extends MinecraftServer> S spin(Function<Thread, S> function) {
|
||||
+ // CraftBukkit start
|
||||
+ public final WorldLoader.a worldLoader;
|
||||
+ public org.bukkit.craftbukkit.CraftServer server;
|
||||
+ public OptionSet options;
|
||||
+ public org.bukkit.command.ConsoleCommandSender console;
|
||||
+ public ConsoleReader reader;
|
||||
+ public static int currentTick = (int) (System.currentTimeMillis() / 50);
|
||||
+ public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
|
||||
+ public int autosavePeriod;
|
||||
+ public Commands vanillaCommandDispatcher;
|
||||
+ private boolean forceTicks;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
||||
AtomicReference<S> atomicreference = new AtomicReference();
|
||||
Thread thread = new Thread(() -> {
|
||||
((MinecraftServer) atomicreference.get()).runServer();
|
||||
@@ -295,7 +329,7 @@
|
||||
this.customBossEvents = new CustomBossEvents();
|
||||
this.registries = worldstem.registries();
|
||||
this.worldData = worldstem.worldData();
|
||||
- if (!this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) {
|
||||
+ if (false && !this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later
|
||||
throw new IllegalStateException("Missing Overworld dimension data");
|
||||
} else {
|
||||
this.proxy = proxy;
|
||||
@@ -319,6 +353,33 @@
|
||||
this.serverThread = thread;
|
||||
this.executor = Util.backgroundExecutor();
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ this.options = options;
|
||||
+ this.worldLoader = worldLoader;
|
||||
+ this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit
|
||||
+ // Try to see if we're actually running in a terminal, disable jline if not
|
||||
+ if (System.console() == null && System.getProperty("jline.terminal") == null) {
|
||||
+ System.setProperty("jline.terminal", "jline.UnsupportedTerminal");
|
||||
+ Main.useJline = false;
|
||||
+ }
|
||||
+
|
||||
+ try {
|
||||
+ reader = new ConsoleReader(System.in, System.out);
|
||||
+ reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators
|
||||
+ } catch (Throwable e) {
|
||||
+ try {
|
||||
+ // Try again with jline disabled for Windows users without C++ 2008 Redistributable
|
||||
+ System.setProperty("jline.terminal", "jline.UnsupportedTerminal");
|
||||
+ System.setProperty("user.language", "en");
|
||||
+ Main.useJline = false;
|
||||
+ reader = new ConsoleReader(System.in, System.out);
|
||||
+ reader.setExpandEvents(false);
|
||||
+ } catch (IOException ex) {
|
||||
+ LOGGER.warn((String) null, ex);
|
||||
+ }
|
||||
+ }
|
||||
+ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this));
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
private void readScoreboard(DimensionDataStorage dimensiondatastorage) {
|
||||
@@ -327,7 +388,7 @@
|
||||
|
||||
protected abstract boolean initServer() throws IOException;
|
||||
|
||||
- protected void loadLevel() {
|
||||
+ protected void loadLevel(String s) { // CraftBukkit
|
||||
if (!JvmProfiler.INSTANCE.isRunning()) {
|
||||
;
|
||||
}
|
||||
@@ -335,8 +396,7 @@
|
||||
boolean flag = false;
|
||||
ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted();
|
||||
|
||||
- this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified());
|
||||
- ChunkProgressListener chunkprogresslistener = this.progressListenerFactory.create(11);
|
||||
+ loadWorld0(s); // CraftBukkit
|
||||
|
||||
this.createLevels(chunkprogresslistener);
|
||||
this.forceDifficulty();
|
||||
@@ -357,16 +414,9 @@
|
||||
|
||||
protected void forceDifficulty() {}
|
||||
|
||||
- protected void createLevels(ChunkProgressListener chunkprogresslistener) {
|
||||
- ServerLevelData serverleveldata = this.worldData.overworldData();
|
||||
- boolean flag = this.worldData.isDebugWorld();
|
||||
- Registry<LevelStem> registry = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM);
|
||||
- WorldOptions worldoptions = this.worldData.worldGenOptions();
|
||||
- long i = worldoptions.seed();
|
||||
- long j = BiomeManager.obfuscateSeed(i);
|
||||
- List<CustomSpawner> list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(serverleveldata));
|
||||
- LevelStem levelstem = (LevelStem) registry.get(LevelStem.OVERWORLD);
|
||||
- ServerLevel serverlevel = new ServerLevel(this, this.executor, this.storageSource, serverleveldata, Level.OVERWORLD, levelstem, chunkprogresslistener, flag, j, list, true, (RandomSequences) null);
|
||||
+ // CraftBukkit start
|
||||
+ private void loadWorld0(String s) {
|
||||
+ LevelStorageSource.LevelStorageAccess worldSession = this.storageSource;
|
||||
|
||||
this.levels.put(Level.OVERWORLD, serverlevel);
|
||||
DimensionDataStorage dimensiondatastorage = serverlevel.getDataStorage();
|
||||
@@ -375,7 +425,207 @@
|
||||
this.commandStorage = new CommandStorage(dimensiondatastorage);
|
||||
WorldBorder worldborder = serverlevel.getWorldBorder();
|
||||
|
||||
- if (!serverleveldata.isInitialized()) {
|
||||
+ if (dimensionKey == LevelStem.NETHER) {
|
||||
+ if (isNetherEnabled()) {
|
||||
+ dimension = -1;
|
||||
+ } else {
|
||||
+ continue;
|
||||
+ }
|
||||
+ } else if (dimensionKey == LevelStem.END) {
|
||||
+ if (server.getAllowEnd()) {
|
||||
+ dimension = 1;
|
||||
+ } else {
|
||||
+ continue;
|
||||
+ }
|
||||
+ } else if (dimensionKey != LevelStem.OVERWORLD) {
|
||||
+ dimension = -999;
|
||||
+ }
|
||||
+
|
||||
+ String worldType = (dimension == -999) ? dimensionKey.location().getNamespace() + "_" + dimensionKey.location().getPath() : org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase();
|
||||
+ String name = (dimensionKey == LevelStem.OVERWORLD) ? s : s + "_" + worldType;
|
||||
+ if (dimension != 0) {
|
||||
+ File newWorld = LevelStorageSource.getStorageFolder(new File(name).toPath(), dimensionKey).toFile();
|
||||
+ File oldWorld = LevelStorageSource.getStorageFolder(new File(s).toPath(), dimensionKey).toFile();
|
||||
+ File oldLevelDat = new File(new File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't
|
||||
+
|
||||
+ if (!newWorld.isDirectory() && oldWorld.isDirectory() && oldLevelDat.isFile()) {
|
||||
+ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder required ----");
|
||||
+ MinecraftServer.LOGGER.info("Unfortunately due to the way that Minecraft implemented multiworld support in 1.6, Bukkit requires that you move your " + worldType + " folder to a new location in order to operate correctly.");
|
||||
+ MinecraftServer.LOGGER.info("We will move this folder for you, but it will mean that you need to move it back should you wish to stop using Bukkit in the future.");
|
||||
+ MinecraftServer.LOGGER.info("Attempting to move " + oldWorld + " to " + newWorld + "...");
|
||||
+
|
||||
+ if (newWorld.exists()) {
|
||||
+ MinecraftServer.LOGGER.warn("A file or folder already exists at " + newWorld + "!");
|
||||
+ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----");
|
||||
+ } else if (newWorld.getParentFile().mkdirs()) {
|
||||
+ if (oldWorld.renameTo(newWorld)) {
|
||||
+ MinecraftServer.LOGGER.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld);
|
||||
+ // Migrate world data too.
|
||||
+ try {
|
||||
+ com.google.common.io.Files.copy(oldLevelDat, new File(new File(name), "level.dat"));
|
||||
+ org.apache.commons.io.FileUtils.copyDirectory(new File(new File(s), "data"), new File(new File(name), "data"));
|
||||
+ } catch (IOException exception) {
|
||||
+ MinecraftServer.LOGGER.warn("Unable to migrate world data.");
|
||||
+ }
|
||||
+ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder complete ----");
|
||||
+ } else {
|
||||
+ MinecraftServer.LOGGER.warn("Could not move folder " + oldWorld + " to " + newWorld + "!");
|
||||
+ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----");
|
||||
+ }
|
||||
+ } else {
|
||||
+ MinecraftServer.LOGGER.warn("Could not create path for " + newWorld + "!");
|
||||
+ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ try {
|
||||
+ worldSession = LevelStorageSource.createDefault(server.getWorldContainer().toPath()).validateAndCreateAccess(name, dimensionKey);
|
||||
+ } catch (IOException | ContentValidationException ex) {
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Dynamic<?> dynamic;
|
||||
+ if (worldSession.hasWorldData()) {
|
||||
+ LevelSummary worldinfo;
|
||||
+
|
||||
+ try {
|
||||
+ dynamic = worldSession.getDataTag();
|
||||
+ worldinfo = worldSession.getSummary(dynamic);
|
||||
+ } catch (NbtException | ReportedNbtException | IOException ioexception) {
|
||||
+ LevelStorageSource.LevelDirectory convertable_b = worldSession.getLevelDirectory();
|
||||
+
|
||||
+ MinecraftServer.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception);
|
||||
+ MinecraftServer.LOGGER.info("Attempting to use fallback");
|
||||
+
|
||||
+ try {
|
||||
+ dynamic = worldSession.getDataTagFallback();
|
||||
+ worldinfo = worldSession.getSummary(dynamic);
|
||||
+ } catch (NbtException | ReportedNbtException | IOException ioexception1) {
|
||||
+ MinecraftServer.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1);
|
||||
+ MinecraftServer.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile());
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ worldSession.restoreLevelDataFromOld();
|
||||
+ }
|
||||
+
|
||||
+ if (worldinfo.requiresManualConversion()) {
|
||||
+ MinecraftServer.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!worldinfo.isCompatible()) {
|
||||
+ MinecraftServer.LOGGER.info("This world was created by an incompatible version.");
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
+ dynamic = null;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name);
|
||||
+ org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name);
|
||||
+
|
||||
+ PrimaryLevelData worlddata;
|
||||
+ WorldLoader.a worldloader_a = this.worldLoader;
|
||||
+ Registry<LevelStem> iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
|
||||
+ if (dynamic != null) {
|
||||
+ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen());
|
||||
+
|
||||
+ worlddata = (PrimaryLevelData) leveldataanddimensions.worldData();
|
||||
+ } else {
|
||||
+ LevelSettings worldsettings;
|
||||
+ WorldOptions worldoptions;
|
||||
+ WorldDimensions worlddimensions;
|
||||
+
|
||||
+ if (this.isDemo()) {
|
||||
+ worldsettings = MinecraftServer.DEMO_SETTINGS;
|
||||
+ worldoptions = WorldOptions.DEMO_OPTIONS;
|
||||
+ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen());
|
||||
+ } else {
|
||||
+ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties();
|
||||
+
|
||||
+ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration());
|
||||
+ worldoptions = options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions;
|
||||
+ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen());
|
||||
+ }
|
||||
+
|
||||
+ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry);
|
||||
+ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle());
|
||||
+
|
||||
+ worlddata = new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle);
|
||||
+ }
|
||||
+ worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end)
|
||||
+ if (options.has("forceUpgrade")) {
|
||||
+ net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), options.has("eraseCache"), () -> {
|
||||
+ return true;
|
||||
+ }, dimensions);
|
||||
+ }
|
||||
+
|
||||
+ PrimaryLevelData iworlddataserver = worlddata;
|
||||
+ boolean flag = worlddata.isDebugWorld();
|
||||
+ WorldOptions worldoptions = worlddata.worldGenOptions();
|
||||
+ long i = worldoptions.seed();
|
||||
+ long j = BiomeManager.obfuscateSeed(i);
|
||||
+ List<CustomSpawner> list = ImmutableList.of(new MobSpawnerPhantom(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver));
|
||||
+ LevelStem worlddimension = (LevelStem) dimensions.get(dimensionKey);
|
||||
+
|
||||
+ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value());
|
||||
+ if (biomeProvider == null && gen != null) {
|
||||
+ biomeProvider = gen.getDefaultBiomeProvider(worldInfo);
|
||||
+ }
|
||||
+
|
||||
+ ResourceKey<Level> worldKey = ResourceKey.create(Registries.DIMENSION, dimensionKey.location());
|
||||
+
|
||||
+ if (dimensionKey == LevelStem.OVERWORLD) {
|
||||
+ this.worldData = worlddata;
|
||||
+ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init
|
||||
+
|
||||
+ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11);
|
||||
+
|
||||
+ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
|
||||
+ DimensionDataStorage worldpersistentdata = world.getDataStorage();
|
||||
+ this.readScoreboard(worldpersistentdata);
|
||||
+ this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard());
|
||||
+ this.commandStorage = new CommandStorage(worldpersistentdata);
|
||||
+ } else {
|
||||
+ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11);
|
||||
+ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider);
|
||||
+ }
|
||||
+
|
||||
+ worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified());
|
||||
+ this.initWorld(world, worlddata, worldData, worldoptions);
|
||||
+
|
||||
+ this.addLevel(world);
|
||||
+ this.getPlayerList().addWorldborderListener(world);
|
||||
+
|
||||
+ if (worlddata.getCustomBossEvents() != null) {
|
||||
+ this.getCustomBossEvents().load(worlddata.getCustomBossEvents());
|
||||
+ }
|
||||
+ }
|
||||
+ this.forceDifficulty();
|
||||
+ for (ServerLevel worldserver : this.getAllLevels()) {
|
||||
+ this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver);
|
||||
+ worldserver.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API
|
||||
+ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld()));
|
||||
+ }
|
||||
+
|
||||
+ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD);
|
||||
+ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP));
|
||||
+ this.connection.acceptConnections();
|
||||
+ }
|
||||
+
|
||||
+ public void initWorld(ServerLevel worldserver, ServerLevelData iworlddataserver, WorldData saveData, WorldOptions worldoptions) {
|
||||
+ boolean flag = saveData.isDebugWorld();
|
||||
+ // CraftBukkit start
|
||||
+ if (worldserver.generator != null) {
|
||||
+ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld()));
|
||||
+ }
|
||||
+ WorldBorder worldborder = worldserver.getWorldBorder();
|
||||
+ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent
|
||||
+ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated
|
||||
+
|
||||
+ if (!iworlddataserver.isInitialized()) {
|
||||
try {
|
||||
setInitialSpawn(serverlevel, serverleveldata, worldoptions.generateBonusChest(), flag);
|
||||
serverleveldata.setInitialized(true);
|
||||
@@ -421,17 +648,30 @@
|
||||
|
||||
worldborder.applySettings(serverleveldata.getWorldBorder());
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
private static void setInitialSpawn(ServerLevel serverlevel, ServerLevelData serverleveldata, boolean flag, boolean flag1) {
|
||||
if (flag1) {
|
||||
serverleveldata.setSpawn(BlockPos.ZERO.above(80), 0.0F);
|
||||
} else {
|
||||
- ServerChunkCache serverchunkcache = serverlevel.getChunkSource();
|
||||
- ChunkPos chunkpos = new ChunkPos(serverchunkcache.randomState().sampler().findSpawnPosition());
|
||||
- int i = serverchunkcache.getGenerator().getSpawnHeight(serverlevel);
|
||||
+ ServerChunkCache chunkproviderserver = level.getChunkSource();
|
||||
+ ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition());
|
||||
+ // CraftBukkit start
|
||||
+ if (level.generator != null) {
|
||||
+ Random rand = new Random(level.getSeed());
|
||||
+ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand);
|
||||
|
||||
- if (i < serverlevel.getMinBuildHeight()) {
|
||||
- BlockPos blockpos = chunkpos.getWorldPosition();
|
||||
+ if (spawn != null) {
|
||||
+ if (spawn.getWorld() != level.getWorld()) {
|
||||
+ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")");
|
||||
+ } else {
|
||||
+ levelData.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw());
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ int i = chunkproviderserver.getGenerator().getSpawnHeight(level);
|
||||
|
||||
i = serverlevel.getHeight(Heightmap.Types.WORLD_SURFACE, blockpos.getX() + 8, blockpos.getZ() + 8);
|
||||
}
|
||||
@@ -487,8 +730,11 @@
|
||||
serverleveldata.setGameType(GameType.SPECTATOR);
|
||||
}
|
||||
|
||||
- private void prepareLevels(ChunkProgressListener chunkprogresslistener) {
|
||||
- ServerLevel serverlevel = this.overworld();
|
||||
+ // CraftBukkit start
|
||||
+ public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) {
|
||||
+ // WorldServer worldserver = this.overworld();
|
||||
+ this.forceTicks = true;
|
||||
+ // CraftBukkit end
|
||||
|
||||
MinecraftServer.LOGGER.info("Preparing start region for dimension {}", serverlevel.dimension().location());
|
||||
BlockPos blockpos = serverlevel.getSharedSpawnPos();
|
||||
@@ -497,7 +743,9 @@
|
||||
ServerChunkCache serverchunkcache = serverlevel.getChunkSource();
|
||||
|
||||
this.nextTickTimeNanos = Util.getNanos();
|
||||
- serverchunkcache.addRegionTicket(TicketType.START, new ChunkPos(blockpos), 11, Unit.INSTANCE);
|
||||
+ // CraftBukkit start
|
||||
+ if (worldserver.getWorld().getKeepSpawnInMemory()) {
|
||||
+ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE);
|
||||
|
||||
while (serverchunkcache.getTickingGenerated() != 441) {
|
||||
this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS;
|
||||
@@ -508,9 +757,10 @@
|
||||
this.waitUntilNextTick();
|
||||
Iterator iterator = this.levels.values().iterator();
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
- ServerLevel serverlevel1 = (ServerLevel) iterator.next();
|
||||
- ForcedChunksSavedData forcedchunkssaveddata = (ForcedChunksSavedData) serverlevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks");
|
||||
+ if (true) {
|
||||
+ ServerLevel worldserver1 = worldserver;
|
||||
+ // CraftBukkit end
|
||||
+ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks");
|
||||
|
||||
if (forcedchunkssaveddata != null) {
|
||||
LongIterator longiterator = forcedchunkssaveddata.getChunks().iterator();
|
||||
@@ -524,10 +774,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS;
|
||||
- this.waitUntilNextTick();
|
||||
- chunkprogresslistener.stop();
|
||||
- this.updateMobSpawningFlags();
|
||||
+ // CraftBukkit start
|
||||
+ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS;
|
||||
+ this.executeModerately();
|
||||
+ // CraftBukkit end
|
||||
+ worldloadlistener.stop();
|
||||
+ // CraftBukkit start
|
||||
+ // this.updateMobSpawningFlags();
|
||||
+ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals());
|
||||
+
|
||||
+ this.forceTicks = false;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public GameType getDefaultGameType() {
|
||||
@@ -557,13 +814,17 @@
|
||||
serverlevel.save((ProgressListener) null, flag1, serverlevel.noSave && !flag2);
|
||||
}
|
||||
|
||||
- ServerLevel serverlevel1 = this.overworld();
|
||||
- ServerLevelData serverleveldata = this.worldData.overworldData();
|
||||
+ // CraftBukkit start - moved to WorldServer.save
|
||||
+ /*
|
||||
+ WorldServer worldserver1 = this.overworld();
|
||||
+ IWorldDataServer iworlddataserver = this.worldData.overworldData();
|
||||
|
||||
serverleveldata.setWorldBorder(serverlevel1.getWorldBorder().createSettings());
|
||||
this.worldData.setCustomBossEvents(this.getCustomBossEvents().save());
|
||||
this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData());
|
||||
- if (flag1) {
|
||||
+ */
|
||||
+ // CraftBukkit end
|
||||
+ if (flush) {
|
||||
Iterator iterator1 = this.getAllLevels().iterator();
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
@@ -598,18 +858,40 @@
|
||||
this.stopServer();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private boolean hasStopped = false;
|
||||
+ private final Object stopLock = new Object();
|
||||
+ public final boolean hasStopped() {
|
||||
+ synchronized (stopLock) {
|
||||
+ return hasStopped;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public void stopServer() {
|
||||
+ // CraftBukkit start - prevent double stopping on multiple threads
|
||||
+ synchronized(stopLock) {
|
||||
+ if (hasStopped) return;
|
||||
+ hasStopped = true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (this.metricsRecorder.isRecording()) {
|
||||
this.cancelRecordingMetrics();
|
||||
}
|
||||
|
||||
MinecraftServer.LOGGER.info("Stopping server");
|
||||
+ // CraftBukkit start
|
||||
+ if (this.server != null) {
|
||||
+ this.server.disablePlugins();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.getConnection().stop();
|
||||
this.isSaving = true;
|
||||
if (this.playerList != null) {
|
||||
MinecraftServer.LOGGER.info("Saving players");
|
||||
this.playerList.saveAll();
|
||||
this.playerList.removeAll();
|
||||
+ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets
|
||||
}
|
||||
|
||||
MinecraftServer.LOGGER.info("Saving worlds");
|
||||
@@ -714,6 +996,7 @@
|
||||
if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) {
|
||||
long k = j / i;
|
||||
|
||||
+ if (server.getWarnOnOverload()) // CraftBukkit
|
||||
MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k);
|
||||
this.nextTickTimeNanos += k * i;
|
||||
this.lastOverloadWarningNanos = this.nextTickTimeNanos;
|
||||
@@ -727,6 +1010,7 @@
|
||||
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
|
||||
}
|
||||
|
||||
+ MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit
|
||||
this.nextTickTimeNanos += i;
|
||||
this.startMetricsRecordingTick();
|
||||
this.profiler.push("tick");
|
||||
@@ -771,6 +1055,12 @@
|
||||
this.services.profileCache().clearExecutor();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - Restore terminal to original settings
|
||||
+ try {
|
||||
+ reader.getTerminal().restore();
|
||||
+ } catch (Exception ignored) {
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.onServerExit();
|
||||
}
|
||||
|
||||
@@ -804,9 +1094,16 @@
|
||||
}
|
||||
|
||||
private boolean haveTime() {
|
||||
- return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos);
|
||||
+ // CraftBukkit start
|
||||
+ return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos);
|
||||
}
|
||||
|
||||
+ private void executeModerately() {
|
||||
+ this.runAllTasks();
|
||||
+ java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L);
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
protected void waitUntilNextTick() {
|
||||
this.runAllTasks();
|
||||
this.managedBlock(() -> {
|
||||
@@ -914,8 +1207,10 @@
|
||||
}
|
||||
|
||||
--this.ticksUntilAutosave;
|
||||
- if (this.ticksUntilAutosave <= 0) {
|
||||
- this.ticksUntilAutosave = this.computeNextAutosaveInterval();
|
||||
+ // CraftBukkit start
|
||||
+ if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) {
|
||||
+ this.ticksUntilAutosave = this.autosavePeriod;
|
||||
+ // CraftBukkit end
|
||||
MinecraftServer.LOGGER.debug("Autosave started");
|
||||
this.profiler.push("save");
|
||||
this.saveEverything(true, false, false);
|
||||
@@ -996,11 +1291,26 @@
|
||||
this.getPlayerList().getPlayers().forEach((serverplayer) -> {
|
||||
serverplayer.connection.suspendFlushing();
|
||||
});
|
||||
+ this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit
|
||||
this.profiler.push("commandFunctions");
|
||||
this.getFunctions().tick();
|
||||
this.profiler.popPush("levels");
|
||||
Iterator iterator = this.getAllLevels().iterator();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ // Run tasks that are waiting on processing
|
||||
+ while (!processQueue.isEmpty()) {
|
||||
+ processQueue.remove().run();
|
||||
+ }
|
||||
+
|
||||
+ // Send time updates to everyone, it will get the right time from the world the player is in.
|
||||
+ if (this.tickCount % 20 == 0) {
|
||||
+ for (int i = 0; i < this.getPlayerList().players.size(); ++i) {
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i);
|
||||
+ entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
while (iterator.hasNext()) {
|
||||
ServerLevel serverlevel = (ServerLevel) iterator.next();
|
||||
|
||||
@@ -1012,6 +1323,7 @@
|
||||
this.synchronizeTime(serverlevel);
|
||||
this.profiler.pop();
|
||||
}
|
||||
+ // CraftBukkit end */
|
||||
|
||||
this.profiler.push("tick");
|
||||
|
||||
@@ -1101,6 +1413,22 @@
|
||||
return (ServerLevel) this.levels.get(resourcekey);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void addLevel(ServerLevel level) {
|
||||
+ Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
||||
+ Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
||||
+ newLevels.put(level.dimension(), level);
|
||||
+ this.levels = Collections.unmodifiableMap(newLevels);
|
||||
+ }
|
||||
+
|
||||
+ public void removeLevel(ServerLevel level) {
|
||||
+ Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
||||
+ Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
||||
+ newLevels.remove(level.dimension());
|
||||
+ this.levels = Collections.unmodifiableMap(newLevels);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public Set<ResourceKey<Level>> levelKeys() {
|
||||
return this.levels.keySet();
|
||||
}
|
||||
@@ -1133,7 +1458,7 @@
|
||||
|
||||
@DontObfuscate
|
||||
public String getServerModName() {
|
||||
- return "vanilla";
|
||||
+ return server.getName(); // CraftBukkit - cb > vanilla!
|
||||
}
|
||||
|
||||
public SystemReport fillSystemReport(SystemReport systemreport) {
|
||||
@@ -1920,6 +2237,22 @@
|
||||
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ @Override
|
||||
+ public boolean isSameThread() {
|
||||
+ return super.isSameThread() || this.isStopped(); // CraftBukkit - MC-142590
|
||||
+ }
|
||||
+
|
||||
+ public boolean isDebugging() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public static MinecraftServer getServer() {
|
||||
+ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
private void startMetricsRecordingTick() {
|
||||
if (this.willStartRecordingMetrics) {
|
||||
this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), Util.timeSource, Util.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> {
|
||||
@@ -2046,6 +2379,11 @@
|
||||
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool(
|
||||
+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build());
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public ChatDecorator getChatDecorator() {
|
||||
return ChatDecorator.PLAIN;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -196,7 +196,8 @@
|
||||
AdvancementHolder advancementholder = serveradvancementmanager.get(resourcelocation);
|
||||
|
||||
if (advancementholder == null) {
|
||||
- PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", resourcelocation, this.playerSavePath);
|
||||
+ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit
|
||||
+ PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath);
|
||||
} else {
|
||||
this.startProgress(advancementholder, advancementprogress);
|
||||
this.progressChanged.add(advancementholder);
|
||||
@@ -227,6 +228,7 @@
|
||||
this.progressChanged.add(advancementholder);
|
||||
flag = true;
|
||||
if (!flag1 && advancementprogress.isDone()) {
|
||||
+ this.player.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancementholder.toBukkit())); // CraftBukkit
|
||||
advancementholder.value().rewards().grant(this.player);
|
||||
advancementholder.value().display().ifPresent((displayinfo) -> {
|
||||
if (displayinfo.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/server/ServerFunctionManager.java
|
||||
+++ b/net/minecraft/server/ServerFunctionManager.java
|
||||
@@ -37,7 +36,7 @@
|
||||
}
|
||||
|
||||
public CommandDispatcher<CommandSourceStack> getDispatcher() {
|
||||
- return this.server.getCommands().getDispatcher();
|
||||
+ return this.server.vanillaCommandDispatcher.getDispatcher(); // CraftBukkit
|
||||
}
|
||||
|
||||
public void tick() {
|
|
@ -0,0 +1,176 @@
|
|||
--- a/net/minecraft/server/ServerScoreboard.java
|
||||
+++ b/net/minecraft/server/ServerScoreboard.java
|
||||
@@ -37,11 +37,10 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- protected void onScoreChanged(ScoreHolder scoreholder, Objective objective, Score score) {
|
||||
- super.onScoreChanged(scoreholder, objective, score);
|
||||
- if (this.trackedObjectives.contains(objective)) {
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), objective.getName(), score.value(), score.display(), score.numberFormat()));
|
||||
+ protected void onScoreChanged(ScoreHolder scoreholder, Objective scoreboardobjective, Score scoreboardscore) {
|
||||
+ super.onScoreChanged(scoreholder, scoreboardobjective, scoreboardscore);
|
||||
+ if (this.trackedObjectives.contains(scoreboardobjective)) {
|
||||
+ this.broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); // CraftBukkit
|
||||
}
|
||||
|
||||
this.setDirty();
|
||||
@@ -58,16 +55,15 @@
|
||||
@Override
|
||||
public void onPlayerRemoved(ScoreHolder scoreholder) {
|
||||
super.onPlayerRemoved(scoreholder);
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null));
|
||||
+ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); // CraftBukkit
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective objective) {
|
||||
- super.onPlayerScoreRemoved(scoreholder, objective);
|
||||
- if (this.trackedObjectives.contains(objective)) {
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), objective.getName()));
|
||||
+ public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective scoreboardobjective) {
|
||||
+ super.onPlayerScoreRemoved(scoreholder, scoreboardobjective);
|
||||
+ if (this.trackedObjectives.contains(scoreboardobjective)) {
|
||||
+ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); // CraftBukkit
|
||||
}
|
||||
|
||||
this.setDirty();
|
||||
@@ -78,18 +73,18 @@
|
||||
public void setDisplayObjective(DisplaySlot displayslot, @Nullable Objective objective) {
|
||||
Objective objective1 = this.getDisplayObjective(displayslot);
|
||||
|
||||
- super.setDisplayObjective(displayslot, objective);
|
||||
- if (objective1 != objective && objective1 != null) {
|
||||
- if (this.getObjectiveDisplaySlotCount(objective1) > 0) {
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, objective));
|
||||
+ super.setDisplayObjective(displayslot, scoreboardobjective);
|
||||
+ if (scoreboardobjective1 != scoreboardobjective && scoreboardobjective1 != null) {
|
||||
+ if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) {
|
||||
+ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit
|
||||
} else {
|
||||
this.stopTrackingObjective(objective1);
|
||||
}
|
||||
}
|
||||
|
||||
- if (objective != null) {
|
||||
- if (this.trackedObjectives.contains(objective)) {
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, objective));
|
||||
+ if (scoreboardobjective != null) {
|
||||
+ if (this.trackedObjectives.contains(scoreboardobjective)) {
|
||||
+ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit
|
||||
} else {
|
||||
this.startTrackingObjective(objective);
|
||||
}
|
||||
@@ -99,10 +94,9 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public boolean addPlayerToTeam(String s, PlayerTeam playerteam) {
|
||||
- if (super.addPlayerToTeam(s, playerteam)) {
|
||||
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerteam, s, ClientboundSetPlayerTeamPacket.Action.ADD));
|
||||
+ public boolean addPlayerToTeam(String playerName, PlayerTeam team) {
|
||||
+ if (super.addPlayerToTeam(playerName, team)) {
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.a.ADD)); // CraftBukkit
|
||||
this.setDirty();
|
||||
return true;
|
||||
} else {
|
||||
@@ -111,10 +105,9 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void removePlayerFromTeam(String s, PlayerTeam playerteam) {
|
||||
- super.removePlayerFromTeam(s, playerteam);
|
||||
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerteam, s, ClientboundSetPlayerTeamPacket.Action.REMOVE));
|
||||
+ public void removePlayerFromTeam(String username, PlayerTeam playerTeam) {
|
||||
+ super.removePlayerFromTeam(username, playerTeam);
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.a.REMOVE)); // CraftBukkit
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@@ -130,7 +121,7 @@
|
||||
public void onObjectiveChanged(Objective objective) {
|
||||
super.onObjectiveChanged(objective);
|
||||
if (this.trackedObjectives.contains(objective)) {
|
||||
- this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(objective, 2));
|
||||
+ this.broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); // CraftBukkit
|
||||
}
|
||||
|
||||
this.setDirty();
|
||||
@@ -148,26 +138,23 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onTeamAdded(PlayerTeam playerteam) {
|
||||
- super.onTeamAdded(playerteam);
|
||||
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, true));
|
||||
+ public void onTeamAdded(PlayerTeam playerTeam) {
|
||||
+ super.onTeamAdded(playerTeam);
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); // CraftBukkit
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onTeamChanged(PlayerTeam playerteam) {
|
||||
- super.onTeamChanged(playerteam);
|
||||
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, false));
|
||||
+ public void onTeamChanged(PlayerTeam playerTeam) {
|
||||
+ super.onTeamChanged(playerTeam);
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onTeamRemoved(PlayerTeam playerteam) {
|
||||
- super.onTeamRemoved(playerteam);
|
||||
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerteam));
|
||||
+ public void onTeamRemoved(PlayerTeam playerTeam) {
|
||||
+ super.onTeamRemoved(playerTeam);
|
||||
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@@ -217,7 +204,8 @@
|
||||
Iterator iterator = this.server.getPlayerList().getPlayers().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
- ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) iterator.next();
|
||||
+ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
|
||||
Iterator iterator1 = list.iterator();
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
@@ -253,7 +241,8 @@
|
||||
Iterator iterator = this.server.getPlayerList().getPlayers().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
- ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) iterator.next();
|
||||
+ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
|
||||
Iterator iterator1 = list.iterator();
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
@@ -298,7 +287,15 @@
|
||||
return this.createData().load(compoundtag);
|
||||
}
|
||||
|
||||
- public static enum Method {
|
||||
+ // CraftBukkit start - Send to players
|
||||
+ private void broadcastAll(Packet packet) {
|
||||
+ for (ServerPlayer entityplayer : (List<ServerPlayer>) this.server.getPlayerList().players) {
|
||||
+ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) {
|
||||
+ entityplayer.connection.send(packet);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
CHANGE, REMOVE;
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
--- a/net/minecraft/server/ServerTickRateManager.java
|
||||
+++ b/net/minecraft/server/ServerTickRateManager.java
|
||||
@@ -60,8 +59,14 @@
|
||||
}
|
||||
|
||||
public boolean stopSprinting() {
|
||||
+ // CraftBukkit start, add sendLog parameter
|
||||
+ return stopSprinting(true);
|
||||
+ }
|
||||
+
|
||||
+ public boolean stopSprinting(boolean sendLog) {
|
||||
+ // CraftBukkit end
|
||||
if (this.remainingSprintTicks > 0L) {
|
||||
- this.finishTickSprint();
|
||||
+ this.finishTickSprint(sendLog); // CraftBukkit - add sendLog parameter
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -79,7 +84,7 @@
|
||||
return flag;
|
||||
}
|
||||
|
||||
- private void finishTickSprint() {
|
||||
+ private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter
|
||||
long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks;
|
||||
double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND;
|
||||
int j = (int) ((double) (TimeUtil.MILLISECONDS_PER_SECOND * i) / d0);
|
||||
@@ -87,9 +92,13 @@
|
||||
|
||||
this.scheduledCurrentSprintTicks = 0L;
|
||||
this.sprintTimeSpend = 0L;
|
||||
- this.server.createCommandSourceStack().sendSuccess(() -> {
|
||||
- return Component.translatable("commands.tick.sprint.report", j, s);
|
||||
- }, true);
|
||||
+ // CraftBukkit start - add sendLog parameter
|
||||
+ if (sendLog) {
|
||||
+ this.server.createCommandSourceStack().sendSuccess(() -> {
|
||||
+ return Component.translatable("commands.tick.sprint.report", j, s);
|
||||
+ }, true);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.remainingSprintTicks = 0L;
|
||||
this.setFrozen(this.previousIsFrozen);
|
||||
this.server.onTickRateChanged();
|
||||
@@ -103,7 +112,7 @@
|
||||
--this.remainingSprintTicks;
|
||||
return true;
|
||||
} else {
|
||||
- this.finishTickSprint();
|
||||
+ this.finishTickSprint(true); // CraftBukkit - add sendLog parameter
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
--- a/net/minecraft/server/bossevents/CustomBossEvent.java
|
||||
+++ b/net/minecraft/server/bossevents/CustomBossEvent.java
|
||||
@@ -17,6 +17,10 @@
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.BossEvent;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.boss.KeyedBossBar;
|
||||
+import org.bukkit.craftbukkit.boss.CraftKeyedBossbar;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class CustomBossEvent extends ServerBossEvent {
|
||||
|
||||
@@ -24,10 +28,20 @@
|
||||
private final Set<UUID> players = Sets.newHashSet();
|
||||
private int value;
|
||||
private int max = 100;
|
||||
+ // CraftBukkit start
|
||||
+ private KeyedBossBar bossBar;
|
||||
|
||||
- public CustomBossEvent(ResourceLocation resourcelocation, Component component) {
|
||||
- super(component, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS);
|
||||
- this.id = resourcelocation;
|
||||
+ public KeyedBossBar getBukkitEntity() {
|
||||
+ if (bossBar == null) {
|
||||
+ bossBar = new CraftKeyedBossbar(this);
|
||||
+ }
|
||||
+ return bossBar;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public CustomBossEvent(ResourceLocation id, Component name) {
|
||||
+ super(name, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS);
|
||||
+ this.id = id;
|
||||
this.setProgress(0.0F);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
--- a/net/minecraft/server/commands/DifficultyCommand.java
|
||||
+++ b/net/minecraft/server/commands/DifficultyCommand.java
|
||||
@@ -43,14 +42,15 @@
|
||||
}));
|
||||
}
|
||||
|
||||
- public static int setDifficulty(CommandSourceStack commandsourcestack, Difficulty difficulty) throws CommandSyntaxException {
|
||||
- MinecraftServer minecraftserver = commandsourcestack.getServer();
|
||||
+ public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException {
|
||||
+ MinecraftServer minecraftserver = source.getServer();
|
||||
+ net.minecraft.server.level.ServerLevel worldServer = source.getLevel(); // CraftBukkit
|
||||
|
||||
- if (minecraftserver.getWorldData().getDifficulty() == difficulty) {
|
||||
+ if (worldServer.getDifficulty() == difficulty) { // CraftBukkit
|
||||
throw DifficultyCommand.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey());
|
||||
} else {
|
||||
- minecraftserver.setDifficulty(difficulty, true);
|
||||
- commandsourcestack.sendSuccess(() -> {
|
||||
+ worldServer.serverLevelData.setDifficulty(difficulty); // CraftBukkit
|
||||
+ source.sendSuccess(() -> {
|
||||
return Component.translatable("commands.difficulty.success", difficulty.getDisplayName());
|
||||
}, true);
|
||||
return 0;
|
|
@ -0,0 +1,29 @@
|
|||
--- a/net/minecraft/server/commands/EffectCommands.java
|
||||
+++ b/net/minecraft/server/commands/EffectCommands.java
|
||||
@@ -85,7 +84,7 @@
|
||||
if (entity instanceof LivingEntity) {
|
||||
MobEffectInstance mobeffectinstance = new MobEffectInstance(mobeffect, k, i, false, flag);
|
||||
|
||||
- if (((LivingEntity) entity).addEffect(mobeffectinstance, commandsourcestack.getEntity())) {
|
||||
+ if (((LivingEntity) entity).addEffect(mobeffect, source.getEntity(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit
|
||||
++j;
|
||||
}
|
||||
}
|
||||
@@ -115,7 +114,7 @@
|
||||
while (iterator.hasNext()) {
|
||||
Entity entity = (Entity) iterator.next();
|
||||
|
||||
- if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects()) {
|
||||
+ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@@ -145,7 +144,7 @@
|
||||
while (iterator.hasNext()) {
|
||||
Entity entity = (Entity) iterator.next();
|
||||
|
||||
- if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffect)) {
|
||||
+ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit
|
||||
++i;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
--- a/net/minecraft/server/commands/GameRuleCommand.java
|
||||
+++ b/net/minecraft/server/commands/GameRuleCommand.java
|
||||
@@ -31,9 +29,9 @@
|
||||
commanddispatcher.register(literalargumentbuilder);
|
||||
}
|
||||
|
||||
- static <T extends GameRules.Value<T>> int setRule(CommandContext<CommandSourceStack> commandcontext, GameRules.Key<T> gamerules_key) {
|
||||
- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource();
|
||||
- T t0 = commandsourcestack.getServer().getGameRules().getRule(gamerules_key);
|
||||
+ static <T extends GameRules.Value<T>> int setRule(CommandContext<CommandSourceStack> source, GameRules.Key<T> gameRule) {
|
||||
+ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) source.getSource();
|
||||
+ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gameRule); // CraftBukkit
|
||||
|
||||
t0.setFromArgument(commandcontext, "value");
|
||||
commandsourcestack.sendSuccess(() -> {
|
||||
@@ -42,8 +40,8 @@
|
||||
return t0.getCommandResult();
|
||||
}
|
||||
|
||||
- static <T extends GameRules.Value<T>> int queryRule(CommandSourceStack commandsourcestack, GameRules.Key<T> gamerules_key) {
|
||||
- T t0 = commandsourcestack.getServer().getGameRules().getRule(gamerules_key);
|
||||
+ static <T extends GameRules.Value<T>> int queryRule(CommandSourceStack source, GameRules.Key<T> gameRule) {
|
||||
+ T t0 = source.getLevel().getGameRules().getRule(gameRule); // CraftBukkit
|
||||
|
||||
commandsourcestack.sendSuccess(() -> {
|
||||
return Component.translatable("commands.gamerule.query", gamerules_key.getId(), t0.toString());
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
--- a/net/minecraft/server/commands/ListPlayersCommand.java
|
||||
+++ b/net/minecraft/server/commands/ListPlayersCommand.java
|
||||
@@ -34,10 +33,17 @@
|
||||
});
|
||||
}
|
||||
|
||||
- private static int format(CommandSourceStack commandsourcestack, Function<ServerPlayer, Component> function) {
|
||||
- PlayerList playerlist = commandsourcestack.getServer().getPlayerList();
|
||||
- List<ServerPlayer> list = playerlist.getPlayers();
|
||||
- Component component = ComponentUtils.formatList(list, function);
|
||||
+ private static int format(CommandSourceStack source, Function<ServerPlayer, Component> nameExtractor) {
|
||||
+ PlayerList playerlist = source.getServer().getPlayerList();
|
||||
+ // CraftBukkit start
|
||||
+ List<ServerPlayer> players = playerlist.getPlayers();
|
||||
+ if (source.getBukkitSender() instanceof org.bukkit.entity.Player) {
|
||||
+ org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender();
|
||||
+ players = players.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList());
|
||||
+ }
|
||||
+ List<ServerPlayer> list = players;
|
||||
+ // CraftBukkit end
|
||||
+ Component ichatbasecomponent = ComponentUtils.formatList(list, nameExtractor);
|
||||
|
||||
commandsourcestack.sendSuccess(() -> {
|
||||
return Component.translatable("commands.list.players", list.size(), playerlist.getMaxPlayers(), component);
|
|
@ -0,0 +1,14 @@
|
|||
--- a/net/minecraft/server/commands/LootCommand.java
|
||||
+++ b/net/minecraft/server/commands/LootCommand.java
|
||||
@@ -248,8 +247,9 @@
|
||||
private static int dropInWorld(CommandSourceStack commandsourcestack, Vec3 vec3, List<ItemStack> list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException {
|
||||
ServerLevel serverlevel = commandsourcestack.getLevel();
|
||||
|
||||
- list.forEach((itemstack) -> {
|
||||
- ItemEntity itementity = new ItemEntity(serverlevel, vec3.x, vec3.y, vec3.z, itemstack.copy());
|
||||
+ items.removeIf(ItemStack::isEmpty); // CraftBukkit - SPIGOT-6959 Remove empty items for avoid throw an error in new EntityItem
|
||||
+ items.forEach((itemstack) -> {
|
||||
+ ItemEntity entityitem = new ItemEntity(worldserver, pos.x, pos.y, pos.z, itemstack.copy());
|
||||
|
||||
itementity.setDefaultPickUpDelay();
|
||||
serverlevel.addFreshEntity(itementity);
|
|
@ -0,0 +1,16 @@
|
|||
--- a/net/minecraft/server/commands/PlaceCommand.java
|
||||
+++ b/net/minecraft/server/commands/PlaceCommand.java
|
||||
@@ -131,9 +130,10 @@
|
||||
if (!structurestart.isValid()) {
|
||||
throw PlaceCommand.ERROR_STRUCTURE_FAILED.create();
|
||||
} else {
|
||||
- BoundingBox boundingbox = structurestart.getBoundingBox();
|
||||
- ChunkPos chunkpos = new ChunkPos(SectionPos.blockToSectionCoord(boundingbox.minX()), SectionPos.blockToSectionCoord(boundingbox.minZ()));
|
||||
- ChunkPos chunkpos1 = new ChunkPos(SectionPos.blockToSectionCoord(boundingbox.maxX()), SectionPos.blockToSectionCoord(boundingbox.maxZ()));
|
||||
+ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause
|
||||
+ BoundingBox structureboundingbox = structurestart.getBoundingBox();
|
||||
+ ChunkPos chunkcoordintpair = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.minX()), SectionPos.blockToSectionCoord(structureboundingbox.minZ()));
|
||||
+ ChunkPos chunkcoordintpair1 = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.maxX()), SectionPos.blockToSectionCoord(structureboundingbox.maxZ()));
|
||||
|
||||
checkLoaded(serverlevel, chunkpos, chunkpos1);
|
||||
ChunkPos.rangeClosed(chunkpos, chunkpos1).forEach((chunkpos2) -> {
|
|
@ -0,0 +1,25 @@
|
|||
--- a/net/minecraft/server/commands/ReloadCommand.java
|
||||
+++ b/net/minecraft/server/commands/ReloadCommand.java
|
||||
@@ -45,9 +44,19 @@
|
||||
return collection1;
|
||||
}
|
||||
|
||||
- public static void register(CommandDispatcher<CommandSourceStack> commanddispatcher) {
|
||||
- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("reload").requires((commandsourcestack) -> {
|
||||
- return commandsourcestack.hasPermission(2);
|
||||
+ // CraftBukkit start
|
||||
+ public static void reload(MinecraftServer minecraftserver) {
|
||||
+ PackRepository resourcepackrepository = minecraftserver.getPackRepository();
|
||||
+ WorldData savedata = minecraftserver.getWorldData();
|
||||
+ Collection<String> collection = resourcepackrepository.getSelectedIds();
|
||||
+ Collection<String> collection1 = discoverNewPacks(resourcepackrepository, savedata, collection);
|
||||
+ minecraftserver.reloadResources(collection1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
+ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("reload").requires((commandlistenerwrapper) -> {
|
||||
+ return commandlistenerwrapper.hasPermission(2);
|
||||
})).executes((commandcontext) -> {
|
||||
CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource();
|
||||
MinecraftServer minecraftserver = commandsourcestack.getServer();
|
|
@ -0,0 +1,15 @@
|
|||
--- a/net/minecraft/server/commands/ScheduleCommand.java
|
||||
+++ b/net/minecraft/server/commands/ScheduleCommand.java
|
||||
@@ -55,9 +53,9 @@
|
||||
if (i == 0) {
|
||||
throw ScheduleCommand.ERROR_SAME_TICK.create();
|
||||
} else {
|
||||
- long j = commandsourcestack.getLevel().getGameTime() + (long) i;
|
||||
- ResourceLocation resourcelocation = (ResourceLocation) pair.getFirst();
|
||||
- TimerQueue<MinecraftServer> timerqueue = commandsourcestack.getServer().getWorldData().overworldData().getScheduledEvents();
|
||||
+ long j = source.getLevel().getGameTime() + (long) time;
|
||||
+ ResourceLocation minecraftkey = (ResourceLocation) function.getFirst();
|
||||
+ TimerQueue<MinecraftServer> customfunctioncallbacktimerqueue = source.getLevel().serverLevelData.overworldData().getScheduledEvents(); // CraftBukkit - SPIGOT-6667: Use world specific function timer
|
||||
|
||||
((Either) pair.getSecond()).ifLeft((commandfunction) -> {
|
||||
String s = resourcelocation.toString();
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/server/commands/SetSpawnCommand.java
|
||||
+++ b/net/minecraft/server/commands/SetSpawnCommand.java
|
||||
@@ -42,7 +41,7 @@
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
|
||||
- serverplayer.setRespawnPosition(resourcekey, blockpos, f, true, false);
|
||||
+ entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit
|
||||
}
|
||||
|
||||
String s = resourcekey.location().toString();
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/server/commands/SpreadPlayersCommand.java
|
||||
+++ b/net/minecraft/server/commands/SpreadPlayersCommand.java
|
||||
@@ -204,7 +203,7 @@
|
||||
spreadplayerscommand_position = aspreadplayerscommand_position[j++];
|
||||
}
|
||||
|
||||
- entity.teleportTo(serverlevel, (double) Mth.floor(spreadplayerscommand_position.x) + 0.5D, (double) spreadplayerscommand_position.getSpawnY(serverlevel, i), (double) Mth.floor(spreadplayerscommand_position.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot());
|
||||
+ entity.teleportTo(level, (double) Mth.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(level, maxHeight), (double) Mth.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND); // CraftBukkit - handle teleport reason
|
||||
d1 = Double.MAX_VALUE;
|
||||
SpreadPlayersCommand.Position[] aspreadplayerscommand_position1 = aspreadplayerscommand_position;
|
||||
int k = aspreadplayerscommand_position.length;
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/server/commands/SummonCommand.java
|
||||
+++ b/net/minecraft/server/commands/SummonCommand.java
|
||||
@@ -68,7 +67,7 @@
|
||||
((Mob) entity).finalizeSpawn(commandsourcestack.getLevel(), commandsourcestack.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null, (CompoundTag) null);
|
||||
}
|
||||
|
||||
- if (!serverlevel.tryAddFreshEntityWithPassengers(entity)) {
|
||||
+ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND"
|
||||
throw SummonCommand.ERROR_DUPLICATE_UUID.create();
|
||||
} else {
|
||||
return entity;
|
|
@ -0,0 +1,53 @@
|
|||
--- a/net/minecraft/server/commands/TeleportCommand.java
|
||||
+++ b/net/minecraft/server/commands/TeleportCommand.java
|
||||
@@ -33,6 +32,12 @@
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.event.entity.EntityTeleportEvent;
|
||||
+import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class TeleportCommand {
|
||||
|
||||
@@ -156,11 +161,34 @@
|
||||
float f2 = Mth.wrapDegrees(f);
|
||||
float f3 = Mth.wrapDegrees(f1);
|
||||
|
||||
- if (entity.teleportTo(serverlevel, d0, d1, d2, set, f2, f3)) {
|
||||
- if (teleportcommand_lookat != null) {
|
||||
- teleportcommand_lookat.perform(commandsourcestack, entity);
|
||||
+ // CraftBukkit start - Teleport event
|
||||
+ boolean result;
|
||||
+ if (entity instanceof ServerPlayer player) {
|
||||
+ result = player.teleportTo(level, x, d1, y, set, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND);
|
||||
+ } else {
|
||||
+ Location to = new Location(level.getWorld(), x, d1, y, f2, f3);
|
||||
+ EntityTeleportEvent event = new EntityTeleportEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), to);
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
}
|
||||
|
||||
+ x = to.getX();
|
||||
+ d1 = to.getY();
|
||||
+ y = to.getZ();
|
||||
+ f2 = to.getYaw();
|
||||
+ f3 = to.getPitch();
|
||||
+ level = ((CraftWorld) to.getWorld()).getHandle();
|
||||
+
|
||||
+ result = entity.teleportTo(level, x, d1, y, set, f2, f3);
|
||||
+ }
|
||||
+
|
||||
+ if (result) {
|
||||
+ // CraftBukkit end
|
||||
+ if (relativeList != null) {
|
||||
+ relativeList.perform(source, entity);
|
||||
+ }
|
||||
+
|
||||
label23:
|
||||
{
|
||||
if (entity instanceof LivingEntity) {
|
|
@ -0,0 +1,59 @@
|
|||
--- a/net/minecraft/server/commands/TimeCommand.java
|
||||
+++ b/net/minecraft/server/commands/TimeCommand.java
|
||||
@@ -9,6 +8,10 @@
|
||||
import net.minecraft.commands.arguments.TimeArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.event.world.TimeSkipEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class TimeCommand {
|
||||
|
||||
@@ -49,13 +52,19 @@
|
||||
return i;
|
||||
}
|
||||
|
||||
- public static int setTime(CommandSourceStack commandsourcestack, int i) {
|
||||
- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator();
|
||||
+ public static int setTime(CommandSourceStack source, int time) {
|
||||
+ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ServerLevel serverlevel = (ServerLevel) iterator.next();
|
||||
|
||||
- serverlevel.setDayTime((long) i);
|
||||
+ // CraftBukkit start
|
||||
+ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, time - worldserver.getDayTime());
|
||||
+ Bukkit.getPluginManager().callEvent(event);
|
||||
+ if (!event.isCancelled()) {
|
||||
+ worldserver.setDayTime((long) worldserver.getDayTime() + event.getSkipAmount());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
commandsourcestack.sendSuccess(() -> {
|
||||
@@ -64,13 +73,19 @@
|
||||
return getDayTime(commandsourcestack.getLevel());
|
||||
}
|
||||
|
||||
- public static int addTime(CommandSourceStack commandsourcestack, int i) {
|
||||
- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator();
|
||||
+ public static int addTime(CommandSourceStack source, int amount) {
|
||||
+ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ServerLevel serverlevel = (ServerLevel) iterator.next();
|
||||
|
||||
- serverlevel.setDayTime(serverlevel.getDayTime() + (long) i);
|
||||
+ // CraftBukkit start
|
||||
+ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, amount);
|
||||
+ Bukkit.getPluginManager().callEvent(event);
|
||||
+ if (!event.isCancelled()) {
|
||||
+ worldserver.setDayTime(worldserver.getDayTime() + event.getSkipAmount());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
int j = getDayTime(commandsourcestack.getLevel());
|
|
@ -0,0 +1,79 @@
|
|||
--- a/net/minecraft/server/commands/WorldBorderCommand.java
|
||||
+++ b/net/minecraft/server/commands/WorldBorderCommand.java
|
||||
@@ -57,8 +56,8 @@
|
||||
})))));
|
||||
}
|
||||
|
||||
- private static int setDamageBuffer(CommandSourceStack commandsourcestack, float f) throws CommandSyntaxException {
|
||||
- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder();
|
||||
+ private static int setDamageBuffer(CommandSourceStack source, float distance) throws CommandSyntaxException {
|
||||
+ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit
|
||||
|
||||
if (worldborder.getDamageSafeZone() == (double) f) {
|
||||
throw WorldBorderCommand.ERROR_SAME_DAMAGE_BUFFER.create();
|
||||
@@ -71,8 +70,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static int setDamageAmount(CommandSourceStack commandsourcestack, float f) throws CommandSyntaxException {
|
||||
- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder();
|
||||
+ private static int setDamageAmount(CommandSourceStack source, float damagePerBlock) throws CommandSyntaxException {
|
||||
+ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit
|
||||
|
||||
if (worldborder.getDamagePerBlock() == (double) f) {
|
||||
throw WorldBorderCommand.ERROR_SAME_DAMAGE_AMOUNT.create();
|
||||
@@ -85,8 +84,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static int setWarningTime(CommandSourceStack commandsourcestack, int i) throws CommandSyntaxException {
|
||||
- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder();
|
||||
+ private static int setWarningTime(CommandSourceStack source, int time) throws CommandSyntaxException {
|
||||
+ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit
|
||||
|
||||
if (worldborder.getWarningTime() == i) {
|
||||
throw WorldBorderCommand.ERROR_SAME_WARNING_TIME.create();
|
||||
@@ -99,8 +98,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static int setWarningDistance(CommandSourceStack commandsourcestack, int i) throws CommandSyntaxException {
|
||||
- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder();
|
||||
+ private static int setWarningDistance(CommandSourceStack source, int distance) throws CommandSyntaxException {
|
||||
+ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit
|
||||
|
||||
if (worldborder.getWarningBlocks() == i) {
|
||||
throw WorldBorderCommand.ERROR_SAME_WARNING_DISTANCE.create();
|
||||
@@ -113,8 +112,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static int getSize(CommandSourceStack commandsourcestack) {
|
||||
- double d0 = commandsourcestack.getServer().overworld().getWorldBorder().getSize();
|
||||
+ private static int getSize(CommandSourceStack source) {
|
||||
+ double d0 = source.getLevel().getWorldBorder().getSize(); // CraftBukkit
|
||||
|
||||
commandsourcestack.sendSuccess(() -> {
|
||||
return Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", d0));
|
||||
@@ -122,8 +121,8 @@
|
||||
return Mth.floor(d0 + 0.5D);
|
||||
}
|
||||
|
||||
- private static int setCenter(CommandSourceStack commandsourcestack, Vec2 vec2) throws CommandSyntaxException {
|
||||
- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder();
|
||||
+ private static int setCenter(CommandSourceStack source, Vec2 pos) throws CommandSyntaxException {
|
||||
+ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit
|
||||
|
||||
if (worldborder.getCenterX() == (double) vec2.x && worldborder.getCenterZ() == (double) vec2.y) {
|
||||
throw WorldBorderCommand.ERROR_SAME_CENTER.create();
|
||||
@@ -138,8 +137,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static int setSize(CommandSourceStack commandsourcestack, double d0, long i) throws CommandSyntaxException {
|
||||
- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder();
|
||||
+ private static int setSize(CommandSourceStack source, double newSize, long i) throws CommandSyntaxException {
|
||||
+ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit
|
||||
double d1 = worldborder.getSize();
|
||||
|
||||
if (d1 == d0) {
|
|
@ -0,0 +1,250 @@
|
|||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -53,6 +52,16 @@
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.server.WorldLoader;
|
||||
+import org.apache.logging.log4j.Level;
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.io.IoBuilder;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.event.server.ServerCommandEvent;
|
||||
+import org.bukkit.event.server.RemoteServerCommandEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class DedicatedServer extends MinecraftServer implements ServerInterface {
|
||||
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -61,7 +70,7 @@
|
||||
private final List<ConsoleInput> consoleInput = Collections.synchronizedList(Lists.newArrayList());
|
||||
@Nullable
|
||||
private QueryThreadGs4 queryThreadGs4;
|
||||
- private final RconConsoleSource rconConsoleSource;
|
||||
+ // private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field
|
||||
@Nullable
|
||||
private RconThread rconThread;
|
||||
private final DedicatedServerSettings settings;
|
||||
@@ -70,10 +79,12 @@
|
||||
@Nullable
|
||||
private final TextFilterClient textFilterClient;
|
||||
|
||||
- public DedicatedServer(Thread thread, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, PackRepository packrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory chunkprogresslistenerfactory) {
|
||||
- super(thread, levelstoragesource_levelstorageaccess, packrepository, worldstem, Proxy.NO_PROXY, datafixer, services, chunkprogresslistenerfactory);
|
||||
+ // CraftBukkit start - Signature changed
|
||||
+ public DedicatedServer(joptsimple.OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) {
|
||||
+ super(options, worldLoader, thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory);
|
||||
+ // CraftBukkit end
|
||||
this.settings = dedicatedserversettings;
|
||||
- this.rconConsoleSource = new RconConsoleSource(this);
|
||||
+ // this.rconConsoleSource = new RemoteControlCommandListener(this); // CraftBukkit - remove field
|
||||
this.textFilterClient = TextFilterClient.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig);
|
||||
}
|
||||
|
||||
@@ -83,13 +92,44 @@
|
||||
Thread thread = new Thread("Server console handler") {
|
||||
@Override
|
||||
public void run() {
|
||||
- BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.Main.useConsole) {
|
||||
+ return;
|
||||
+ }
|
||||
+ jline.console.ConsoleReader bufferedreader = reader;
|
||||
|
||||
+ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return
|
||||
+ try {
|
||||
+ System.in.available();
|
||||
+ } catch (IOException ex) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
String s;
|
||||
|
||||
try {
|
||||
- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (s = bufferedreader.readLine()) != null) {
|
||||
- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack());
|
||||
+ // CraftBukkit start - JLine disabling compatibility
|
||||
+ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) {
|
||||
+ if (org.bukkit.craftbukkit.Main.useJline) {
|
||||
+ s = bufferedreader.readLine(">", null);
|
||||
+ } else {
|
||||
+ s = bufferedreader.readLine();
|
||||
+ }
|
||||
+
|
||||
+ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null
|
||||
+ if (s == null) {
|
||||
+ try {
|
||||
+ Thread.sleep(50L);
|
||||
+ } catch (InterruptedException ex) {
|
||||
+ Thread.currentThread().interrupt();
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (s.trim().length() > 0) { // Trim to filter lines which are just spaces
|
||||
+ DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
} catch (IOException ioexception) {
|
||||
DedicatedServer.LOGGER.error("Exception handling console input", ioexception);
|
||||
@@ -98,6 +138,27 @@
|
||||
}
|
||||
};
|
||||
|
||||
+ // CraftBukkit start - TODO: handle command-line logging arguments
|
||||
+ java.util.logging.Logger global = java.util.logging.Logger.getLogger("");
|
||||
+ global.setUseParentHandlers(false);
|
||||
+ for (java.util.logging.Handler handler : global.getHandlers()) {
|
||||
+ global.removeHandler(handler);
|
||||
+ }
|
||||
+ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler());
|
||||
+
|
||||
+ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger());
|
||||
+ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) {
|
||||
+ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) {
|
||||
+ logger.removeAppender(appender);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start();
|
||||
+
|
||||
+ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream());
|
||||
+ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream());
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
thread.setDaemon(true);
|
||||
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER));
|
||||
thread.start();
|
||||
@@ -122,7 +183,7 @@
|
||||
this.setMotd(dedicatedserverproperties.motd);
|
||||
super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get());
|
||||
this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist);
|
||||
- this.worldData.setGameType(dedicatedserverproperties.gamemode);
|
||||
+ // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading
|
||||
DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode);
|
||||
InetAddress inetaddress = null;
|
||||
|
||||
@@ -146,6 +207,12 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
|
||||
+ server.loadPlugins();
|
||||
+ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP);
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (!this.usesAuthentication()) {
|
||||
DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
|
||||
DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
|
||||
@@ -160,13 +227,13 @@
|
||||
if (!OldUsersConverter.serverReadyAfterUserconversion(this)) {
|
||||
return false;
|
||||
} else {
|
||||
- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
|
||||
+ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up
|
||||
long i = Util.getNanos();
|
||||
|
||||
SkullBlockEntity.setup(this.services, this);
|
||||
GameProfileCache.setUsesAuthentication(this.usesAuthentication());
|
||||
DedicatedServer.LOGGER.info("Preparing level \"{}\"", this.getLevelIdName());
|
||||
- this.loadLevel();
|
||||
+ this.loadLevel(storageSource.getLevelId()); // CraftBukkit
|
||||
long j = Util.getNanos() - i;
|
||||
String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D);
|
||||
|
||||
@@ -307,6 +365,7 @@
|
||||
this.queryThreadGs4.stop();
|
||||
}
|
||||
|
||||
+ System.exit(0); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,7 +387,15 @@
|
||||
while (!this.consoleInput.isEmpty()) {
|
||||
ConsoleInput consoleinput = (ConsoleInput) this.consoleInput.remove(0);
|
||||
|
||||
- this.getCommands().performPrefixedCommand(consoleinput.source, consoleinput.msg);
|
||||
+ // CraftBukkit start - ServerCommand for preprocessing
|
||||
+ ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg);
|
||||
+ server.getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) continue;
|
||||
+ servercommand = new ConsoleInput(event.getCommand(), servercommand.source);
|
||||
+
|
||||
+ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand
|
||||
+ server.dispatchServerCommand(console, servercommand);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
}
|
||||
@@ -582,17 +622,45 @@
|
||||
@Override
|
||||
@Override
|
||||
public String getPluginNames() {
|
||||
- return "";
|
||||
+ // CraftBukkit start - Whole method
|
||||
+ StringBuilder result = new StringBuilder();
|
||||
+ org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins();
|
||||
+
|
||||
+ result.append(server.getName());
|
||||
+ result.append(" on Bukkit ");
|
||||
+ result.append(server.getBukkitVersion());
|
||||
+
|
||||
+ if (plugins.length > 0 && server.getQueryPlugins()) {
|
||||
+ result.append(": ");
|
||||
+
|
||||
+ for (int i = 0; i < plugins.length; i++) {
|
||||
+ if (i > 0) {
|
||||
+ result.append("; ");
|
||||
+ }
|
||||
+
|
||||
+ result.append(plugins[i].getDescription().getName());
|
||||
+ result.append(" ");
|
||||
+ result.append(plugins[i].getDescription().getVersion().replaceAll(";", ","));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return result.toString();
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public String runCommand(String s) {
|
||||
- this.rconConsoleSource.prepareForCommand();
|
||||
+ public String runCommand(String command) {
|
||||
+ // CraftBukkit start - fire RemoteServerCommandEvent
|
||||
+ throw new UnsupportedOperationException("Not supported - remote source required.");
|
||||
+ }
|
||||
+
|
||||
+ public String runCommand(RconConsoleSource rconConsoleSource, String s) {
|
||||
+ rconConsoleSource.prepareForCommand();
|
||||
this.executeBlocking(() -> {
|
||||
this.getCommands().performPrefixedCommand(this.rconConsoleSource.createCommandSourceStack(), s);
|
||||
});
|
||||
- return this.rconConsoleSource.getCommandResponse();
|
||||
+ return rconConsoleSource.getCommandResponse();
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public void storeUsingWhiteList(boolean flag) {
|
||||
@@ -651,4 +718,15 @@
|
||||
public Optional<MinecraftServer.ServerResourcePackInfo> getServerResourcePack() {
|
||||
return this.settings.getProperties().serverResourcePackInfo;
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public boolean isDebugging() {
|
||||
+ return this.getProperties().debug;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CommandSender getBukkitSender(CommandSourceStack wrapper) {
|
||||
+ return console;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
@@ -44,11 +44,16 @@
|
||||
import net.minecraft.world.level.levelgen.presets.WorldPresets;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import joptsimple.OptionSet;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class DedicatedServerProperties extends Settings<DedicatedServerProperties> {
|
||||
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$");
|
||||
private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults();
|
||||
+ public final boolean debug = this.get("debug", false); // CraftBukkit
|
||||
public final boolean onlineMode = this.get("online-mode", true);
|
||||
public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false);
|
||||
public final String serverIp = this.get("server-ip", "");
|
||||
@@ -103,8 +108,10 @@
|
||||
private final DedicatedServerProperties.WorldDimensionData worldDimensionData;
|
||||
public final WorldOptions worldOptions;
|
||||
|
||||
- public DedicatedServerProperties(Properties properties) {
|
||||
- super(properties);
|
||||
+ // CraftBukkit start
|
||||
+ public DedicatedServerProperties(Properties properties, OptionSet optionset) {
|
||||
+ super(properties, optionset);
|
||||
+ // CraftBukkit end
|
||||
this.difficulty = (Difficulty) this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY);
|
||||
this.gamemode = (GameType) this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL);
|
||||
this.levelName = this.get("level-name", "world");
|
||||
@@ -161,14 +168,15 @@
|
||||
this.initialDataPackConfiguration = getDatapackConfig(this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())), this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled())));
|
||||
}
|
||||
|
||||
- public static DedicatedServerProperties fromFile(Path path) {
|
||||
- return new DedicatedServerProperties(loadFromFile(path));
|
||||
+ // CraftBukkit start
|
||||
+ public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) {
|
||||
+ return new DedicatedServerProperties(loadFromFile(path), optionset);
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- protected DedicatedServerProperties reload(RegistryAccess registryaccess, Properties properties) {
|
||||
- return new DedicatedServerProperties(properties);
|
||||
+ protected DedicatedServerProperties reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset) {
|
||||
+ return new DedicatedServerProperties(properties, optionset);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Nullable
|
|
@ -0,0 +1,27 @@
|
|||
--- a/net/minecraft/server/dedicated/DedicatedServerSettings.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServerSettings.java
|
||||
@@ -3,14 +3,21 @@
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.io.File;
|
||||
+import joptsimple.OptionSet;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class DedicatedServerSettings {
|
||||
|
||||
private final Path source;
|
||||
private DedicatedServerProperties properties;
|
||||
|
||||
- public DedicatedServerSettings(Path path) {
|
||||
- this.source = path;
|
||||
- this.properties = DedicatedServerProperties.fromFile(path);
|
||||
+ // CraftBukkit start
|
||||
+ public DedicatedServerSettings(OptionSet optionset) {
|
||||
+ this.source = ((File) optionset.valueOf("config")).toPath();
|
||||
+ this.properties = DedicatedServerProperties.fromFile(source, optionset);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public DedicatedServerProperties getProperties() {
|
|
@ -0,0 +1,102 @@
|
|||
--- a/net/minecraft/server/dedicated/Settings.java
|
||||
+++ b/net/minecraft/server/dedicated/Settings.java
|
||||
@@ -23,17 +22,36 @@
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+import joptsimple.OptionSet; // CraftBukkit
|
||||
+import net.minecraft.core.RegistryAccess;
|
||||
+
|
||||
public abstract class Settings<T extends Settings<T>> {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- protected final Properties properties;
|
||||
+ public final Properties properties;
|
||||
+ // CraftBukkit start
|
||||
+ private OptionSet options = null;
|
||||
|
||||
public Settings(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
+ private String getOverride(String name, String value) {
|
||||
+ if ((this.options != null) && (this.options.has(name))) {
|
||||
+ return String.valueOf(this.options.valueOf(name));
|
||||
+ }
|
||||
+
|
||||
+ return value;
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
public static Properties loadFromFile(Path path) {
|
||||
try {
|
||||
+ // CraftBukkit start - SPIGOT-7465, MC-264979: Don't load if file doesn't exist
|
||||
+ if (!path.toFile().exists()) {
|
||||
+ return new Properties();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Properties properties;
|
||||
Properties properties1;
|
||||
|
||||
@@ -97,6 +117,11 @@
|
||||
|
||||
public void store(Path path) {
|
||||
try {
|
||||
+ // CraftBukkit start - Don't attempt writing to file if it's read only
|
||||
+ if (path.toFile().exists() && !path.toFile().canWrite()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8);
|
||||
|
||||
try {
|
||||
@@ -143,8 +168,8 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- private String getStringRaw(String s) {
|
||||
- return (String) this.properties.get(s);
|
||||
+ private String getStringRaw(String key) {
|
||||
+ return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -159,7 +184,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
- protected <V> V get(String s, Function<String, V> function, Function<V, String> function1, V v0) {
|
||||
+ protected <V> V get(String key, Function<String, V> mapper, Function<V, String> toString, V value) {
|
||||
+ // CraftBukkit start
|
||||
+ try {
|
||||
+ return get0(key, mapper, toString, value);
|
||||
+ } catch (Exception ex) {
|
||||
+ throw new RuntimeException("Could not load invalidly configured property '" + key + "'", ex);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private <V> V get0(String s, Function<String, V> function, Function<V, String> function1, V v0) {
|
||||
+ // CraftBukkit end
|
||||
String s1 = this.getStringRaw(s);
|
||||
V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0);
|
||||
|
||||
@@ -236,7 +271,7 @@
|
||||
return properties;
|
||||
}
|
||||
|
||||
- protected abstract T reload(RegistryAccess registryAccess, Properties properties);
|
||||
+ protected abstract T reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset); // CraftBukkit
|
||||
|
||||
public class MutableValue<V> implements Supplier<V> {
|
||||
|
||||
@@ -258,8 +292,8 @@
|
||||
public T update(RegistryAccess registryaccess, V v0) {
|
||||
Properties properties = Settings.this.cloneProperties();
|
||||
|
||||
- properties.put(this.key, this.serializer.apply(v0));
|
||||
- return Settings.this.reload(registryaccess, properties);
|
||||
+ properties.put(this.key, this.serializer.apply(newValue));
|
||||
+ return Settings.this.reload(registryAccess, properties, Settings.this.options); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
--- a/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -168,7 +166,8 @@
|
||||
this.finalizers.forEach(Runnable::run);
|
||||
}
|
||||
|
||||
- public void print(JTextArea jtextarea, JScrollPane jscrollpane, String s) {
|
||||
+ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit
|
||||
+ public void print(JTextArea textArea, JScrollPane scrollPane, String line) {
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
this.print(jtextarea, jscrollpane, s);
|
||||
@@ -183,7 +182,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
- document.insertString(document.getLength(), s, (AttributeSet) null);
|
||||
+ document.insertString(document.getLength(), ANSI.matcher(line).replaceAll(""), (AttributeSet) null); // CraftBukkit
|
||||
} catch (BadLocationException badlocationexception) {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
--- a/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -36,6 +36,10 @@
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ChunkHolder {
|
||||
|
||||
public static final Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> UNLOADED_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED);
|
||||
@@ -90,9 +94,23 @@
|
||||
this.changedBlocksPerSection = new ShortSet[levelheightaccessor.getSectionsCount()];
|
||||
}
|
||||
|
||||
- public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getFutureIfPresentUnchecked(ChunkStatus chunkstatus) {
|
||||
- CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = (CompletableFuture) this.futures.get(chunkstatus.getIndex());
|
||||
+ // CraftBukkit start
|
||||
+ public LevelChunk getFullChunkNow() {
|
||||
+ // Note: We use the oldTicketLevel for isLoaded checks.
|
||||
+ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null;
|
||||
+ return this.getFullChunkNowUnchecked();
|
||||
+ }
|
||||
|
||||
+ public LevelChunk getFullChunkNowUnchecked() {
|
||||
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.Failure>> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL);
|
||||
+ Either<ChunkAccess, ChunkHolder.Failure> either = (Either<ChunkAccess, ChunkHolder.Failure>) statusFuture.getNow(null);
|
||||
+ return (either == null) ? null : (LevelChunk) either.left().orElse(null);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public CompletableFuture<Either<ChunkAccess, ChunkHolder.Failure>> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) {
|
||||
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.Failure>> completablefuture = (CompletableFuture) this.futures.get(chunkStatus.getIndex());
|
||||
+
|
||||
return completablefuture == null ? ChunkHolder.UNLOADED_CHUNK_FUTURE : completablefuture;
|
||||
}
|
||||
|
||||
@@ -179,6 +197,7 @@
|
||||
if (levelchunk != null) {
|
||||
int i = this.levelHeightAccessor.getSectionIndex(blockpos.getY());
|
||||
|
||||
+ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
||||
if (this.changedBlocksPerSection[i] == null) {
|
||||
this.hasChangedSections = true;
|
||||
this.changedBlocksPerSection[i] = new ShortOpenHashSet();
|
||||
@@ -256,9 +275,12 @@
|
||||
LevelChunkSection levelchunksection = levelchunk.getSection(i);
|
||||
ClientboundSectionBlocksUpdatePacket clientboundsectionblocksupdatepacket = new ClientboundSectionBlocksUpdatePacket(sectionpos, shortset, levelchunksection);
|
||||
|
||||
- this.broadcast(list, clientboundsectionblocksupdatepacket);
|
||||
- clientboundsectionblocksupdatepacket.runUpdates((blockpos1, blockstate1) -> {
|
||||
- this.broadcastBlockEntityIfNeeded(list, level, blockpos1, blockstate1);
|
||||
+ this.broadcast(list, packetplayoutmultiblockchange);
|
||||
+ // CraftBukkit start
|
||||
+ List finalList = list;
|
||||
+ packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> {
|
||||
+ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1);
|
||||
+ // CraftBukkit end
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -411,7 +433,31 @@
|
||||
boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel);
|
||||
FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel);
|
||||
FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel);
|
||||
+ // CraftBukkit start
|
||||
+ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
||||
+ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) {
|
||||
+ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
+ LevelChunk chunk = (LevelChunk)either.left().orElse(null);
|
||||
+ if (chunk != null) {
|
||||
+ chunkMap.callbackExecutor.execute(() -> {
|
||||
+ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick
|
||||
+ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag.
|
||||
+ // These actions may however happen deferred, so we manually set the needsSaving flag already here.
|
||||
+ chunk.setUnsaved(true);
|
||||
+ chunk.unloadCallback();
|
||||
+ });
|
||||
+ }
|
||||
+ }).exceptionally((throwable) -> {
|
||||
+ // ensure exceptions are printed, by default this is not the case
|
||||
+ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + ChunkHolder.this.pos, throwable);
|
||||
+ return null;
|
||||
+ });
|
||||
|
||||
+ // Run callback right away if the future was already done
|
||||
+ chunkMap.callbackExecutor.run();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (flag) {
|
||||
Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = Either.right(new ChunkHolder.ChunkLoadingFailure() {
|
||||
@Override
|
||||
@@ -482,6 +527,26 @@
|
||||
|
||||
this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel);
|
||||
this.oldTicketLevel = this.ticketLevel;
|
||||
+ // CraftBukkit start
|
||||
+ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins.
|
||||
+ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) {
|
||||
+ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
+ LevelChunk chunk = (LevelChunk)either.left().orElse(null);
|
||||
+ if (chunk != null) {
|
||||
+ chunkMap.callbackExecutor.execute(() -> {
|
||||
+ chunk.loadCallback();
|
||||
+ });
|
||||
+ }
|
||||
+ }).exceptionally((throwable) -> {
|
||||
+ // ensure exceptions are printed, by default this is not the case
|
||||
+ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + ChunkHolder.this.pos, throwable);
|
||||
+ return null;
|
||||
+ });
|
||||
+
|
||||
+ // Run callback right away if the future was already done
|
||||
+ chunkMap.callbackExecutor.run();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public boolean wasAccessibleSinceLastSave() {
|
|
@ -0,0 +1,147 @@
|
|||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -100,6 +100,9 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.slf4j.Logger;
|
||||
+import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
|
||||
+import org.bukkit.entity.Player;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider {
|
||||
|
||||
@@ -143,8 +146,29 @@
|
||||
private final Queue<Runnable> unloadQueue;
|
||||
private int serverViewDistance;
|
||||
|
||||
- public ChunkMap(ServerLevel serverlevel, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, StructureTemplateManager structuretemplatemanager, Executor executor, BlockableEventLoop<Runnable> blockableeventloop, LightChunkGetter lightchunkgetter, ChunkGenerator chunkgenerator, ChunkProgressListener chunkprogresslistener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier<DimensionDataStorage> supplier, int i, boolean flag) {
|
||||
- super(levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()).resolve("region"), datafixer, flag);
|
||||
+ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
|
||||
+ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
|
||||
+ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
|
||||
+
|
||||
+ private final java.util.Queue<Runnable> queue = new java.util.ArrayDeque<>();
|
||||
+
|
||||
+ @Override
|
||||
+ public void execute(Runnable runnable) {
|
||||
+ queue.add(runnable);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ Runnable task;
|
||||
+ while ((task = queue.poll()) != null) {
|
||||
+ task.run();
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public ChunkMap(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter lightChunk, ChunkGenerator generator, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier<DimensionDataStorage> overworldDataStorage, int viewDistance, boolean sync) {
|
||||
+ super(levelStorageAccess.getDimensionPath(level.dimension()).resolve("region"), fixerUpper, sync);
|
||||
this.visibleChunkMap = this.updatingChunkMap.clone();
|
||||
this.pendingUnloads = new Long2ObjectLinkedOpenHashMap();
|
||||
this.entitiesInLevel = new LongOpenHashSet();
|
||||
@@ -159,10 +183,15 @@
|
||||
Path path = levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension());
|
||||
|
||||
this.storageName = path.getFileName().toString();
|
||||
- this.level = serverlevel;
|
||||
- this.generator = chunkgenerator;
|
||||
- RegistryAccess registryaccess = serverlevel.registryAccess();
|
||||
- long j = serverlevel.getSeed();
|
||||
+ this.level = level;
|
||||
+ this.generator = generator;
|
||||
+ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random.
|
||||
+ if (generator instanceof CustomChunkGenerator) {
|
||||
+ generator = ((CustomChunkGenerator) generator).getDelegate();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ RegistryAccess iregistrycustom = level.registryAccess();
|
||||
+ long j = level.getSeed();
|
||||
|
||||
if (chunkgenerator instanceof NoiseBasedChunkGenerator) {
|
||||
NoiseBasedChunkGenerator noisebasedchunkgenerator = (NoiseBasedChunkGenerator) chunkgenerator;
|
||||
@@ -335,8 +364,10 @@
|
||||
List<ChunkAccess> list3 = Lists.newArrayList();
|
||||
final int l1 = 0;
|
||||
|
||||
- for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++l1) {
|
||||
- final Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = (Either) iterator.next();
|
||||
+ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) {
|
||||
+ final int l1 = cnt;
|
||||
+ // CraftBukkit end
|
||||
+ final Either<ChunkAccess, ChunkHolder.Failure> either = (Either) iterator.next();
|
||||
|
||||
if (either == null) {
|
||||
throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a");
|
||||
@@ -749,9 +778,23 @@
|
||||
return chunkstatus1;
|
||||
}
|
||||
|
||||
- private static void postLoadProtoChunk(ServerLevel serverlevel, List<CompoundTag> list) {
|
||||
- if (!list.isEmpty()) {
|
||||
- serverlevel.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(list, serverlevel));
|
||||
+ private static void postLoadProtoChunk(ServerLevel level, List<CompoundTag> tags) {
|
||||
+ if (!tags.isEmpty()) {
|
||||
+ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
|
||||
+ level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level).filter((entity) -> {
|
||||
+ boolean needsRemoval = false;
|
||||
+ net.minecraft.server.dedicated.DedicatedServer server = level.getCraftServer().getServer();
|
||||
+ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) {
|
||||
+ entity.discard();
|
||||
+ needsRemoval = true;
|
||||
+ }
|
||||
+ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) {
|
||||
+ entity.discard();
|
||||
+ needsRemoval = true;
|
||||
+ }
|
||||
+ return !needsRemoval;
|
||||
+ }));
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1047,14 +1091,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos chunkpos) {
|
||||
- return this.read(chunkpos).thenApplyAsync((optional) -> {
|
||||
- return optional.map(this::upgradeChunkTag);
|
||||
+ private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos pos) {
|
||||
+ return this.read(pos).thenApplyAsync((optional) -> {
|
||||
+ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, pos)); // CraftBukkit
|
||||
}, Util.backgroundExecutor());
|
||||
}
|
||||
|
||||
- private CompoundTag upgradeChunkTag(CompoundTag compoundtag) {
|
||||
- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, compoundtag, this.generator.getTypeNameForDataFixer());
|
||||
+ // CraftBukkit start
|
||||
+ private CompoundTag upgradeChunkTag(CompoundTag nbttagcompound, ChunkPos chunkcoordintpair) {
|
||||
+ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkpos) {
|
||||
@@ -1467,7 +1509,7 @@
|
||||
private final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
||||
|
||||
public TrackedEntity(Entity entity, int i, int j, boolean flag) {
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast);
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit
|
||||
this.entity = entity;
|
||||
this.range = i;
|
||||
this.lastSectionPos = SectionPos.of((EntityAccess) entity);
|
||||
@@ -1529,6 +1569,11 @@
|
||||
double d2 = d0 * d0;
|
||||
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(serverplayer) && ChunkMap.this.isChunkTracked(serverplayer, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
||||
|
||||
+ // CraftBukkit start - respect vanish API
|
||||
+ if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {
|
||||
+ flag = false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (flag) {
|
||||
if (this.seenBy.add(serverplayer.connection)) {
|
||||
this.serverEntity.addPairing(serverplayer);
|
|
@ -0,0 +1,149 @@
|
|||
--- a/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -122,10 +122,25 @@
|
||||
}
|
||||
|
||||
if (!this.chunksToUpdateFutures.isEmpty()) {
|
||||
- this.chunksToUpdateFutures.forEach((chunkholder) -> {
|
||||
- chunkholder.updateFutures(chunkmap, this.mainThreadExecutor);
|
||||
- });
|
||||
- this.chunksToUpdateFutures.clear();
|
||||
+ // CraftBukkit start
|
||||
+ // Iterate pending chunk updates with protection against concurrent modification exceptions
|
||||
+ java.util.Iterator<ChunkHolder> iter = this.chunksToUpdateFutures.iterator();
|
||||
+ int expectedSize = this.chunksToUpdateFutures.size();
|
||||
+ do {
|
||||
+ ChunkHolder playerchunk = iter.next();
|
||||
+ iter.remove();
|
||||
+ expectedSize--;
|
||||
+
|
||||
+ playerchunk.updateFutures(chunkManager, this.mainThreadExecutor);
|
||||
+
|
||||
+ // Reset iterator if set was modified using add()
|
||||
+ if (this.chunksToUpdateFutures.size() != expectedSize) {
|
||||
+ expectedSize = this.chunksToUpdateFutures.size();
|
||||
+ iter = this.chunksToUpdateFutures.iterator();
|
||||
+ }
|
||||
+ } while (iter.hasNext());
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
return true;
|
||||
} else {
|
||||
if (!this.ticketsToRelease.isEmpty()) {
|
||||
@@ -161,30 +176,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
- void addTicket(long i, Ticket<?> ticket) {
|
||||
- SortedArraySet<Ticket<?>> sortedarrayset = this.getTickets(i);
|
||||
- int j = getTicketLevelAt(sortedarrayset);
|
||||
- Ticket<?> ticket1 = (Ticket) sortedarrayset.addOrGet(ticket);
|
||||
+ boolean addTicket(long i, Ticket<?> ticket) { // CraftBukkit - void -> boolean
|
||||
+ SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(i);
|
||||
+ int j = getTicketLevelAt(arraysetsorted);
|
||||
+ Ticket<?> ticket1 = (Ticket) arraysetsorted.addOrGet(ticket);
|
||||
|
||||
ticket1.setCreatedTick(this.ticketTickCounter);
|
||||
if (ticket.getTicketLevel() < j) {
|
||||
this.ticketTracker.update(i, ticket.getTicketLevel(), true);
|
||||
}
|
||||
|
||||
+ return ticket == ticket1; // CraftBukkit
|
||||
}
|
||||
|
||||
- void removeTicket(long i, Ticket<?> ticket) {
|
||||
- SortedArraySet<Ticket<?>> sortedarrayset = this.getTickets(i);
|
||||
+ boolean removeTicket(long i, Ticket<?> ticket) { // CraftBukkit - void -> boolean
|
||||
+ SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(i);
|
||||
|
||||
- if (sortedarrayset.remove(ticket)) {
|
||||
- ;
|
||||
+ boolean removed = false; // CraftBukkit
|
||||
+ if (arraysetsorted.remove(ticket)) {
|
||||
+ removed = true; // CraftBukkit
|
||||
}
|
||||
|
||||
if (sortedarrayset.isEmpty()) {
|
||||
this.tickets.remove(i);
|
||||
}
|
||||
|
||||
- this.ticketTracker.update(i, getTicketLevelAt(sortedarrayset), false);
|
||||
+ this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false);
|
||||
+ return removed; // CraftBukkit
|
||||
}
|
||||
|
||||
public <T> void addTicket(TicketType<T> tickettype, ChunkPos chunkpos, int i, T t0) {
|
||||
@@ -197,20 +215,34 @@
|
||||
this.removeTicket(chunkpos.toLong(), ticket);
|
||||
}
|
||||
|
||||
- public <T> void addRegionTicket(TicketType<T> tickettype, ChunkPos chunkpos, int i, T t0) {
|
||||
+ public <T> void addRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
|
||||
+ // CraftBukkit start
|
||||
+ addRegionTicketAtDistance(type, pos, distance, value);
|
||||
+ }
|
||||
+
|
||||
+ public <T> boolean addRegionTicketAtDistance(TicketType<T> tickettype, ChunkPos chunkcoordintpair, int i, T t0) {
|
||||
+ // CraftBukkit end
|
||||
Ticket<T> ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0);
|
||||
long j = chunkpos.toLong();
|
||||
|
||||
- this.addTicket(j, ticket);
|
||||
+ boolean added = this.addTicket(j, ticket); // CraftBukkit
|
||||
this.tickingTicketsTracker.addTicket(j, ticket);
|
||||
+ return added; // CraftBukkit
|
||||
}
|
||||
|
||||
- public <T> void removeRegionTicket(TicketType<T> tickettype, ChunkPos chunkpos, int i, T t0) {
|
||||
+ public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int distance, T value) {
|
||||
+ // CraftBukkit start
|
||||
+ removeRegionTicketAtDistance(type, pos, distance, value);
|
||||
+ }
|
||||
+
|
||||
+ public <T> boolean removeRegionTicketAtDistance(TicketType<T> tickettype, ChunkPos chunkcoordintpair, int i, T t0) {
|
||||
+ // CraftBukkit end
|
||||
Ticket<T> ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0);
|
||||
long j = chunkpos.toLong();
|
||||
|
||||
- this.removeTicket(j, ticket);
|
||||
+ boolean removed = this.removeTicket(j, ticket); // CraftBukkit
|
||||
this.tickingTicketsTracker.removeTicket(j, ticket);
|
||||
+ return removed; // CraftBukkit
|
||||
}
|
||||
|
||||
private SortedArraySet<Ticket<?>> getTickets(long i) {
|
||||
@@ -249,6 +281,7 @@
|
||||
ChunkPos chunkpos = sectionpos.chunk();
|
||||
long i = chunkpos.toLong();
|
||||
ObjectSet<ServerPlayer> objectset = (ObjectSet) this.playersPerChunk.get(i);
|
||||
+ if (objectset == null) return; // CraftBukkit - SPIGOT-6208
|
||||
|
||||
objectset.remove(serverplayer);
|
||||
if (objectset.isEmpty()) {
|
||||
@@ -378,6 +411,26 @@
|
||||
return !this.tickets.isEmpty();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public <T> void removeAllTicketsFor(TicketType<T> ticketType, int ticketLevel, T ticketIdentifier) {
|
||||
+ Ticket<T> target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier);
|
||||
+
|
||||
+ for (java.util.Iterator<Entry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
|
||||
+ Entry<SortedArraySet<Ticket<?>>> entry = iterator.next();
|
||||
+ SortedArraySet<Ticket<?>> tickets = entry.getValue();
|
||||
+ if (tickets.remove(target)) {
|
||||
+ // copied from removeTicket
|
||||
+ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(tickets), false);
|
||||
+
|
||||
+ // can't use entry after it's removed
|
||||
+ if (tickets.isEmpty()) {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
private class ChunkTicketTracker extends ChunkTracker {
|
||||
|
||||
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;
|
|
@ -0,0 +1,139 @@
|
|||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -83,6 +83,16 @@
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - properly implement isChunkLoaded
|
||||
+ public boolean isChunkLoaded(int chunkX, int chunkZ) {
|
||||
+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(ChunkPos.asLong(chunkX, chunkZ));
|
||||
+ if (chunk == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return chunk.getFullChunkNow() != null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public ThreadedLevelLightEngine getLightEngine() {
|
||||
@@ -127,10 +135,10 @@
|
||||
ChunkAccess chunkaccess;
|
||||
|
||||
for (int l = 0; l < 4; ++l) {
|
||||
- if (k == this.lastChunkPos[l] && chunkstatus == this.lastChunkStatus[l]) {
|
||||
- chunkaccess = this.lastChunk[l];
|
||||
- if (chunkaccess != null || !flag) {
|
||||
- return chunkaccess;
|
||||
+ if (k == this.lastChunkPos[l] && requiredStatus == this.lastChunkStatus[l]) {
|
||||
+ ichunkaccess = this.lastChunk[l];
|
||||
+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime
|
||||
+ return ichunkaccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,10 +238,18 @@
|
||||
int l = ChunkLevel.byStatus(chunkstatus);
|
||||
ChunkHolder chunkholder = this.getVisibleChunkIfPresent(k);
|
||||
|
||||
- if (flag) {
|
||||
- this.distanceManager.addTicket(TicketType.UNKNOWN, chunkpos, l, chunkpos);
|
||||
- if (this.chunkAbsent(chunkholder, l)) {
|
||||
- ProfilerFiller profilerfiller = this.level.getProfiler();
|
||||
+ // CraftBukkit start - don't add new ticket for currently unloading chunk
|
||||
+ boolean currentlyUnloading = false;
|
||||
+ if (playerchunk != null) {
|
||||
+ FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel);
|
||||
+ FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel());
|
||||
+ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL));
|
||||
+ }
|
||||
+ if (load && !currentlyUnloading) {
|
||||
+ // CraftBukkit end
|
||||
+ this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair);
|
||||
+ if (this.chunkAbsent(playerchunk, l)) {
|
||||
+ ProfilerFiller gameprofilerfiller = this.level.getProfiler();
|
||||
|
||||
profilerfiller.push("chunkLoad");
|
||||
this.runDistanceManagerUpdates();
|
||||
@@ -249,8 +264,8 @@
|
||||
return this.chunkAbsent(chunkholder, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : chunkholder.getOrScheduleFuture(chunkstatus, this.chunkMap);
|
||||
}
|
||||
|
||||
- private boolean chunkAbsent(@Nullable ChunkHolder chunkholder, int i) {
|
||||
- return chunkholder == null || chunkholder.getTicketLevel() > i;
|
||||
+ private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) {
|
||||
+ return chunkHolder == null || chunkHolder.oldTicketLevel > status; // CraftBukkit using oldTicketLevel for isLoaded checks
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,11 +346,31 @@
|
||||
@Override
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
- this.save(true);
|
||||
+ // CraftBukkit start
|
||||
+ close(true);
|
||||
+ }
|
||||
+
|
||||
+ public void close(boolean save) throws IOException {
|
||||
+ if (save) {
|
||||
+ this.save(true);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.lightEngine.close();
|
||||
this.chunkMap.close();
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - modelled on below
|
||||
+ public void purgeUnload() {
|
||||
+ this.level.getProfiler().push("purge");
|
||||
+ this.distanceManager.purgeStaleTickets();
|
||||
+ this.runDistanceManagerUpdates();
|
||||
+ this.level.getProfiler().popPush("unload");
|
||||
+ this.chunkMap.tick(() -> true);
|
||||
+ this.level.getProfiler().pop();
|
||||
+ this.clearCache();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public void tick(BooleanSupplier booleansupplier, boolean flag) {
|
||||
@@ -385,13 +415,13 @@
|
||||
int k = this.distanceManager.getNaturalSpawnChunkCount();
|
||||
NaturalSpawner.SpawnState naturalspawner_spawnstate = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap));
|
||||
|
||||
- this.lastSpawnState = naturalspawner_spawnstate;
|
||||
- profilerfiller.popPush("spawnAndTick");
|
||||
- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING);
|
||||
+ this.lastSpawnState = spawnercreature_d;
|
||||
+ gameprofilerfiller.popPush("spawnAndTick");
|
||||
+ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
Util.shuffle(list, this.level.random);
|
||||
int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
||||
- boolean flag1 = this.level.getLevelData().getGameTime() % 400L == 0L;
|
||||
+ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
|
||||
Iterator iterator1 = list.iterator();
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
@@ -604,7 +624,9 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected boolean pollTask() {
|
||||
+ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
|
||||
+ public boolean pollTask() {
|
||||
+ try {
|
||||
if (ServerChunkCache.this.runDistanceManagerUpdates()) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -612,6 +636,8 @@
|
||||
return super.pollTask();
|
||||
}
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
}
|
||||
|
||||
private static record ChunkAndHolder(LevelChunk chunk, ChunkHolder holder) {
|
|
@ -0,0 +1,146 @@
|
|||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -42,6 +41,13 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.server.network.ServerPlayerConnection;
|
||||
+import net.minecraft.util.Mth;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.player.PlayerVelocityEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ServerEntity {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -66,8 +72,12 @@
|
||||
private boolean wasOnGround;
|
||||
@Nullable
|
||||
private List<SynchedEntityData.DataValue<?>> trackedDataValues;
|
||||
+ // CraftBukkit start
|
||||
+ private final Set<ServerPlayerConnection> trackedPlayers;
|
||||
|
||||
- public ServerEntity(ServerLevel serverlevel, Entity entity, int i, boolean flag, Consumer<Packet<?>> consumer) {
|
||||
+ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer<Packet<?>> consumer, Set<ServerPlayerConnection> trackedPlayers) {
|
||||
+ this.trackedPlayers = trackedPlayers;
|
||||
+ // CraftBukkit end
|
||||
this.ap = Vec3.ZERO;
|
||||
this.lastPassengers = Collections.emptyList();
|
||||
this.level = serverlevel;
|
||||
@@ -87,7 +97,7 @@
|
||||
List<Entity> list = this.entity.getPassengers();
|
||||
|
||||
if (!list.equals(this.lastPassengers)) {
|
||||
- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity));
|
||||
+ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
|
||||
removedPassengers(list, this.lastPassengers).forEach((entity) -> {
|
||||
if (entity instanceof ServerPlayer) {
|
||||
ServerPlayer serverplayer = (ServerPlayer) entity;
|
||||
@@ -104,18 +114,18 @@
|
||||
if (entity instanceof ItemFrame) {
|
||||
ItemFrame itemframe = (ItemFrame) entity;
|
||||
|
||||
- if (this.tickCount % 10 == 0) {
|
||||
- ItemStack itemstack = itemframe.getItem();
|
||||
+ if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block
|
||||
+ ItemStack itemstack = entityitemframe.getItem();
|
||||
|
||||
- if (itemstack.getItem() instanceof MapItem) {
|
||||
+ if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks
|
||||
Integer integer = MapItem.getMapId(itemstack);
|
||||
MapItemSavedData mapitemsaveddata = MapItem.getSavedData(integer, this.level);
|
||||
|
||||
- if (mapitemsaveddata != null) {
|
||||
- Iterator iterator = this.level.players().iterator();
|
||||
+ if (worldmap != null) {
|
||||
+ Iterator<ServerPlayerConnection> iterator = this.trackedPlayers.iterator(); // CraftBukkit
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
- ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
+ ServerPlayer entityplayer = iterator.next().getPlayer(); // CraftBukkit
|
||||
|
||||
mapitemsaveddata.tickCarriedBy(serverplayer, itemstack);
|
||||
Packet<?> packet = mapitemsaveddata.getUpdatePacket(integer, serverplayer);
|
||||
@@ -228,7 +238,27 @@
|
||||
|
||||
++this.tickCount;
|
||||
if (this.entity.hurtMarked) {
|
||||
- this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
||||
+ // CraftBukkit start - Create PlayerVelocity event
|
||||
+ boolean cancelled = false;
|
||||
+
|
||||
+ if (this.entity instanceof ServerPlayer) {
|
||||
+ Player player = (Player) this.entity.getBukkitEntity();
|
||||
+ org.bukkit.util.Vector velocity = player.getVelocity();
|
||||
+
|
||||
+ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone());
|
||||
+ this.entity.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ cancelled = true;
|
||||
+ } else if (!velocity.equals(event.getVelocity())) {
|
||||
+ player.setVelocity(event.getVelocity());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!cancelled) {
|
||||
+ this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.entity.hurtMarked = false;
|
||||
}
|
||||
|
||||
@@ -256,7 +286,10 @@
|
||||
|
||||
public void sendPairingData(ServerPlayer serverplayer, Consumer<Packet<ClientGamePacketListener>> consumer) {
|
||||
if (this.entity.isRemoved()) {
|
||||
- ServerEntity.LOGGER.warn("Fetching packet for removed entity {}", this.entity);
|
||||
+ // CraftBukkit start - Remove useless error spam, just return
|
||||
+ // EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity);
|
||||
+ return;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
Packet<ClientGamePacketListener> packet = this.entity.getAddEntityPacket();
|
||||
@@ -272,6 +305,12 @@
|
||||
if (this.entity instanceof LivingEntity) {
|
||||
Collection<AttributeInstance> collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes();
|
||||
|
||||
+ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health
|
||||
+ if (this.entity.getId() == player.getId()) {
|
||||
+ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (!collection.isEmpty()) {
|
||||
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection));
|
||||
}
|
||||
@@ -303,8 +342,15 @@
|
||||
if (!list.isEmpty()) {
|
||||
consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list));
|
||||
}
|
||||
+ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - MC-109346: Fix for nonsensical head yaw
|
||||
+ if (this.entity instanceof ServerPlayer) {
|
||||
+ consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F)));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (!this.entity.getPassengers().isEmpty()) {
|
||||
consumer.accept(new ClientboundSetPassengersPacket(this.entity));
|
||||
}
|
||||
@@ -338,6 +384,11 @@
|
||||
Set<AttributeInstance> set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes();
|
||||
|
||||
if (!set.isEmpty()) {
|
||||
+ // CraftBukkit start - Send scaled max health
|
||||
+ if (this.entity instanceof ServerPlayer) {
|
||||
+ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set));
|
||||
}
|
||||
|
|
@ -0,0 +1,657 @@
|
|||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -163,6 +164,19 @@
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraft.world.ticks.LevelTicks;
|
||||
import org.slf4j.Logger;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.WeatherType;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.generator.CustomWorldChunkManager;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.bukkit.craftbukkit.util.WorldUUID;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
+import org.bukkit.event.server.MapInitializeEvent;
|
||||
+import org.bukkit.event.weather.LightningStrikeEvent;
|
||||
+import org.bukkit.event.world.GenericGameEvent;
|
||||
+import org.bukkit.event.world.TimeSkipEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
||||
@@ -177,7 +191,7 @@
|
||||
final List<ServerPlayer> players;
|
||||
private final ServerChunkCache chunkSource;
|
||||
private final MinecraftServer server;
|
||||
- private final ServerLevelData serverLevelData;
|
||||
+ public final PrimaryLevelData serverLevelData; // CraftBukkit - type
|
||||
final EntityTickList entityTickList;
|
||||
private final PersistentEntitySectionManager<Entity> entityManager;
|
||||
private final GameEventDispatcher gameEventDispatcher;
|
||||
@@ -202,12 +216,30 @@
|
||||
private final boolean tickTime;
|
||||
private final RandomSequences randomSequences;
|
||||
|
||||
- public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, ServerLevelData serverleveldata, ResourceKey<Level> resourcekey, LevelStem levelstem, ChunkProgressListener chunkprogresslistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences) {
|
||||
- RegistryAccess.Frozen registryaccess_frozen = minecraftserver.registryAccess();
|
||||
- Holder holder = levelstem.type();
|
||||
+ // CraftBukkit start
|
||||
+ public final LevelStorageSource.LevelStorageAccess convertable;
|
||||
+ public final UUID uuid;
|
||||
|
||||
- Objects.requireNonNull(minecraftserver);
|
||||
- super(serverleveldata, resourcekey, registryaccess_frozen, holder, minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates());
|
||||
+ public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
+ return this.chunkSource.getChunk(x, z, false);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ResourceKey<LevelStem> getTypeKey() {
|
||||
+ return convertable.dimensionType;
|
||||
+ }
|
||||
+
|
||||
+ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer
|
||||
+ public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
|
||||
+ // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error
|
||||
+ // Holder holder = worlddimension.type(); // CraftBukkit - decompile error
|
||||
+
|
||||
+ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
|
||||
+ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env);
|
||||
+ this.pvpMode = minecraftserver.isPvpAllowed();
|
||||
+ convertable = convertable_conversionsession;
|
||||
+ uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile());
|
||||
+ // CraftBukkit end
|
||||
this.players = Lists.newArrayList();
|
||||
this.entityTickList = new EntityTickList();
|
||||
this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier());
|
||||
@@ -219,8 +251,24 @@
|
||||
this.tickTime = flag1;
|
||||
this.server = minecraftserver;
|
||||
this.customSpawners = list;
|
||||
- this.serverLevelData = serverleveldata;
|
||||
- ChunkGenerator chunkgenerator = levelstem.generator();
|
||||
+ this.serverLevelData = iworlddataserver;
|
||||
+ ChunkGenerator chunkgenerator = worlddimension.generator();
|
||||
+ // CraftBukkit start
|
||||
+ serverLevelData.setWorld(this);
|
||||
+
|
||||
+ if (biomeProvider != null) {
|
||||
+ BiomeSource worldChunkManager = new CustomWorldChunkManager(getWorld(), biomeProvider, server.registryAccess().registryOrThrow(Registries.BIOME));
|
||||
+ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) {
|
||||
+ chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings);
|
||||
+ } else if (chunkgenerator instanceof FlatLevelSource cpf) {
|
||||
+ chunkgenerator = new FlatLevelSource(cpf.settings(), worldChunkManager);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (gen != null) {
|
||||
+ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
boolean flag2 = minecraftserver.forceSynchronousWrites();
|
||||
DataFixer datafixer = minecraftserver.getFixerUpper();
|
||||
EntityPersistentStorage<Entity> entitypersistentstorage = new EntityStorage(this, levelstoragesource_levelstorageaccess.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver);
|
||||
@@ -248,9 +296,9 @@
|
||||
long l = minecraftserver.getWorldData().worldGenOptions().seed();
|
||||
|
||||
this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer);
|
||||
- this.structureManager = new StructureManager(this, minecraftserver.getWorldData().worldGenOptions(), this.structureCheck);
|
||||
- if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) {
|
||||
- this.dragonFight = new EndDragonFight(this, l, minecraftserver.getWorldData().endDragonFightData());
|
||||
+ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), structureCheck); // CraftBukkit
|
||||
+ if ((this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END
|
||||
+ this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit
|
||||
} else {
|
||||
this.dragonFight = null;
|
||||
}
|
||||
@@ -260,6 +308,7 @@
|
||||
this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> {
|
||||
return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences");
|
||||
});
|
||||
+ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@@ -305,12 +353,18 @@
|
||||
long j;
|
||||
|
||||
if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) {
|
||||
+ // CraftBukkit start
|
||||
+ j = this.levelData.getDayTime() + 24000L;
|
||||
+ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime());
|
||||
if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
|
||||
j = this.levelData.getDayTime() + 24000L;
|
||||
this.setDayTime(j - j % 24000L);
|
||||
}
|
||||
|
||||
- this.wakeUpAllPlayers();
|
||||
+ if (!event.isCancelled()) {
|
||||
+ this.wakeUpAllPlayers();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) {
|
||||
this.resetWeatherCycle();
|
||||
}
|
||||
@@ -344,8 +400,8 @@
|
||||
}
|
||||
|
||||
this.handlingTick = false;
|
||||
- profilerfiller.pop();
|
||||
- boolean flag1 = !this.players.isEmpty() || !this.getForcedChunks().isEmpty();
|
||||
+ gameprofilerfiller.pop();
|
||||
+ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
|
||||
|
||||
if (flag1) {
|
||||
this.resetEmptyTime();
|
||||
@@ -361,7 +417,7 @@
|
||||
|
||||
this.entityTickList.forEach((entity) -> {
|
||||
if (!entity.isRemoved()) {
|
||||
- if (this.shouldDiscardEntity(entity)) {
|
||||
+ if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
|
||||
entity.discard();
|
||||
} else if (!tickratemanager.isEntityFrozen(entity)) {
|
||||
profilerfiller.push("checkDespawn");
|
||||
@@ -457,20 +512,20 @@
|
||||
if (flag1) {
|
||||
SkeletonHorse skeletonhorse = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this);
|
||||
|
||||
- if (skeletonhorse != null) {
|
||||
- skeletonhorse.setTrap(true);
|
||||
- skeletonhorse.setAge(0);
|
||||
- skeletonhorse.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ());
|
||||
- this.addFreshEntity(skeletonhorse);
|
||||
+ if (entityhorseskeleton != null) {
|
||||
+ entityhorseskeleton.setTrap(true);
|
||||
+ entityhorseskeleton.setAge(0);
|
||||
+ entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
|
||||
+ this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this);
|
||||
|
||||
- if (lightningbolt != null) {
|
||||
- lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos));
|
||||
- lightningbolt.setVisualOnly(flag1);
|
||||
- this.addFreshEntity(lightningbolt);
|
||||
+ if (entitylightning != null) {
|
||||
+ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition));
|
||||
+ entitylightning.setVisualOnly(flag1);
|
||||
+ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,8 +580,8 @@
|
||||
BlockPos blockpos2 = blockpos1.below();
|
||||
Biome biome = (Biome) this.getBiome(blockpos1).value();
|
||||
|
||||
- if (biome.shouldFreeze(this, blockpos2)) {
|
||||
- this.setBlockAndUpdate(blockpos2, Blocks.ICE.defaultBlockState());
|
||||
+ if (biomebase.shouldFreeze(this, blockposition2)) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition2, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
|
||||
}
|
||||
|
||||
if (this.isRaining()) {
|
||||
@@ -541,11 +596,11 @@
|
||||
if (j < Math.min(i, 8)) {
|
||||
BlockState blockstate1 = (BlockState) blockstate.setValue(SnowLayerBlock.LAYERS, j + 1);
|
||||
|
||||
- Block.pushEntitiesUp(blockstate, blockstate1, this, blockpos1);
|
||||
- this.setBlockAndUpdate(blockpos1, blockstate1);
|
||||
+ Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, iblockdata1, null); // CraftBukkit
|
||||
}
|
||||
} else {
|
||||
- this.setBlockAndUpdate(blockpos1, Blocks.SNOW.defaultBlockState());
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,6 +761,7 @@
|
||||
this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
+ /* CraftBukkit start
|
||||
if (this.oRainLevel != this.rainLevel) {
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension());
|
||||
}
|
||||
@@ -726,14 +787,41 @@
|
||||
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
|
||||
}
|
||||
|
||||
+ if (flag != this.isRaining()) {
|
||||
+ // Only send weather packets to those affected
|
||||
+ for (int idx = 0; idx < this.players.size(); ++idx) {
|
||||
+ if (((ServerPlayer) this.players.get(idx)).level() == this) {
|
||||
+ ((ServerPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ for (int idx = 0; idx < this.players.size(); ++idx) {
|
||||
+ if (((ServerPlayer) this.players.get(idx)).level() == this) {
|
||||
+ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void resetWeatherCycle() {
|
||||
- this.serverLevelData.setRainTime(0);
|
||||
+ // CraftBukkit start
|
||||
this.serverLevelData.setRaining(false);
|
||||
- this.serverLevelData.setThunderTime(0);
|
||||
+ // If we stop due to everyone sleeping we should reset the weather duration to some other random value.
|
||||
+ // Not that everyone ever manages to get the whole server to sleep at the same time....
|
||||
+ if (!this.serverLevelData.isRaining()) {
|
||||
+ this.serverLevelData.setRainTime(0);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.serverLevelData.setThundering(false);
|
||||
+ // CraftBukkit start
|
||||
+ // If we stop due to everyone sleeping we should reset the weather duration to some other random value.
|
||||
+ // Not that everyone ever manages to get the whole server to sleep at the same time....
|
||||
+ if (!this.serverLevelData.isThundering()) {
|
||||
+ this.serverLevelData.setThunderTime(0);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public void resetEmptyTime() {
|
||||
@@ -768,6 +856,7 @@
|
||||
});
|
||||
profilerfiller.incrementCounter("tickNonPassenger");
|
||||
entity.tick();
|
||||
+ entity.postTick(); // CraftBukkit
|
||||
this.getProfiler().pop();
|
||||
Iterator iterator = entity.getPassengers().iterator();
|
||||
|
||||
@@ -789,10 +878,11 @@
|
||||
profilerfiller.push(() -> {
|
||||
return BuiltInRegistries.ENTITY_TYPE.getKey(entity1.getType()).toString();
|
||||
});
|
||||
- profilerfiller.incrementCounter("tickPassenger");
|
||||
- entity1.rideTick();
|
||||
- profilerfiller.pop();
|
||||
- Iterator iterator = entity1.getPassengers().iterator();
|
||||
+ gameprofilerfiller.incrementCounter("tickPassenger");
|
||||
+ passengerEntity.rideTick();
|
||||
+ passengerEntity.postTick(); // CraftBukkit
|
||||
+ gameprofilerfiller.pop();
|
||||
+ Iterator iterator = passengerEntity.getPassengers().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Entity entity2 = (Entity) iterator.next();
|
||||
@@ -815,9 +904,10 @@
|
||||
public void save(@Nullable ProgressListener progresslistener, boolean flag, boolean flag1) {
|
||||
ServerChunkCache serverchunkcache = this.getChunkSource();
|
||||
|
||||
- if (!flag1) {
|
||||
- if (progresslistener != null) {
|
||||
- progresslistener.progressStartNoAbort(Component.translatable("menu.savingLevel"));
|
||||
+ if (!skipSave) {
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
|
||||
+ if (progress != null) {
|
||||
+ progress.progressStartNoAbort(Component.translatable("menu.savingLevel"));
|
||||
}
|
||||
|
||||
this.saveLevelData();
|
||||
@@ -833,11 +923,19 @@
|
||||
}
|
||||
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
|
||||
+ ServerLevel worldserver1 = this;
|
||||
+
|
||||
+ serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings());
|
||||
+ serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save());
|
||||
+ convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
private void saveLevelData() {
|
||||
if (this.dragonFight != null) {
|
||||
- this.server.getWorldData().setEndDragonFightData(this.dragonFight.saveData());
|
||||
+ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit
|
||||
}
|
||||
|
||||
this.getChunkSource().getDataStorage().save();
|
||||
@@ -903,19 +1000,37 @@
|
||||
@Override
|
||||
@Override
|
||||
public boolean addFreshEntity(Entity entity) {
|
||||
- return this.addEntity(entity);
|
||||
+ // CraftBukkit start
|
||||
+ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ return this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
public boolean addWithUUID(Entity entity) {
|
||||
- return this.addEntity(entity);
|
||||
+ // CraftBukkit start
|
||||
+ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
}
|
||||
|
||||
+ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ return this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
public void addDuringTeleport(Entity entity) {
|
||||
- this.addEntity(entity);
|
||||
+ // CraftBukkit start
|
||||
+ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds,
|
||||
+ // since it is only an implementation detail, that a new entity is created when
|
||||
+ // they are traveling between worlds.
|
||||
+ this.addDuringTeleport(entity, null);
|
||||
}
|
||||
|
||||
- public void addDuringCommandTeleport(ServerPlayer serverplayer) {
|
||||
- this.addPlayer(serverplayer);
|
||||
+ public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ this.addEntity(entity, reason);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public void addDuringPortalTeleport(ServerPlayer serverplayer) {
|
||||
@@ -942,24 +1061,37 @@
|
||||
this.entityManager.addNewEntity(serverplayer);
|
||||
}
|
||||
|
||||
- private boolean addEntity(Entity entity) {
|
||||
+ // CraftBukkit start
|
||||
+ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
if (entity.isRemoved()) {
|
||||
- ServerLevel.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityType.getKey(entity.getType()));
|
||||
+ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit
|
||||
return false;
|
||||
} else {
|
||||
+ // SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world.
|
||||
+ if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
return this.entityManager.addNewEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryAddFreshEntityWithPassengers(Entity entity) {
|
||||
- Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID);
|
||||
+ // CraftBukkit start
|
||||
+ return this.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ // CraftBukkit end
|
||||
+ Stream<UUID> stream = entity.getSelfAndPassengers().map(Entity::getUUID); // CraftBukkit - decompile error
|
||||
PersistentEntitySectionManager persistententitysectionmanager = this.entityManager;
|
||||
|
||||
Objects.requireNonNull(this.entityManager);
|
||||
if (stream.anyMatch(persistententitysectionmanager::isLoaded)) {
|
||||
return false;
|
||||
} else {
|
||||
- this.addFreshEntityWithPassengers(entity);
|
||||
+ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -973,11 +1105,33 @@
|
||||
serverplayer.remove(entity_removalreason);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public boolean strikeLightning(Entity entitylightning) {
|
||||
+ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN);
|
||||
+ }
|
||||
+
|
||||
+ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) {
|
||||
+ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause);
|
||||
+
|
||||
+ if (lightning.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return this.addFreshEntity(entitylightning);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public void destroyBlockProgress(int i, BlockPos blockpos, int j) {
|
||||
Iterator iterator = this.server.getPlayerList().getPlayers().iterator();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ Player entityhuman = null;
|
||||
+ Entity entity = this.getEntity(breakerId);
|
||||
+ if (entity instanceof Player) entityhuman = (Player) entity;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
|
||||
@@ -986,6 +1139,12 @@
|
||||
double d1 = (double) blockpos.getY() - serverplayer.getY();
|
||||
double d2 = (double) blockpos.getZ() - serverplayer.getZ();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
|
||||
serverplayer.connection.send(new ClientboundBlockDestructionPacket(i, blockpos, j));
|
||||
}
|
||||
@@ -1051,8 +1204,19 @@
|
||||
Iterator iterator = this.navigatingMobs.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
- Mob mob = (Mob) iterator.next();
|
||||
- PathNavigation pathnavigation = mob.getNavigation();
|
||||
+ // CraftBukkit start - fix SPIGOT-6362
|
||||
+ Mob entityinsentient;
|
||||
+ try {
|
||||
+ entityinsentient = (Mob) iterator.next();
|
||||
+ } catch (java.util.ConcurrentModificationException ex) {
|
||||
+ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register
|
||||
+ // In this case we just run the update again across all the iterators as the chunk will then be loaded
|
||||
+ // As this is a relative edge case it is much faster than copying navigators (on either read or write)
|
||||
+ sendBlockUpdated(pos, oldState, newState, flags);
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ PathNavigation navigationabstract = entityinsentient.getNavigation();
|
||||
|
||||
if (pathnavigation.shouldRecomputePath(blockpos)) {
|
||||
list.add(pathnavigation);
|
||||
@@ -1118,9 +1275,13 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) {
|
||||
- Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, false, particleoptions, particleoptions1, soundevent);
|
||||
+ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) {
|
||||
+ Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, false, particleparam, particleparam1, soundeffect);
|
||||
+ // CraftBukkit start
|
||||
+ if (explosion.wasCanceled) {
|
||||
+ return explosion;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (!explosion.interactsWithBlocks()) {
|
||||
explosion.clearToBlow();
|
||||
@@ -1196,14 +1353,21 @@
|
||||
return this.server.getStructureManager();
|
||||
}
|
||||
|
||||
- public <T extends ParticleOptions> int sendParticles(T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) {
|
||||
- ClientboundLevelParticlesPacket clientboundlevelparticlespacket = new ClientboundLevelParticlesPacket(t0, false, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
|
||||
+ public <T extends ParticleOptions> int sendParticles(T type, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) {
|
||||
+ // CraftBukkit - visibility api support
|
||||
+ return sendParticles(null, type, posX, d1, posY, i, posZ, d4, particleCount, xOffset, false);
|
||||
+ }
|
||||
+
|
||||
+ public <T extends ParticleOptions> int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) {
|
||||
+ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
|
||||
+ // CraftBukkit end
|
||||
int j = 0;
|
||||
|
||||
for (int k = 0; k < this.players.size(); ++k) {
|
||||
- ServerPlayer serverplayer = (ServerPlayer) this.players.get(k);
|
||||
+ ServerPlayer entityplayer = (ServerPlayer) this.players.get(k);
|
||||
+ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit
|
||||
|
||||
- if (this.sendParticles(serverplayer, false, d0, d1, d2, clientboundlevelparticlespacket)) {
|
||||
+ if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit
|
||||
++j;
|
||||
}
|
||||
}
|
||||
@@ -1254,8 +1417,8 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- public BlockPos findNearestMapStructure(TagKey<Structure> tagkey, BlockPos blockpos, int i, boolean flag) {
|
||||
- if (!this.server.getWorldData().worldGenOptions().generateStructures()) {
|
||||
+ public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipExistingChunks) {
|
||||
+ if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit
|
||||
return null;
|
||||
} else {
|
||||
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(tagkey);
|
||||
@@ -1299,15 +1459,24 @@
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
- @Override
|
||||
- public MapItemSavedData getMapData(String s) {
|
||||
- return (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), s);
|
||||
+ public MapItemSavedData getMapData(String mapName) {
|
||||
+ // CraftBukkit start
|
||||
+ MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName);
|
||||
+ if (worldmap != null) {
|
||||
+ worldmap.id = mapName;
|
||||
+ }
|
||||
+ return worldmap;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void setMapData(String s, MapItemSavedData mapitemsaveddata) {
|
||||
- this.getServer().overworld().getDataStorage().set(s, mapitemsaveddata);
|
||||
+ public void setMapData(String mapName, MapItemSavedData data) {
|
||||
+ // CraftBukkit start
|
||||
+ data.id = mapName;
|
||||
+ MapInitializeEvent event = new MapInitializeEvent(data.mapView);
|
||||
+ Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
+ // CraftBukkit end
|
||||
+ this.getServer().overworld().getDataStorage().set(mapName, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1608,7 +1773,12 @@
|
||||
@Override
|
||||
public void blockUpdated(BlockPos blockpos, Block block) {
|
||||
if (!this.isDebug()) {
|
||||
- this.updateNeighborsAt(blockpos, block);
|
||||
+ // CraftBukkit start
|
||||
+ if (populating) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ this.updateNeighborsAt(pos, block);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1629,13 +1797,13 @@
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
- return this.server.getWorldData().isFlatWorld();
|
||||
+ return this.serverLevelData.isFlatWorld(); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public long getSeed() {
|
||||
- return this.server.getWorldData().worldGenOptions().seed();
|
||||
+ return this.serverLevelData.worldGenOptions().seed(); // CraftBukkit
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1678,18 +1844,34 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public static void makeObsidianPlatform(ServerLevel serverlevel) {
|
||||
- BlockPos blockpos = ServerLevel.END_SPAWN_POINT;
|
||||
- int i = blockpos.getX();
|
||||
- int j = blockpos.getY() - 2;
|
||||
- int k = blockpos.getZ();
|
||||
+ public static void makeObsidianPlatform(ServerLevel serverLevel) {
|
||||
+ // CraftBukkit start
|
||||
+ ServerLevel.makeObsidianPlatform(serverLevel, null);
|
||||
+ }
|
||||
|
||||
- BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockpos1) -> {
|
||||
- serverlevel.setBlockAndUpdate(blockpos1, Blocks.AIR.defaultBlockState());
|
||||
+ public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) {
|
||||
+ // CraftBukkit end
|
||||
+ BlockPos blockposition = ServerLevel.END_SPAWN_POINT;
|
||||
+ int i = blockposition.getX();
|
||||
+ int j = blockposition.getY() - 2;
|
||||
+ int k = blockposition.getZ();
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver);
|
||||
+ BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> {
|
||||
+ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3);
|
||||
});
|
||||
BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockpos1) -> {
|
||||
serverlevel.setBlockAndUpdate(blockpos1, Blocks.OBSIDIAN.defaultBlockState());
|
||||
});
|
||||
+ org.bukkit.World bworld = worldserver.getWorld();
|
||||
+ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List<org.bukkit.block.BlockState>) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM);
|
||||
+
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent);
|
||||
+ if (!portalEvent.isCancelled()) {
|
||||
+ blockList.updateList();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1833,6 +2005,8 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
|
||||
+ entity.inWorld = true; // CraftBukkit - Mark entity as in world
|
||||
+ entity.valid = true; // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1870,6 +2043,14 @@
|
||||
}
|
||||
|
||||
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
|
||||
+ // CraftBukkit start
|
||||
+ entity.valid = false;
|
||||
+ if (!(entity instanceof ServerPlayer)) {
|
||||
+ for (ServerPlayer player : players) {
|
||||
+ player.getBukkitEntity().onEntityRemove(entity);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,334 @@
|
|||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -21,10 +23,28 @@
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.GameMasterBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
-import net.minecraft.world.level.block.state.BlockState;
|
||||
+import net.minecraft.world.level.block.state.IBlockData;
|
||||
+import org.slf4j.Logger;
|
||||
+
|
||||
+// CraftBukkit start
|
||||
+import java.util.ArrayList;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
+import net.minecraft.world.level.block.Blocks;
|
||||
+import net.minecraft.world.level.block.CakeBlock;
|
||||
+import net.minecraft.world.level.block.DoorBlock;
|
||||
+import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
-import org.slf4j.Logger;
|
||||
+import org.bukkit.GameMode;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.event.block.BlockBreakEvent;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.block.Action;
|
||||
+import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||
+import org.bukkit.event.player.PlayerInteractEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ServerPlayerGameMode {
|
||||
|
||||
@@ -56,9 +76,16 @@
|
||||
if (gametype == this.gameModeForPlayer) {
|
||||
return false;
|
||||
} else {
|
||||
- this.setGameModeForPlayer(gametype, this.previousGameModeForPlayer);
|
||||
+ // CraftBukkit start
|
||||
+ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player.getBukkitEntity(), GameMode.getByValue(gameModeForPlayer.getId()));
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ this.setGameModeForPlayer(gameModeForPlayer, this.previousGameModeForPlayer);
|
||||
this.player.onUpdateAbilities();
|
||||
- this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player));
|
||||
+ this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit
|
||||
this.level.updateSleepingPlayerList();
|
||||
return true;
|
||||
}
|
||||
@@ -88,8 +115,8 @@
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
- ++this.gameTicks;
|
||||
- BlockState blockstate;
|
||||
+ this.gameTicks = MinecraftServer.currentTick; // CraftBukkit;
|
||||
+ IBlockData iblockdata;
|
||||
|
||||
if (this.hasDelayedDestroy) {
|
||||
blockstate = this.level.getBlockState(this.delayedDestroyPos);
|
||||
@@ -140,13 +167,35 @@
|
||||
} else {
|
||||
BlockState blockstate;
|
||||
|
||||
- if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) {
|
||||
- if (!this.level.mayInteract(this.player, blockpos)) {
|
||||
- this.player.connection.send(new ClientboundBlockUpdatePacket(blockpos, this.level.getBlockState(blockpos)));
|
||||
- this.debugLogging(blockpos, false, j, "may not interact");
|
||||
+ if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.START_DESTROY_BLOCK) {
|
||||
+ if (!this.level.mayInteract(this.player, pos)) {
|
||||
+ // CraftBukkit start - fire PlayerInteractEvent
|
||||
+ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND);
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
|
||||
+ this.debugLogging(pos, false, sequence, "may not interact");
|
||||
+ // Update any tile entity data for this block
|
||||
+ BlockEntity tileentity = level.getBlockEntity(pos);
|
||||
+ if (tileentity != null) {
|
||||
+ this.player.connection.send(tileentity.getUpdatePacket());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND);
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Let the client know the block still exists
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ // Update any tile entity data for this block
|
||||
+ BlockEntity tileentity = this.level.getBlockEntity(pos);
|
||||
+ if (tileentity != null) {
|
||||
+ this.player.connection.send(tileentity.getUpdatePacket());
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (this.isCreative()) {
|
||||
this.destroyAndAck(blockpos, j, "creative destroy");
|
||||
return;
|
||||
@@ -161,14 +210,46 @@
|
||||
this.destroyProgressStart = this.gameTicks;
|
||||
float f = 1.0F;
|
||||
|
||||
- blockstate = this.level.getBlockState(blockpos);
|
||||
- if (!blockstate.isAir()) {
|
||||
- blockstate.attack(this.level, blockpos, this.player);
|
||||
- f = blockstate.getDestroyProgress(this.player, this.player.level(), blockpos);
|
||||
+ iblockdata = this.level.getBlockState(pos);
|
||||
+ // CraftBukkit start - Swings at air do *NOT* exist.
|
||||
+ if (event.useInteractedBlock() == Event.Result.DENY) {
|
||||
+ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door.
|
||||
+ IBlockData data = this.level.getBlockState(pos);
|
||||
+ if (data.getBlock() instanceof DoorBlock) {
|
||||
+ // For some reason *BOTH* the bottom/top part have to be marked updated.
|
||||
+ boolean bottom = data.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER;
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below()));
|
||||
+ } else if (data.getBlock() instanceof TrapDoorBlock) {
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ }
|
||||
+ } else if (!iblockdata.isAir()) {
|
||||
+ iblockdata.attack(this.level, pos, this.player);
|
||||
+ f = iblockdata.getDestroyProgress(this.player, this.player.level(), pos);
|
||||
}
|
||||
|
||||
- if (!blockstate.isAir() && f >= 1.0F) {
|
||||
- this.destroyAndAck(blockpos, j, "insta mine");
|
||||
+ if (event.useItemInHand() == Event.Result.DENY) {
|
||||
+ // If we 'insta destroyed' then the client needs to be informed.
|
||||
+ if (f > 1.0f) {
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f);
|
||||
+
|
||||
+ if (blockEvent.isCancelled()) {
|
||||
+ // Let the client know the block still exists
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (blockEvent.getInstaBreak()) {
|
||||
+ f = 2.0f;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (!iblockdata.isAir() && f >= 1.0F) {
|
||||
+ this.destroyAndAck(pos, sequence, "insta mine");
|
||||
} else {
|
||||
if (this.isDestroyingBlock) {
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(this.destroyPos, this.level.getBlockState(this.destroyPos)));
|
||||
@@ -210,14 +291,16 @@
|
||||
this.debugLogging(blockpos, true, j, "stopped destroying");
|
||||
} else if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
|
||||
this.isDestroyingBlock = false;
|
||||
- if (!Objects.equals(this.destroyPos, blockpos)) {
|
||||
- ServerPlayerGameMode.LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, blockpos);
|
||||
+ if (!Objects.equals(this.destroyPos, pos)) {
|
||||
+ ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled
|
||||
this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
|
||||
this.debugLogging(blockpos, true, j, "aborted mismatched destroying");
|
||||
}
|
||||
|
||||
- this.level.destroyBlockProgress(this.player.getId(), blockpos, -1);
|
||||
- this.debugLogging(blockpos, true, j, "aborted destroying");
|
||||
+ this.level.destroyBlockProgress(this.player.getId(), pos, -1);
|
||||
+ this.debugLogging(pos, true, sequence, "aborted destroying");
|
||||
+
|
||||
+ CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit
|
||||
}
|
||||
|
||||
}
|
||||
@@ -233,14 +316,69 @@
|
||||
|
||||
}
|
||||
|
||||
- public boolean destroyBlock(BlockPos blockpos) {
|
||||
- BlockState blockstate = this.level.getBlockState(blockpos);
|
||||
+ public boolean destroyBlock(BlockPos pos) {
|
||||
+ IBlockData iblockdata = this.level.getBlockState(pos);
|
||||
+ // CraftBukkit start - fire BlockBreakEvent
|
||||
+ org.bukkit.block.Block bblock = CraftBlock.at(level, pos);
|
||||
+ BlockBreakEvent event = null;
|
||||
|
||||
- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockstate, this.level, blockpos, this.player)) {
|
||||
+ if (this.player instanceof ServerPlayer) {
|
||||
+ // Sword + Creative mode pre-cancel
|
||||
+ boolean isSwordNoBreak = !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player);
|
||||
+
|
||||
+ // Tell client the block is gone immediately then process events
|
||||
+ // Don't tell the client if its a creative sword break because its not broken!
|
||||
+ if (level.getBlockEntity(pos) == null && !isSwordNoBreak) {
|
||||
+ ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(pos, Blocks.AIR.defaultBlockState());
|
||||
+ this.player.connection.send(packet);
|
||||
+ }
|
||||
+
|
||||
+ event = new BlockBreakEvent(bblock, this.player.getBukkitEntity());
|
||||
+
|
||||
+ // Sword + Creative mode pre-cancel
|
||||
+ event.setCancelled(isSwordNoBreak);
|
||||
+
|
||||
+ // Calculate default block experience
|
||||
+ IBlockData nmsData = this.level.getBlockState(pos);
|
||||
+ Block nmsBlock = nmsData.getBlock();
|
||||
+
|
||||
+ ItemStack itemstack = this.player.getItemBySlot(EquipmentSlot.MAINHAND);
|
||||
+
|
||||
+ if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) {
|
||||
+ event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, pos, itemstack, true));
|
||||
+ }
|
||||
+
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ if (isSwordNoBreak) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Let the client know the block still exists
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
|
||||
+
|
||||
+ // Brute force all possible updates
|
||||
+ for (Direction dir : Direction.values()) {
|
||||
+ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir)));
|
||||
+ }
|
||||
+
|
||||
+ // Update any tile entity data for this block
|
||||
+ BlockEntity tileentity = this.level.getBlockEntity(pos);
|
||||
+ if (tileentity != null) {
|
||||
+ this.player.connection.send(tileentity.getUpdatePacket());
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player)) { // CraftBukkit - false
|
||||
return false;
|
||||
} else {
|
||||
- BlockEntity blockentity = this.level.getBlockEntity(blockpos);
|
||||
- Block block = blockstate.getBlock();
|
||||
+ iblockdata = this.level.getBlockState(pos); // CraftBukkit - update state from plugins
|
||||
+ if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling
|
||||
+ BlockEntity tileentity = this.level.getBlockEntity(pos);
|
||||
+ Block block = iblockdata.getBlock();
|
||||
|
||||
if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) {
|
||||
this.level.sendBlockUpdated(blockpos, blockstate, blockstate, 3);
|
||||
@@ -248,27 +386,44 @@
|
||||
} else if (this.player.blockActionRestricted(this.level, blockpos, this.gameModeForPlayer)) {
|
||||
return false;
|
||||
} else {
|
||||
- BlockState blockstate1 = block.playerWillDestroy(this.level, blockpos, blockstate, this.player);
|
||||
- boolean flag = this.level.removeBlock(blockpos, false);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.BlockState state = bblock.getState();
|
||||
+ level.captureDrops = new ArrayList<>();
|
||||
+ // CraftBukkit end
|
||||
+ IBlockData iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player);
|
||||
+ boolean flag = this.level.removeBlock(pos, false);
|
||||
|
||||
if (flag) {
|
||||
block.destroy(this.level, blockpos, blockstate1);
|
||||
}
|
||||
|
||||
if (this.isCreative()) {
|
||||
- return true;
|
||||
+ // return true; // CraftBukkit
|
||||
} else {
|
||||
ItemStack itemstack = this.player.getMainHandItem();
|
||||
ItemStack itemstack1 = itemstack.copy();
|
||||
boolean flag1 = this.player.hasCorrectToolForDrops(blockstate1);
|
||||
|
||||
- itemstack.mineBlock(this.level, blockstate1, blockpos, this.player);
|
||||
- if (flag && flag1) {
|
||||
- block.playerDestroy(this.level, this.player, blockpos, blockstate1, blockentity, itemstack1);
|
||||
+ itemstack.mineBlock(this.level, iblockdata1, pos, this.player);
|
||||
+ if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
|
||||
+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1);
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ // return true; // CraftBukkit
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ if (event.isDropItems()) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops);
|
||||
+ }
|
||||
+ level.captureDrops = null;
|
||||
+
|
||||
+ // Drop event experience
|
||||
+ if (flag && event != null) {
|
||||
+ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop());
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,9 +468,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public InteractionResult useItemOn(ServerPlayer serverplayer, Level level, ItemStack itemstack, InteractionHand interactionhand, BlockHitResult blockhitresult) {
|
||||
- BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
- BlockState blockstate = level.getBlockState(blockpos);
|
||||
+ // CraftBukkit start - whole method
|
||||
+ public boolean interactResult = false;
|
||||
+ public boolean firedInteract = false;
|
||||
+ public BlockPos interactPosition;
|
||||
+ public EnumHand interactHand;
|
||||
+ public ItemStack interactItemStack;
|
||||
+ public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, EnumHand hand, BlockHitResult hitResult) {
|
||||
+ BlockPos blockposition = hitResult.getBlockPos();
|
||||
+ IBlockData iblockdata = level.getBlockState(blockposition);
|
||||
+ InteractionResult enuminteractionresult = InteractionResult.PASS;
|
||||
+ boolean cancelledBlock = false;
|
||||
|
||||
if (!blockstate.getBlock().isEnabled(level.enabledFeatures())) {
|
||||
return InteractionResult.FAIL;
|
||||
@@ -364,6 +557,8 @@
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
+ return enuminteractionresult;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public void setLevel(ServerLevel serverlevel) {
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/server/level/TicketType.java
|
||||
+++ b/net/minecraft/server/level/TicketType.java
|
||||
@@ -23,6 +23,8 @@
|
||||
public static final TicketType<BlockPos> PORTAL = create("portal", Vec3i::compareTo, 300);
|
||||
public static final TicketType<Integer> POST_TELEPORT = create("post_teleport", Integer::compareTo, 5);
|
||||
public static final TicketType<ChunkPos> UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1);
|
||||
+ public static final TicketType<Unit> PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit
|
||||
+ public static final TicketType<org.bukkit.plugin.Plugin> PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit
|
||||
|
||||
public static <T> TicketType<T> create(String s, Comparator<T> comparator) {
|
||||
return new TicketType<>(s, comparator, 0L);
|
|
@ -0,0 +1,27 @@
|
|||
--- a/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -221,8 +208,8 @@
|
||||
if (blockstate.isAir()) {
|
||||
return false;
|
||||
} else {
|
||||
- if (flag) {
|
||||
- BlockEntity blockentity = blockstate.hasBlockEntity() ? this.getBlockEntity(blockpos) : null;
|
||||
+ if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation
|
||||
+ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
|
||||
|
||||
Block.dropResources(blockstate, this.level, blockpos, blockentity, entity, ItemStack.EMPTY);
|
||||
}
|
||||
@@ -344,6 +327,13 @@
|
||||
@Override
|
||||
@Override
|
||||
public boolean addFreshEntity(Entity entity) {
|
||||
+ // CraftBukkit start
|
||||
+ return addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ // CraftBukkit end
|
||||
int i = SectionPos.blockToSectionCoord(entity.getBlockX());
|
||||
int j = SectionPos.blockToSectionCoord(entity.getBlockZ());
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
--- a/net/minecraft/server/network/LegacyQueryHandler.java
|
||||
+++ b/net/minecraft/server/network/LegacyQueryHandler.java
|
||||
@@ -36,10 +35,11 @@
|
||||
SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress();
|
||||
int i = bytebuf.readableBytes();
|
||||
String s;
|
||||
+ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); // CraftBukkit
|
||||
|
||||
if (i == 0) {
|
||||
LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress);
|
||||
- s = createVersion0Response(this.server);
|
||||
+ s = createVersion0Response(this.server, event); // CraftBukkit
|
||||
sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s));
|
||||
} else {
|
||||
if (bytebuf.readUnsignedByte() != 1) {
|
||||
@@ -56,7 +56,7 @@
|
||||
LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress);
|
||||
}
|
||||
|
||||
- s = createVersion1Response(this.server);
|
||||
+ s = createVersion1Response(this.server, event); // CraftBukkit
|
||||
sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s));
|
||||
}
|
||||
|
||||
@@ -107,12 +107,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static String createVersion0Response(ServerInfo serverinfo) {
|
||||
- return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers());
|
||||
+ // CraftBukkit start
|
||||
+ private static String createVersion0Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) {
|
||||
+ return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers());
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- private static String createVersion1Response(ServerInfo serverinfo) {
|
||||
- return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers());
|
||||
+ // CraftBukkit start
|
||||
+ private static String createVersion1Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) {
|
||||
+ return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers());
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
private static void sendFlushAndClose(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) {
|
|
@ -0,0 +1,208 @@
|
|||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -26,6 +30,17 @@
|
||||
import net.minecraft.util.thread.BlockableEventLoop;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import io.netty.buffer.ByteBuf;
|
||||
+import java.util.concurrent.ExecutionException;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
+import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.craftbukkit.util.Waitable;
|
||||
+import org.bukkit.event.player.PlayerKickEvent;
|
||||
+import org.bukkit.event.player.PlayerResourcePackStatusEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -39,13 +54,21 @@
|
||||
private int latency;
|
||||
private volatile boolean suspendFlushingOnServerThread = false;
|
||||
|
||||
- public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection connection, CommonListenerCookie commonlistenercookie) {
|
||||
+ public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit
|
||||
this.server = minecraftserver;
|
||||
this.connection = connection;
|
||||
this.keepAliveTime = Util.getMillis();
|
||||
this.latency = commonlistenercookie.latency();
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ this.player = player;
|
||||
+ this.cserver = minecraftserver.server;
|
||||
}
|
||||
|
||||
+ public CraftPlayer getCraftPlayer() {
|
||||
+ return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity();
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public void onDisconnect(Component component) {
|
||||
@@ -59,6 +83,7 @@
|
||||
@Override
|
||||
@Override
|
||||
public void handleKeepAlive(ServerboundKeepAlivePacket serverboundkeepalivepacket) {
|
||||
+ PacketUtils.ensureRunningOnSameThread(serverboundkeepalivepacket, this, this.player.serverLevel()); // CraftBukkit
|
||||
if (this.keepAlivePending && serverboundkeepalivepacket.getId() == this.keepAliveChallenge) {
|
||||
int i = (int) (Util.getMillis() - this.keepAliveTime);
|
||||
|
||||
@@ -74,10 +98,52 @@
|
||||
@Override
|
||||
public void handlePong(ServerboundPongPacket serverboundpongpacket) {}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register");
|
||||
+ private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister");
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) {}
|
||||
|
||||
+ if (identifier.equals(CUSTOM_REGISTER)) {
|
||||
+ try {
|
||||
+ String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
||||
+ for (String channel : channels.split("\0")) {
|
||||
+ getCraftPlayer().addChannel(channel);
|
||||
+ }
|
||||
+ } catch (Exception ex) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex);
|
||||
+ this.disconnect("Invalid payload REGISTER!");
|
||||
+ }
|
||||
+ } else if (identifier.equals(CUSTOM_UNREGISTER)) {
|
||||
+ try {
|
||||
+ String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
||||
+ for (String channel : channels.split("\0")) {
|
||||
+ getCraftPlayer().removeChannel(channel);
|
||||
+ }
|
||||
+ } catch (Exception ex) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex);
|
||||
+ this.disconnect("Invalid payload UNREGISTER!");
|
||||
+ }
|
||||
+ } else {
|
||||
+ try {
|
||||
+ byte[] data = new byte[payload.readableBytes()];
|
||||
+ payload.readBytes(data);
|
||||
+ cserver.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), identifier.toString(), data);
|
||||
+ } catch (Exception ex) {
|
||||
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex);
|
||||
+ this.disconnect("Invalid custom payload!");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ public final boolean isDisconnected() {
|
||||
+ return !this.player.joining && !this.connection.isConnected();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) {
|
||||
@@ -86,6 +156,7 @@
|
||||
ServerCommonPacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundresourcepackpacket.id());
|
||||
this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"));
|
||||
}
|
||||
+ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), serverboundresourcepackpacket.id(), PlayerResourcePackStatusEvent.Status.values()[serverboundresourcepackpacket.action().ordinal()])); // CraftBukkit
|
||||
|
||||
}
|
||||
|
||||
@@ -93,7 +164,7 @@
|
||||
this.server.getProfiler().push("keepAlive");
|
||||
long i = Util.getMillis();
|
||||
|
||||
- if (i - this.keepAliveTime >= 15000L) {
|
||||
+ if (i - this.keepAliveTime >= 25000L) { // CraftBukkit
|
||||
if (this.keepAlivePending) {
|
||||
this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE);
|
||||
} else {
|
||||
@@ -121,6 +192,14 @@
|
||||
}
|
||||
|
||||
public void send(Packet<?> packet, @Nullable PacketSendListener packetsendlistener) {
|
||||
+ // CraftBukkit start
|
||||
+ if (packet == null) {
|
||||
+ return;
|
||||
+ } else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) {
|
||||
+ ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet;
|
||||
+ this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread();
|
||||
|
||||
try {
|
||||
@@ -136,16 +215,67 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public void disconnect(Component component) {
|
||||
- this.connection.send(new ClientboundDisconnectPacket(component), PacketSendListener.thenRun(() -> {
|
||||
- this.connection.disconnect(component);
|
||||
+ // CraftBukkit start
|
||||
+ @Deprecated
|
||||
+ public void disconnect(Component ichatbasecomponent) {
|
||||
+ disconnect(CraftChatMessage.fromComponent(ichatbasecomponent));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public void disconnect(String s) {
|
||||
+ // CraftBukkit start - fire PlayerKickEvent
|
||||
+ if (this.processedDisconnect) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!this.cserver.isPrimaryThread()) {
|
||||
+ Waitable waitable = new Waitable() {
|
||||
+ @Override
|
||||
+ protected Object evaluate() {
|
||||
+ ServerCommonPacketListenerImpl.this.disconnect(s);
|
||||
+ return null;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ this.server.processQueue.add(waitable);
|
||||
+
|
||||
+ try {
|
||||
+ waitable.get();
|
||||
+ } catch (InterruptedException e) {
|
||||
+ Thread.currentThread().interrupt();
|
||||
+ } catch (ExecutionException e) {
|
||||
+ throw new RuntimeException(e);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game.";
|
||||
+
|
||||
+ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage);
|
||||
+
|
||||
+ if (this.cserver.getServer().isRunning()) {
|
||||
+ this.cserver.getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Do not kick the player
|
||||
+ return;
|
||||
+ }
|
||||
+ this.player.kickLeaveMessage = event.getLeaveMessage(); // CraftBukkit - SPIGOT-3034: Forward leave message to PlayerQuitEvent
|
||||
+ // Send the possibly modified leave message
|
||||
+ final Component ichatbasecomponent = CraftChatMessage.fromString(event.getReason(), true)[0];
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> {
|
||||
+ this.connection.disconnect(ichatbasecomponent);
|
||||
}));
|
||||
+ this.onDisconnect(ichatbasecomponent); // CraftBukkit - fire quit instantly
|
||||
this.connection.setReadOnly();
|
||||
MinecraftServer minecraftserver = this.server;
|
||||
Connection connection = this.connection;
|
||||
|
||||
Objects.requireNonNull(this.connection);
|
||||
- minecraftserver.executeBlocking(connection::handleDisconnection);
|
||||
+ // CraftBukkit - Don't wait
|
||||
+ minecraftserver.wrapRunnable(networkmanager::handleDisconnection);
|
||||
}
|
||||
|
||||
protected boolean isSingleplayerOwner() {
|
|
@ -0,0 +1,30 @@
|
|||
--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
@@ -44,8 +44,8 @@
|
||||
private ConfigurationTask currentTask;
|
||||
private ClientInformation clientInformation;
|
||||
|
||||
- public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection connection, CommonListenerCookie commonlistenercookie) {
|
||||
- super(minecraftserver, connection, commonlistenercookie);
|
||||
+ public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit
|
||||
+ super(minecraftserver, networkmanager, commonlistenercookie, player); // CraftBukkit
|
||||
this.gameProfile = commonlistenercookie.gameProfile();
|
||||
this.clientInformation = commonlistenercookie.clientInformation();
|
||||
}
|
||||
@@ -123,14 +117,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
- Component component = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile);
|
||||
+ Component ichatbasecomponent = null; // CraftBukkit - login checks already completed
|
||||
|
||||
if (component != null) {
|
||||
this.disconnect(component);
|
||||
return;
|
||||
}
|
||||
|
||||
- ServerPlayer serverplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation);
|
||||
+ ServerPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit
|
||||
|
||||
playerlist.placeNewPlayer(this.connection, serverplayer, this.createCookie(this.clientInformation));
|
||||
this.connection.resumeInboundAfterProtocolChange();
|
|
@ -0,0 +1,24 @@
|
|||
--- a/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -105,10 +104,20 @@
|
||||
((Connection) object).configurePacketHandler(channelpipeline);
|
||||
((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object));
|
||||
}
|
||||
- }).group(eventloopgroup).localAddress(inetaddress, i)).bind().syncUninterruptibly());
|
||||
+ }).group(eventloopgroup).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void acceptConnections() {
|
||||
+ synchronized (this.channels) {
|
||||
+ for (ChannelFuture future : this.channels) {
|
||||
+ future.channel().config().setAutoRead(true);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public SocketAddress startMemoryChannel() {
|
||||
List list = this.channels;
|
||||
ChannelFuture channelfuture;
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,78 @@
|
|||
--- a/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -11,8 +11,17 @@
|
||||
import net.minecraft.network.protocol.status.ServerStatus;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.net.InetAddress;
|
||||
+import java.util.HashMap;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketListener {
|
||||
|
||||
+ // CraftBukkit start - add fields
|
||||
+ private static final HashMap<InetAddress, Long> throttleTracker = new HashMap<InetAddress, Long>();
|
||||
+ private static int throttleCounter = 0;
|
||||
+ // CraftBukkit end
|
||||
private static final Component IGNORE_STATUS_REASON = Component.translatable("disconnect.ignoring_status_request");
|
||||
private final MinecraftServer server;
|
||||
private final Connection connection;
|
||||
@@ -23,16 +32,50 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void handleIntention(ClientIntentionPacket clientintentionpacket) {
|
||||
- switch (clientintentionpacket.intention()) {
|
||||
+ public void handleIntention(ClientIntentionPacket packet) {
|
||||
+ this.connection.hostname = packet.hostName() + ":" + packet.port(); // CraftBukkit - set hostname
|
||||
+ switch (packet.intention()) {
|
||||
case LOGIN:
|
||||
this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN);
|
||||
- if (clientintentionpacket.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
|
||||
- MutableComponent mutablecomponent;
|
||||
+ // CraftBukkit start - Connection throttle
|
||||
+ try {
|
||||
+ long currentTime = System.currentTimeMillis();
|
||||
+ long connectionThrottle = this.server.server.getConnectionThrottle();
|
||||
+ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress();
|
||||
|
||||
- if (clientintentionpacket.protocolVersion() < 754) {
|
||||
- mutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName());
|
||||
+ synchronized (throttleTracker) {
|
||||
+ if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) {
|
||||
+ throttleTracker.put(address, currentTime);
|
||||
+ MutableComponent chatmessage = Component.literal("Connection throttled! Please wait before reconnecting.");
|
||||
+ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
|
||||
+ this.connection.disconnect(chatmessage);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ throttleTracker.put(address, currentTime);
|
||||
+ throttleCounter++;
|
||||
+ if (throttleCounter > 200) {
|
||||
+ throttleCounter = 0;
|
||||
+
|
||||
+ // Cleanup stale entries
|
||||
+ java.util.Iterator iter = throttleTracker.entrySet().iterator();
|
||||
+ while (iter.hasNext()) {
|
||||
+ java.util.Map.Entry<InetAddress, Long> entry = (java.util.Map.Entry) iter.next();
|
||||
+ if (entry.getValue() > connectionThrottle) {
|
||||
+ iter.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (Throwable t) {
|
||||
+ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
|
||||
+ MutableComponent ichatmutablecomponent;
|
||||
+
|
||||
+ if (packet.protocolVersion() < 754) {
|
||||
+ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName());
|
||||
} else {
|
||||
mutablecomponent = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName());
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -39,6 +40,10 @@
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.slf4j.Logger;
|
||||
+import org.bukkit.craftbukkit.util.Waitable;
|
||||
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
+import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener {
|
||||
|
||||
@@ -56,6 +61,7 @@
|
||||
@Nullable
|
||||
private GameProfile authenticatedProfile;
|
||||
private final String serverId;
|
||||
+ private ServerPlayer player; // CraftBukkit
|
||||
|
||||
public ServerLoginPacketListenerImpl(MinecraftServer minecraftserver, Connection connection) {
|
||||
this.state = ServerLoginPacketListenerImpl.State.HELLO;
|
||||
@@ -82,6 +87,13 @@
|
||||
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ @Deprecated
|
||||
+ public void disconnect(String s) {
|
||||
+ disconnect(Component.literal(s));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
@Override
|
||||
public boolean isAcceptingMessages() {
|
||||
@@ -143,10 +152,12 @@
|
||||
|
||||
private void verifyLoginAndFinishConnectionSetup(GameProfile gameprofile) {
|
||||
PlayerList playerlist = this.server.getPlayerList();
|
||||
- Component component = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), gameprofile);
|
||||
+ // CraftBukkit start - fire PlayerLoginEvent
|
||||
+ this.player = playerlist.canPlayerLogin(this, gameprofile); // CraftBukkit
|
||||
|
||||
- if (component != null) {
|
||||
- this.disconnect(component);
|
||||
+ if (this.player == null) {
|
||||
+ // this.disconnect(ichatbasecomponent);
|
||||
+ // CraftBukkit end
|
||||
} else {
|
||||
if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) {
|
||||
this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> {
|
||||
@@ -154,7 +165,7 @@
|
||||
}));
|
||||
}
|
||||
|
||||
- boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile);
|
||||
+ boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile, this.player); // CraftBukkit - add player reference
|
||||
|
||||
if (flag) {
|
||||
this.state = ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT;
|
||||
@@ -206,6 +215,43 @@
|
||||
if (profileresult != null) {
|
||||
GameProfile gameprofile = profileresult.profile();
|
||||
|
||||
+ // CraftBukkit start - fire PlayerPreLoginEvent
|
||||
+ if (!connection.isConnected()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ String playerName = gameprofile.getName();
|
||||
+ java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress();
|
||||
+ java.util.UUID uniqueId = gameprofile.getId();
|
||||
+ final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server;
|
||||
+
|
||||
+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId);
|
||||
+ server.getPluginManager().callEvent(asyncEvent);
|
||||
+
|
||||
+ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
|
||||
+ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId);
|
||||
+ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
|
||||
+ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage());
|
||||
+ }
|
||||
+ Waitable<PlayerPreLoginEvent.Result> waitable = new Waitable<PlayerPreLoginEvent.Result>() {
|
||||
+ @Override
|
||||
+ protected PlayerPreLoginEvent.Result evaluate() {
|
||||
+ server.getPluginManager().callEvent(event);
|
||||
+ return event.getResult();
|
||||
+ }};
|
||||
+
|
||||
+ ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable);
|
||||
+ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) {
|
||||
+ disconnect(event.getKickMessage());
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
+ disconnect(asyncEvent.getKickMessage());
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId());
|
||||
ServerLoginPacketListenerImpl.this.startClientVerification(gameprofile);
|
||||
} else if (ServerLoginPacketListenerImpl.this.server.isSingleplayer()) {
|
||||
@@ -223,6 +269,11 @@
|
||||
ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down"));
|
||||
ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable");
|
||||
}
|
||||
+ // CraftBukkit start - catch all exceptions
|
||||
+ } catch (Exception exception) {
|
||||
+ disconnect("Failed to verify username!");
|
||||
+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + s1, exception);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
}
|
||||
@@ -250,7 +299,7 @@
|
||||
public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundloginacknowledgedpacket) {
|
||||
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]);
|
||||
CommonListenerCookie commonlistenercookie = CommonListenerCookie.createInitial((GameProfile) Objects.requireNonNull(this.authenticatedProfile));
|
||||
- ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie);
|
||||
+ ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie, this.player); // CraftBukkit
|
||||
|
||||
this.connection.setListener(serverconfigurationpacketlistenerimpl);
|
||||
serverconfigurationpacketlistenerimpl.startConfiguration();
|
|
@ -0,0 +1,131 @@
|
|||
--- a/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
|
||||
@@ -1,5 +1,12 @@
|
||||
package net.minecraft.server.network;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import java.net.InetSocketAddress;
|
||||
+import java.util.Collections;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.Optional;
|
||||
+import net.minecraft.SharedConstants;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.status.ClientboundPongResponsePacket;
|
||||
@@ -8,6 +15,12 @@
|
||||
import net.minecraft.network.protocol.status.ServerStatusPacketListener;
|
||||
import net.minecraft.network.protocol.status.ServerboundPingRequestPacket;
|
||||
import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
+import org.bukkit.craftbukkit.util.CraftIconCache;
|
||||
+import org.bukkit.entity.Player;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ServerStatusPacketListenerImpl implements ServerStatusPacketListener {
|
||||
|
||||
@@ -38,7 +48,101 @@
|
||||
this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON);
|
||||
} else {
|
||||
this.hasRequestedStatus = true;
|
||||
- this.connection.send(new ClientboundStatusResponsePacket(this.status));
|
||||
+ // CraftBukkit start
|
||||
+ // this.connection.send(new PacketStatusOutServerInfo(this.status));
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ final Object[] players = server.getPlayerList().players.toArray();
|
||||
+ class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent {
|
||||
+
|
||||
+ CraftIconCache icon = server.server.getServerIcon();
|
||||
+
|
||||
+ ServerListPingEvent() {
|
||||
+ super(connection.hostname, ((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setServerIcon(org.bukkit.util.CachedServerIcon icon) {
|
||||
+ if (!(icon instanceof CraftIconCache)) {
|
||||
+ throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class);
|
||||
+ }
|
||||
+ this.icon = (CraftIconCache) icon;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Iterator<Player> iterator() throws UnsupportedOperationException {
|
||||
+ return new Iterator<Player>() {
|
||||
+ int i;
|
||||
+ int ret = Integer.MIN_VALUE;
|
||||
+ ServerPlayer player;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ if (player != null) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ final Object[] currentPlayers = players;
|
||||
+ for (int length = currentPlayers.length, i = this.i; i < length; i++) {
|
||||
+ final ServerPlayer player = (ServerPlayer) currentPlayers[i];
|
||||
+ if (player != null) {
|
||||
+ this.i = i + 1;
|
||||
+ this.player = player;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Player next() {
|
||||
+ if (!hasNext()) {
|
||||
+ throw new java.util.NoSuchElementException();
|
||||
+ }
|
||||
+ final ServerPlayer player = this.player;
|
||||
+ this.player = null;
|
||||
+ this.ret = this.i - 1;
|
||||
+ return player.getBukkitEntity();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ final Object[] currentPlayers = players;
|
||||
+ final int i = this.ret;
|
||||
+ if (i < 0 || currentPlayers[i] == null) {
|
||||
+ throw new IllegalStateException();
|
||||
+ }
|
||||
+ currentPlayers[i] = null;
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ServerListPingEvent event = new ServerListPingEvent();
|
||||
+ server.server.getPluginManager().callEvent(event);
|
||||
+
|
||||
+ java.util.List<GameProfile> profiles = new java.util.ArrayList<GameProfile>(players.length);
|
||||
+ for (Object player : players) {
|
||||
+ if (player != null) {
|
||||
+ ServerPlayer entityPlayer = ((ServerPlayer) player);
|
||||
+ if (entityPlayer.allowsListing()) {
|
||||
+ profiles.add(entityPlayer.getGameProfile());
|
||||
+ } else {
|
||||
+ profiles.add(MinecraftServer.ANONYMOUS_PLAYER_PROFILE);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ServerStatus.ServerPingPlayerSample playerSample = new ServerStatus.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles);
|
||||
+
|
||||
+ ServerStatus ping = new ServerStatus(
|
||||
+ CraftChatMessage.fromString(event.getMotd(), true)[0],
|
||||
+ Optional.of(playerSample),
|
||||
+ Optional.of(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), SharedConstants.getCurrentVersion().getProtocolVersion())),
|
||||
+ (event.icon.value != null) ? Optional.of(new ServerStatus.a(event.icon.value)) : Optional.empty(),
|
||||
+ server.enforceSecureProfile()
|
||||
+ );
|
||||
+
|
||||
+ this.connection.send(new ClientboundStatusResponsePacket(ping));
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
--- a/net/minecraft/server/players/BanListEntry.java
|
||||
+++ b/net/minecraft/server/players/BanListEntry.java
|
||||
@@ -26,8 +26,8 @@
|
||||
this.reason = s1 == null ? "Banned by an operator." : s1;
|
||||
}
|
||||
|
||||
- protected BanListEntry(@Nullable T t0, JsonObject jsonobject) {
|
||||
- super(t0);
|
||||
+ protected BanListEntry(@Nullable T user, JsonObject entryData) {
|
||||
+ super(checkExpiry(user, entryData)); // CraftBukkit
|
||||
|
||||
Date date;
|
||||
|
||||
@@ -85,4 +83,22 @@
|
||||
jsonobject.addProperty("expires", this.expires == null ? "forever" : BanListEntry.DATE_FORMAT.format(this.expires));
|
||||
jsonobject.addProperty("reason", this.reason);
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ private static <T> T checkExpiry(T object, JsonObject jsonobject) {
|
||||
+ Date expires = null;
|
||||
+
|
||||
+ try {
|
||||
+ expires = jsonobject.has("expires") ? DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null;
|
||||
+ } catch (ParseException ex) {
|
||||
+ // Guess we don't have a date
|
||||
+ }
|
||||
+
|
||||
+ if (expires == null || expires.after(new Date())) {
|
||||
+ return object;
|
||||
+ } else {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
--- a/net/minecraft/server/players/OldUsersConverter.java
|
||||
+++ b/net/minecraft/server/players/OldUsersConverter.java
|
||||
@@ -85,7 +88,7 @@
|
||||
try {
|
||||
userbanlist.load();
|
||||
} catch (IOException ioexception) {
|
||||
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", userbanlist.getFile().getName(), ioexception);
|
||||
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +146,7 @@
|
||||
try {
|
||||
ipbanlist.load();
|
||||
} catch (IOException ioexception) {
|
||||
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName(), ioexception);
|
||||
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +187,7 @@
|
||||
try {
|
||||
serveroplist.load();
|
||||
} catch (IOException ioexception) {
|
||||
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", serveroplist.getFile().getName(), ioexception);
|
||||
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +231,7 @@
|
||||
try {
|
||||
userwhitelist.load();
|
||||
} catch (IOException ioexception) {
|
||||
- OldUsersConverter.LOGGER.warn("Could not load existing file {}", userwhitelist.getFile().getName(), ioexception);
|
||||
+ OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +350,31 @@
|
||||
File file5 = new File(file, s2 + ".dat");
|
||||
File file6 = new File(file4, s3 + ".dat");
|
||||
|
||||
- OldUsersConverter.ensureDirectoryExists(file4);
|
||||
+ // CraftBukkit start - Use old file name to seed lastKnownName
|
||||
+ CompoundTag root = null;
|
||||
+
|
||||
+ try {
|
||||
+ root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap());
|
||||
+ } catch (Exception exception) {
|
||||
+ exception.printStackTrace();
|
||||
+ }
|
||||
+
|
||||
+ if (root != null) {
|
||||
+ if (!root.contains("bukkit")) {
|
||||
+ root.put("bukkit", new CompoundTag());
|
||||
+ }
|
||||
+ CompoundTag data = root.getCompound("bukkit");
|
||||
+ data.putString("lastKnownName", oldFileName);
|
||||
+
|
||||
+ try {
|
||||
+ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2));
|
||||
+ } catch (Exception exception) {
|
||||
+ exception.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ OldUsersConverter.ensureDirectoryExists(file);
|
||||
if (!file5.renameTo(file6)) {
|
||||
throw new OldUsersConverter.ConversionError("Could not convert file for " + s2);
|
||||
}
|
|
@ -0,0 +1,856 @@
|
|||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -101,6 +101,25 @@
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.util.stream.Collectors;
|
||||
+import net.minecraft.server.dedicated.DedicatedServer;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.CraftServer;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
+import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
+import org.bukkit.event.player.PlayerJoinEvent;
|
||||
+import org.bukkit.event.player.PlayerLoginEvent;
|
||||
+import org.bukkit.event.player.PlayerQuitEvent;
|
||||
+import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
+import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason;
|
||||
+import org.bukkit.event.player.PlayerSpawnChangeEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public abstract class PlayerList {
|
||||
|
||||
public static final File USERBANLIST_FILE = new File("banned-players.json");
|
||||
@@ -113,15 +132,17 @@
|
||||
private static final int SEND_PLAYER_INFO_INTERVAL = 600;
|
||||
private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
|
||||
private final MinecraftServer server;
|
||||
- private final List<ServerPlayer> players = Lists.newArrayList();
|
||||
+ public final List<ServerPlayer> players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety
|
||||
private final Map<UUID, ServerPlayer> playersByUUID = Maps.newHashMap();
|
||||
private final UserBanList bans;
|
||||
private final IpBanList ipBans;
|
||||
private final ServerOpList ops;
|
||||
private final UserWhiteList whitelist;
|
||||
- private final Map<UUID, ServerStatsCounter> stats;
|
||||
- private final Map<UUID, PlayerAdvancements> advancements;
|
||||
- private final PlayerDataStorage playerIo;
|
||||
+ // CraftBukkit start
|
||||
+ // private final Map<UUID, ServerStatisticManager> stats;
|
||||
+ // private final Map<UUID, AdvancementDataPlayer> advancements;
|
||||
+ // CraftBukkit end
|
||||
+ public final PlayerDataStorage playerIo;
|
||||
private boolean doWhiteList;
|
||||
private final LayeredRegistryAccess<RegistryLayer> registries;
|
||||
protected final int maxPlayers;
|
||||
@@ -131,17 +152,27 @@
|
||||
private static final boolean ALLOW_LOGOUTIVATOR = false;
|
||||
private int sendAllPlayerInfoIn;
|
||||
|
||||
- public PlayerList(MinecraftServer minecraftserver, LayeredRegistryAccess<RegistryLayer> layeredregistryaccess, PlayerDataStorage playerdatastorage, int i) {
|
||||
+ // CraftBukkit start
|
||||
+ private CraftServer cserver;
|
||||
+
|
||||
+ public PlayerList(MinecraftServer server, LayeredRegistryAccess<RegistryLayer> registries, PlayerDataStorage playerIo, int maxPlayers) {
|
||||
+ this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
|
||||
+ server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance();
|
||||
+ server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server));
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
this.bans = new UserBanList(PlayerList.USERBANLIST_FILE);
|
||||
this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE);
|
||||
this.ops = new ServerOpList(PlayerList.OPLIST_FILE);
|
||||
this.whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE);
|
||||
- this.stats = Maps.newHashMap();
|
||||
- this.advancements = Maps.newHashMap();
|
||||
- this.server = minecraftserver;
|
||||
- this.registries = layeredregistryaccess;
|
||||
- this.maxPlayers = i;
|
||||
- this.playerIo = playerdatastorage;
|
||||
+ // CraftBukkit start
|
||||
+ // this.stats = Maps.newHashMap();
|
||||
+ // this.advancements = Maps.newHashMap();
|
||||
+ // CraftBukkit end
|
||||
+ this.server = server;
|
||||
+ this.registries = registries;
|
||||
+ this.maxPlayers = maxPlayers;
|
||||
+ this.playerIo = playerIo;
|
||||
}
|
||||
|
||||
public void placeNewPlayer(Connection connection, ServerPlayer serverplayer, CommonListenerCookie commonlistenercookie) {
|
||||
@@ -160,15 +191,21 @@
|
||||
|
||||
CompoundTag compoundtag = this.load(serverplayer);
|
||||
ResourceKey resourcekey;
|
||||
+ // CraftBukkit start - Better rename detection
|
||||
+ if (nbttagcompound != null && nbttagcompound.contains("bukkit")) {
|
||||
+ CompoundTag bukkit = nbttagcompound.getCompound("bukkit");
|
||||
+ s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (compoundtag != null) {
|
||||
DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundtag.get("Dimension")));
|
||||
Logger logger = PlayerList.LOGGER;
|
||||
|
||||
Objects.requireNonNull(logger);
|
||||
- resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(Level.OVERWORLD);
|
||||
+ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(entityplayer.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD
|
||||
} else {
|
||||
- resourcekey = Level.OVERWORLD;
|
||||
+ resourcekey = entityplayer.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD
|
||||
}
|
||||
|
||||
ResourceKey<Level> resourcekey1 = resourcekey;
|
||||
@@ -185,8 +222,9 @@
|
||||
serverplayer.setServerLevel(serverlevel1);
|
||||
String s1 = connection.getLoggableAddress(this.server.logIPs());
|
||||
|
||||
- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{serverplayer.getName().getString(), s1, serverplayer.getId(), serverplayer.getX(), serverplayer.getY(), serverplayer.getZ()});
|
||||
- LevelData leveldata = serverlevel1.getLevelData();
|
||||
+ // CraftBukkit - Moved message to after join
|
||||
+ // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()});
|
||||
+ LevelData worlddata = worldserver1.getLevelData();
|
||||
|
||||
serverplayer.loadGameTypes(compoundtag);
|
||||
ServerGamePacketListenerImpl servergamepacketlistenerimpl = new ServerGamePacketListenerImpl(this.server, connection, serverplayer, commonlistenercookie);
|
||||
@@ -195,15 +233,16 @@
|
||||
boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
|
||||
boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
|
||||
|
||||
- servergamepacketlistenerimpl.send(new ClientboundLoginPacket(serverplayer.getId(), leveldata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, serverplayer.createCommonSpawnInfo(serverlevel1)));
|
||||
- servergamepacketlistenerimpl.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked()));
|
||||
- servergamepacketlistenerimpl.send(new ClientboundPlayerAbilitiesPacket(serverplayer.getAbilities()));
|
||||
- servergamepacketlistenerimpl.send(new ClientboundSetCarriedItemPacket(serverplayer.getInventory().selected));
|
||||
- servergamepacketlistenerimpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()));
|
||||
- this.sendPlayerPermissionLevel(serverplayer);
|
||||
- serverplayer.getStats().markAllDirty();
|
||||
- serverplayer.getRecipeBook().sendInitialRecipeBook(serverplayer);
|
||||
- this.updateEntireScoreboard(serverlevel1.getScoreboard(), serverplayer);
|
||||
+ playerconnection.send(new ClientboundLoginPacket(entityplayer.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, entityplayer.createCommonSpawnInfo(worldserver1)));
|
||||
+ entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||
+ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
|
||||
+ playerconnection.send(new ClientboundPlayerAbilitiesPacket(entityplayer.getAbilities()));
|
||||
+ playerconnection.send(new ClientboundSetCarriedItemPacket(entityplayer.getInventory().selected));
|
||||
+ playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()));
|
||||
+ this.sendPlayerPermissionLevel(entityplayer);
|
||||
+ entityplayer.getStats().markAllDirty();
|
||||
+ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer);
|
||||
+ this.updateEntireScoreboard(worldserver1.getScoreboard(), entityplayer);
|
||||
this.server.invalidateStatus();
|
||||
MutableComponent mutablecomponent;
|
||||
|
||||
@@ -212,6 +251,9 @@
|
||||
} else {
|
||||
mutablecomponent = Component.translatable("multiplayer.player.joined.renamed", serverplayer.getDisplayName(), s);
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ ichatmutablecomponent.withStyle(ChatFormatting.YELLOW);
|
||||
+ String joinMessage = CraftChatMessage.fromComponent(ichatmutablecomponent);
|
||||
|
||||
this.broadcastSystemMessage(mutablecomponent.withStyle(ChatFormatting.YELLOW), false);
|
||||
servergamepacketlistenerimpl.teleport(serverplayer.getX(), serverplayer.getY(), serverplayer.getZ(), serverplayer.getYRot(), serverplayer.getXRot());
|
||||
@@ -221,25 +262,79 @@
|
||||
serverplayer.sendServerStatus(serverstatus);
|
||||
}
|
||||
|
||||
- serverplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players));
|
||||
- this.players.add(serverplayer);
|
||||
- this.playersByUUID.put(serverplayer.getUUID(), serverplayer);
|
||||
- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(serverplayer)));
|
||||
- this.sendLevelInfo(serverplayer, serverlevel1);
|
||||
- serverlevel1.addNewPlayer(serverplayer);
|
||||
- this.server.getCustomBossEvents().onPlayerConnect(serverplayer);
|
||||
- Iterator iterator = serverplayer.getActiveEffects().iterator();
|
||||
+ // entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
|
||||
+ this.players.add(entityplayer);
|
||||
+ this.playersByUUID.put(entityplayer.getUUID(), entityplayer);
|
||||
+ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ CraftPlayer bukkitPlayer = entityplayer.getBukkitEntity();
|
||||
+
|
||||
+ // Ensure that player inventory is populated with its viewer
|
||||
+ entityplayer.containerMenu.transferTo(entityplayer.containerMenu, bukkitPlayer);
|
||||
+
|
||||
+ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage);
|
||||
+ cserver.getPluginManager().callEvent(playerJoinEvent);
|
||||
+
|
||||
+ if (!entityplayer.connection.isAcceptingMessages()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ joinMessage = playerJoinEvent.getJoinMessage();
|
||||
+
|
||||
+ if (joinMessage != null && joinMessage.length() > 0) {
|
||||
+ for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) {
|
||||
+ server.getPlayerList().broadcastSystemMessage(line, false);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // CraftBukkit start - sendAll above replaced with this loop
|
||||
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer));
|
||||
+
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
|
||||
+
|
||||
+ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
|
||||
+ entityplayer1.connection.send(packet);
|
||||
+ }
|
||||
+
|
||||
+ if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1)));
|
||||
+ }
|
||||
+ entityplayer.sentListPacket = true;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
||||
+
|
||||
+ this.sendLevelInfo(entityplayer, worldserver1);
|
||||
+
|
||||
+ // CraftBukkit start - Only add if the player wasn't moved in the event
|
||||
+ if (entityplayer.level() == worldserver1 && !worldserver1.players().contains(entityplayer)) {
|
||||
+ worldserver1.addNewPlayer(entityplayer);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer);
|
||||
+ }
|
||||
+
|
||||
+ worldserver1 = entityplayer.serverLevel(); // CraftBukkit - Update in case join event changed it
|
||||
+ // CraftBukkit end
|
||||
+ Iterator iterator = entityplayer.getActiveEffects().iterator();
|
||||
+
|
||||
while (iterator.hasNext()) {
|
||||
MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next();
|
||||
|
||||
servergamepacketlistenerimpl.send(new ClientboundUpdateMobEffectPacket(serverplayer.getId(), mobeffectinstance));
|
||||
}
|
||||
|
||||
- if (compoundtag != null && compoundtag.contains("RootVehicle", 10)) {
|
||||
- CompoundTag compoundtag1 = compoundtag.getCompound("RootVehicle");
|
||||
- Entity entity = EntityType.loadEntityRecursive(compoundtag1.getCompound("Entity"), serverlevel1, (entity1) -> {
|
||||
- return !serverlevel1.addWithUUID(entity1) ? null : entity1;
|
||||
+ if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) {
|
||||
+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle");
|
||||
+ // CraftBukkit start
|
||||
+ ServerLevel finalWorldServer = worldserver1;
|
||||
+ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> {
|
||||
+ return !finalWorldServer.addWithUUID(entity1) ? null : entity1;
|
||||
+ // CraftBukkit end
|
||||
});
|
||||
|
||||
if (entity != null) {
|
||||
@@ -281,7 +376,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
- serverplayer.initInventoryMenu();
|
||||
+ entityplayer.initInventoryMenu();
|
||||
+ // CraftBukkit - Moved from above, added world
|
||||
+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.serverLevelData.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ());
|
||||
}
|
||||
|
||||
protected void updateEntireScoreboard(ServerScoreboard serverscoreboard, ServerPlayer serverplayer) {
|
||||
@@ -317,36 +414,32 @@
|
||||
|
||||
}
|
||||
|
||||
- public void addWorldborderListener(ServerLevel serverlevel) {
|
||||
- serverlevel.getWorldBorder().addListener(new BorderChangeListener() {
|
||||
+ public void addWorldborderListener(ServerLevel level) {
|
||||
+ if (playerIo != null) return; // CraftBukkit
|
||||
+ level.getWorldBorder().addListener(new BorderChangeListener() {
|
||||
@Override
|
||||
- @Override
|
||||
- public void onBorderSizeSet(WorldBorder worldborder, double d0) {
|
||||
- PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(worldborder));
|
||||
+ public void onBorderSizeSet(WorldBorder border, double size) {
|
||||
+ PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onBorderSizeLerping(WorldBorder worldborder, double d0, double d1, long i) {
|
||||
- PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(worldborder));
|
||||
+ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) {
|
||||
+ PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onBorderCenterSet(WorldBorder worldborder, double d0, double d1) {
|
||||
- PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(worldborder));
|
||||
+ public void onBorderCenterSet(WorldBorder border, double x, double d1) {
|
||||
+ PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onBorderSetWarningTime(WorldBorder worldborder, int i) {
|
||||
- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(worldborder));
|
||||
+ public void onBorderSetWarningTime(WorldBorder border, int warningTime) {
|
||||
+ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
- @Override
|
||||
- public void onBorderSetWarningBlocks(WorldBorder worldborder, int i) {
|
||||
- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(worldborder));
|
||||
+ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) {
|
||||
+ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -375,15 +466,16 @@
|
||||
return compoundtag1;
|
||||
}
|
||||
|
||||
- protected void save(ServerPlayer serverplayer) {
|
||||
- this.playerIo.save(serverplayer);
|
||||
- ServerStatsCounter serverstatscounter = (ServerStatsCounter) this.stats.get(serverplayer.getUUID());
|
||||
+ protected void save(ServerPlayer player) {
|
||||
+ if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
|
||||
+ this.playerIo.save(player);
|
||||
+ ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit
|
||||
|
||||
if (serverstatscounter != null) {
|
||||
serverstatscounter.save();
|
||||
}
|
||||
|
||||
- PlayerAdvancements playeradvancements = (PlayerAdvancements) this.advancements.get(serverplayer.getUUID());
|
||||
+ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit
|
||||
|
||||
if (playeradvancements != null) {
|
||||
playeradvancements.save();
|
||||
@@ -391,14 +483,31 @@
|
||||
|
||||
}
|
||||
|
||||
- public void remove(ServerPlayer serverplayer) {
|
||||
- ServerLevel serverlevel = serverplayer.serverLevel();
|
||||
+ public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string
|
||||
+ ServerLevel worldserver = entityplayer.serverLevel();
|
||||
|
||||
serverplayer.awardStat(Stats.LEAVE_GAME);
|
||||
this.save(serverplayer);
|
||||
if (serverplayer.isPassenger()) {
|
||||
Entity entity = serverplayer.getRootVehicle();
|
||||
|
||||
+ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
|
||||
+ // See SPIGOT-5799, SPIGOT-6145
|
||||
+ if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
|
||||
+ entityplayer.closeContainer();
|
||||
+ }
|
||||
+
|
||||
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), entityplayer.kickLeaveMessage != null ? entityplayer.kickLeaveMessage : "\u00A7e" + entityplayer.getScoreboardName() + " left the game");
|
||||
+ cserver.getPluginManager().callEvent(playerQuitEvent);
|
||||
+ entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
+
|
||||
+ entityplayer.doTick(); // SPIGOT-924
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ this.save(entityplayer);
|
||||
+ if (entityplayer.isPassenger()) {
|
||||
+ Entity entity = entityplayer.getRootVehicle();
|
||||
+
|
||||
if (entity.hasExactlyOnePlayerPassenger()) {
|
||||
PlayerList.LOGGER.debug("Removing player mount");
|
||||
serverplayer.stopRiding();
|
||||
@@ -418,16 +524,34 @@
|
||||
|
||||
if (serverplayer1 == serverplayer) {
|
||||
this.playersByUUID.remove(uuid);
|
||||
- this.stats.remove(uuid);
|
||||
- this.advancements.remove(uuid);
|
||||
+ // CraftBukkit start
|
||||
+ // this.stats.remove(uuid);
|
||||
+ // this.advancements.remove(uuid);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(serverplayer.getUUID())));
|
||||
+ // CraftBukkit start
|
||||
+ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())));
|
||||
+ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()));
|
||||
+ for (int i = 0; i < players.size(); i++) {
|
||||
+ ServerPlayer entityplayer2 = (ServerPlayer) this.players.get(i);
|
||||
+
|
||||
+ if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) {
|
||||
+ entityplayer2.connection.send(packet);
|
||||
+ } else {
|
||||
+ entityplayer2.getBukkitEntity().onEntityRemove(entityplayer);
|
||||
+ }
|
||||
+ }
|
||||
+ // This removes the scoreboard (and player reference) for the specific player in the manager
|
||||
+ cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ return playerQuitEvent.getQuitMessage(); // CraftBukkit
|
||||
}
|
||||
|
||||
- @Nullable
|
||||
- public Component canPlayerLogin(SocketAddress socketaddress, GameProfile gameprofile) {
|
||||
- MutableComponent mutablecomponent;
|
||||
+ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer
|
||||
+ public ServerPlayer canPlayerLogin(ServerLoginPacketListenerImpl loginlistener, GameProfile gameprofile) {
|
||||
+ MutableComponent ichatmutablecomponent;
|
||||
|
||||
if (this.bans.isBanned(gameprofile)) {
|
||||
UserBanListEntry userbanlistentry = (UserBanListEntry) this.bans.get(gameprofile);
|
||||
@@ -437,7 +566,33 @@
|
||||
mutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(userbanlistentry.getExpires())));
|
||||
}
|
||||
|
||||
- return mutablecomponent;
|
||||
+ Iterator iterator = list.iterator();
|
||||
+
|
||||
+ while (iterator.hasNext()) {
|
||||
+ entityplayer = (ServerPlayer) iterator.next();
|
||||
+ save(entityplayer); // CraftBukkit - Force the player's inventory to be saved
|
||||
+ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login"));
|
||||
+ }
|
||||
+
|
||||
+ // Instead of kicking then returning, we need to store the kick reason
|
||||
+ // in the event, check with plugins to see if it's ok, and THEN kick
|
||||
+ // depending on the outcome.
|
||||
+ SocketAddress socketaddress = loginlistener.connection.getRemoteAddress();
|
||||
+
|
||||
+ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, ClientInformation.createDefault());
|
||||
+ Player player = entity.getBukkitEntity();
|
||||
+ PlayerLoginEvent event = new PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketaddress).getAddress());
|
||||
+
|
||||
+ if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) {
|
||||
+ UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile);
|
||||
+
|
||||
+ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason());
|
||||
+ if (gameprofilebanentry.getExpires() != null) {
|
||||
+ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires())));
|
||||
+ }
|
||||
+
|
||||
+ // return chatmessage;
|
||||
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent));
|
||||
} else if (!this.isWhiteListed(gameprofile)) {
|
||||
return Component.translatable("multiplayer.disconnect.not_whitelisted");
|
||||
} else if (this.ipBans.isBanned(socketaddress)) {
|
||||
@@ -454,11 +621,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation) {
|
||||
- return new ServerPlayer(this.server, this.server.overworld(), gameprofile, clientinformation);
|
||||
+ // CraftBukkit start - added EntityPlayer
|
||||
+ public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation, ServerPlayer player) {
|
||||
+ player.updateOptions(clientinformation);
|
||||
+ return player;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile) {
|
||||
+ public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile, ServerPlayer player) { // CraftBukkit - added EntityPlayer
|
||||
+ /* CraftBukkit startMoved up
|
||||
UUID uuid = gameprofile.getId();
|
||||
Set<ServerPlayer> set = Sets.newIdentityHashSet();
|
||||
Iterator iterator = this.players.iterator();
|
||||
@@ -486,15 +657,25 @@
|
||||
}
|
||||
|
||||
return !set.isEmpty();
|
||||
+ */
|
||||
+ return player == null;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- public ServerPlayer respawn(ServerPlayer serverplayer, boolean flag) {
|
||||
- this.players.remove(serverplayer);
|
||||
- serverplayer.serverLevel().removePlayerImmediately(serverplayer, Entity.RemovalReason.DISCARDED);
|
||||
- BlockPos blockpos = serverplayer.getRespawnPosition();
|
||||
- float f = serverplayer.getRespawnAngle();
|
||||
- boolean flag1 = serverplayer.isRespawnForced();
|
||||
- ServerLevel serverlevel = this.server.getLevel(serverplayer.getRespawnDimension());
|
||||
+ // CraftBukkit start
|
||||
+ public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, RespawnReason reason) {
|
||||
+ return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason);
|
||||
+ }
|
||||
+
|
||||
+ public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason) {
|
||||
+ entityplayer.stopRiding(); // CraftBukkit
|
||||
+ this.players.remove(entityplayer);
|
||||
+ entityplayer.serverLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED);
|
||||
+ BlockPos blockposition = entityplayer.getRespawnPosition();
|
||||
+ float f = entityplayer.getRespawnAngle();
|
||||
+ boolean flag1 = entityplayer.isRespawnForced();
|
||||
+ /* CraftBukkit start
|
||||
+ WorldServer worldserver = this.server.getLevel(entityplayer.getRespawnDimension());
|
||||
Optional optional;
|
||||
|
||||
if (serverlevel != null && blockpos != null) {
|
||||
@@ -503,8 +684,13 @@
|
||||
optional = Optional.empty();
|
||||
}
|
||||
|
||||
- ServerLevel serverlevel1 = serverlevel != null && optional.isPresent() ? serverlevel : this.server.overworld();
|
||||
- ServerPlayer serverplayer1 = new ServerPlayer(this.server, serverlevel1, serverplayer.getGameProfile(), serverplayer.clientInformation());
|
||||
+ WorldServer worldserver1 = worldserver != null && optional.isPresent() ? worldserver : this.server.overworld();
|
||||
+ EntityPlayer entityplayer1 = new EntityPlayer(this.server, worldserver1, entityplayer.getGameProfile(), entityplayer.clientInformation());
|
||||
+ // */
|
||||
+ ServerPlayer entityplayer1 = entityplayer;
|
||||
+ org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld();
|
||||
+ entityplayer.wonGame = false;
|
||||
+ // CraftBukkit end
|
||||
|
||||
serverplayer1.connection = serverplayer.connection;
|
||||
serverplayer1.restoreFrom(serverplayer, flag);
|
||||
@@ -520,18 +706,40 @@
|
||||
|
||||
boolean flag2 = false;
|
||||
|
||||
- if (optional.isPresent()) {
|
||||
- BlockState blockstate = serverlevel1.getBlockState(blockpos);
|
||||
- boolean flag3 = blockstate.is(Blocks.RESPAWN_ANCHOR);
|
||||
- Vec3 vec3 = (Vec3) optional.get();
|
||||
- float f1;
|
||||
+ // CraftBukkit start - fire PlayerRespawnEvent
|
||||
+ if (location == null) {
|
||||
+ boolean isBedSpawn = false;
|
||||
+ ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension());
|
||||
+ if (worldserver1 != null) {
|
||||
+ Optional optional;
|
||||
|
||||
if (!blockstate.is(BlockTags.BEDS) && !flag3) {
|
||||
f1 = f;
|
||||
} else {
|
||||
Vec3 vec31 = Vec3.atBottomCenterOf(blockpos).subtract(vec3).normalize();
|
||||
|
||||
- f1 = (float) Mth.wrapDegrees(Mth.atan2(vec31.z, vec31.x) * 57.2957763671875D - 90.0D);
|
||||
+ if (optional.isPresent()) {
|
||||
+ IBlockData iblockdata = worldserver1.getBlockState(blockposition);
|
||||
+ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR);
|
||||
+ Vec3 vec3d = (Vec3) optional.get();
|
||||
+ float f1;
|
||||
+
|
||||
+ if (!iblockdata.is(BlockTags.BEDS) && !flag3) {
|
||||
+ f1 = f;
|
||||
+ } else {
|
||||
+ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize();
|
||||
+
|
||||
+ f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D);
|
||||
+ }
|
||||
+
|
||||
+ // entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); // CraftBukkit - not required, just copies old location into reused entity
|
||||
+ flag2 = !flag && flag3;
|
||||
+ isBedSpawn = true;
|
||||
+ location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F);
|
||||
+ } else if (blockposition != null) {
|
||||
+ entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
|
||||
+ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed
|
||||
+ }
|
||||
}
|
||||
|
||||
serverplayer1.moveTo(vec3.x, vec3.y, vec3.z, f1, 0.0F);
|
||||
@@ -541,31 +764,48 @@
|
||||
serverplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
|
||||
}
|
||||
|
||||
- while (!serverlevel1.noCollision((Entity) serverplayer1) && serverplayer1.getY() < (double) serverlevel1.getMaxBuildHeight()) {
|
||||
- serverplayer1.setPos(serverplayer1.getX(), serverplayer1.getY() + 1.0D, serverplayer1.getZ());
|
||||
+ while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
|
||||
+ // CraftBukkit end
|
||||
+ entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ());
|
||||
}
|
||||
|
||||
int i = flag ? 1 : 0;
|
||||
ServerLevel serverlevel2 = serverplayer1.serverLevel();
|
||||
LevelData leveldata = serverlevel2.getLevelData();
|
||||
|
||||
- serverplayer1.connection.send(new ClientboundRespawnPacket(serverplayer1.createCommonSpawnInfo(serverlevel2), (byte) i));
|
||||
- serverplayer1.connection.teleport(serverplayer1.getX(), serverplayer1.getY(), serverplayer1.getZ(), serverplayer1.getYRot(), serverplayer1.getXRot());
|
||||
- serverplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverlevel1.getSharedSpawnPos(), serverlevel1.getSharedSpawnAngle()));
|
||||
- serverplayer1.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked()));
|
||||
- serverplayer1.connection.send(new ClientboundSetExperiencePacket(serverplayer1.experienceProgress, serverplayer1.totalExperience, serverplayer1.experienceLevel));
|
||||
- this.sendLevelInfo(serverplayer1, serverlevel1);
|
||||
- this.sendPlayerPermissionLevel(serverplayer1);
|
||||
- serverlevel1.addRespawnedPlayer(serverplayer1);
|
||||
- this.players.add(serverplayer1);
|
||||
- this.playersByUUID.put(serverplayer1.getUUID(), serverplayer1);
|
||||
- serverplayer1.initInventoryMenu();
|
||||
- serverplayer1.setHealth(serverplayer1.getHealth());
|
||||
+ entityplayer1.connection.send(new ClientboundRespawnPacket(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i));
|
||||
+ entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit
|
||||
+ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle()));
|
||||
+ entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
|
||||
+ entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel));
|
||||
+ this.sendLevelInfo(entityplayer1, worldserver1);
|
||||
+ this.sendPlayerPermissionLevel(entityplayer1);
|
||||
+ if (!entityplayer.connection.isDisconnected()) {
|
||||
+ worldserver1.addRespawnedPlayer(entityplayer1);
|
||||
+ this.players.add(entityplayer1);
|
||||
+ this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1);
|
||||
+ }
|
||||
+ // entityplayer1.initInventoryMenu();
|
||||
+ entityplayer1.setHealth(entityplayer1.getHealth());
|
||||
if (flag2) {
|
||||
serverplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), 1.0F, 1.0F, serverlevel1.getRandom().nextLong()));
|
||||
}
|
||||
|
||||
- return serverplayer1;
|
||||
+ // Fire advancement trigger
|
||||
+ entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle());
|
||||
+
|
||||
+ // Don't fire on respawn
|
||||
+ if (fromWorld != location.getWorld()) {
|
||||
+ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld);
|
||||
+ server.server.getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ // Save player file again if they were disconnected
|
||||
+ if (entityplayer.connection.isDisconnected()) {
|
||||
+ this.save(entityplayer);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ return entityplayer1;
|
||||
}
|
||||
|
||||
public void sendPlayerPermissionLevel(ServerPlayer serverplayer) {
|
||||
@@ -577,7 +823,18 @@
|
||||
|
||||
public void tick() {
|
||||
if (++this.sendAllPlayerInfoIn > 600) {
|
||||
- this.broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players));
|
||||
+ // CraftBukkit start
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ final ServerPlayer target = (ServerPlayer) this.players.get(i);
|
||||
+
|
||||
+ target.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players.stream().filter(new Predicate<ServerPlayer>() {
|
||||
+ @Override
|
||||
+ public boolean test(ServerPlayer input) {
|
||||
+ return target.getBukkitEntity().canSee(input.getBukkitEntity());
|
||||
+ }
|
||||
+ }).collect(Collectors.toList())));
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.sendAllPlayerInfoIn = 0;
|
||||
}
|
||||
|
||||
@@ -594,7 +851,26 @@
|
||||
|
||||
}
|
||||
|
||||
- public void broadcastAll(Packet<?> packet, ResourceKey<Level> resourcekey) {
|
||||
+ // CraftBukkit start - add a world/entity limited version
|
||||
+ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) {
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ ServerPlayer entityplayer = this.players.get(i);
|
||||
+ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ ((ServerPlayer) this.players.get(i)).connection.send(packet);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void broadcastAll(Packet packet, Level world) {
|
||||
+ for (int i = 0; i < world.players().size(); ++i) {
|
||||
+ ((ServerPlayer) world.players().get(i)).connection.send(packet);
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public void broadcastAll(Packet<?> packet, ResourceKey<Level> dimension) {
|
||||
Iterator iterator = this.players.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -696,7 +972,8 @@
|
||||
serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, b0));
|
||||
}
|
||||
|
||||
- this.server.getCommands().sendCommands(serverplayer);
|
||||
+ player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
|
||||
+ this.server.getCommands().sendCommands(player);
|
||||
}
|
||||
|
||||
public boolean isWhiteListed(GameProfile gameprofile) {
|
||||
@@ -726,10 +1003,11 @@
|
||||
for (int i = 0; i < this.players.size(); ++i) {
|
||||
ServerPlayer serverplayer = (ServerPlayer) this.players.get(i);
|
||||
|
||||
- if (serverplayer != player && serverplayer.level().dimension() == resourcekey) {
|
||||
- double d4 = d0 - serverplayer.getX();
|
||||
- double d5 = d1 - serverplayer.getY();
|
||||
- double d6 = d2 - serverplayer.getZ();
|
||||
+ // CraftBukkit start - Test if player receiving packet can see the source of the packet
|
||||
+ if (except != null && !entityplayer.getBukkitEntity().canSee(except.getBukkitEntity())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) {
|
||||
serverplayer.connection.send(packet);
|
||||
@@ -764,26 +1047,38 @@
|
||||
|
||||
public void reloadWhiteList() {}
|
||||
|
||||
- public void sendLevelInfo(ServerPlayer serverplayer, ServerLevel serverlevel) {
|
||||
- WorldBorder worldborder = this.server.overworld().getWorldBorder();
|
||||
+ public void sendLevelInfo(ServerPlayer player, ServerLevel level) {
|
||||
+ WorldBorder worldborder = player.level().getWorldBorder(); // CraftBukkit
|
||||
|
||||
- serverplayer.connection.send(new ClientboundInitializeBorderPacket(worldborder));
|
||||
- serverplayer.connection.send(new ClientboundSetTimePacket(serverlevel.getGameTime(), serverlevel.getDayTime(), serverlevel.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
|
||||
- serverplayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverlevel.getSharedSpawnPos(), serverlevel.getSharedSpawnAngle()));
|
||||
- if (serverlevel.isRaining()) {
|
||||
- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F));
|
||||
- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, serverlevel.getRainLevel(1.0F)));
|
||||
- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, serverlevel.getThunderLevel(1.0F)));
|
||||
+ player.connection.send(new ClientboundInitializeBorderPacket(worldborder));
|
||||
+ player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
|
||||
+ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
|
||||
+ if (level.isRaining()) {
|
||||
+ // CraftBukkit start - handle player weather
|
||||
+ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F));
|
||||
+ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F)));
|
||||
+ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F)));
|
||||
+ player.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false);
|
||||
+ player.updateWeather(-level.rainLevel, level.rainLevel, -level.thunderLevel, level.thunderLevel);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
|
||||
this.server.tickRateManager().updateJoiningPlayer(serverplayer);
|
||||
}
|
||||
|
||||
- public void sendAllPlayerInfo(ServerPlayer serverplayer) {
|
||||
- serverplayer.inventoryMenu.sendAllDataToRemote();
|
||||
- serverplayer.resetSentInfo();
|
||||
- serverplayer.connection.send(new ClientboundSetCarriedItemPacket(serverplayer.getInventory().selected));
|
||||
+ public void sendAllPlayerInfo(ServerPlayer player) {
|
||||
+ player.inventoryMenu.sendAllDataToRemote();
|
||||
+ // entityplayer.resetSentInfo();
|
||||
+ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange
|
||||
+ player.getEntityData().refresh(player); // CraftBukkkit - SPIGOT-7218: sync metadata
|
||||
+ player.connection.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected));
|
||||
+ // CraftBukkit start - from GameRules
|
||||
+ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
|
||||
+ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i));
|
||||
+ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F;
|
||||
+ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn));
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public int getPlayerCount() {
|
||||
@@ -839,17 +1134,21 @@
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
- for (int i = 0; i < this.players.size(); ++i) {
|
||||
- ((ServerPlayer) this.players.get(i)).connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
|
||||
+ // CraftBukkit start - disconnect safely
|
||||
+ for (ServerPlayer player : this.players) {
|
||||
+ player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
}
|
||||
|
||||
- public void broadcastSystemMessage(Component component, boolean flag) {
|
||||
- this.broadcastSystemMessage(component, (serverplayer) -> {
|
||||
- return component;
|
||||
- }, flag);
|
||||
+ // CraftBukkit start
|
||||
+ public void broadcastMessage(Component[] iChatBaseComponents) {
|
||||
+ for (Component component : iChatBaseComponents) {
|
||||
+ broadcastSystemMessage(component, false);
|
||||
+ }
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
public void broadcastSystemMessage(Component component, Function<ServerPlayer, Component> function, boolean flag) {
|
||||
this.server.sendSystemMessage(component);
|
||||
@@ -902,16 +1207,23 @@
|
||||
return playerchatmessage.hasSignature() && !playerchatmessage.hasExpiredServer(Instant.now());
|
||||
}
|
||||
|
||||
- public ServerStatsCounter getPlayerStats(Player player) {
|
||||
- UUID uuid = player.getUUID();
|
||||
- ServerStatsCounter serverstatscounter = (ServerStatsCounter) this.stats.get(uuid);
|
||||
+ // CraftBukkit start
|
||||
+ public ServerStatsCounter getPlayerStats(ServerPlayer entityhuman) {
|
||||
+ ServerStatsCounter serverstatisticmanager = entityhuman.getStats();
|
||||
+ return serverstatisticmanager == null ? getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager;
|
||||
+ }
|
||||
|
||||
- if (serverstatscounter == null) {
|
||||
+ public ServerStatsCounter getPlayerStats(UUID uuid, String displayName) {
|
||||
+ ServerPlayer entityhuman = this.getPlayer(uuid);
|
||||
+ ServerStatsCounter serverstatisticmanager = entityhuman == null ? null : (ServerStatsCounter) entityhuman.getStats();
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (serverstatisticmanager == null) {
|
||||
File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile();
|
||||
File file1 = new File(file, uuid + ".json");
|
||||
|
||||
if (!file1.exists()) {
|
||||
- File file2 = new File(file, player.getName().getString() + ".json");
|
||||
+ File file2 = new File(file, displayName + ".json"); // CraftBukkit
|
||||
Path path = file2.toPath();
|
||||
|
||||
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
|
||||
@@ -919,22 +1231,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
- serverstatscounter = new ServerStatsCounter(this.server, file1);
|
||||
- this.stats.put(uuid, serverstatscounter);
|
||||
+ serverstatisticmanager = new ServerStatsCounter(this.server, file1);
|
||||
+ // this.stats.put(uuid, serverstatisticmanager); // CraftBukkit
|
||||
}
|
||||
|
||||
return serverstatscounter;
|
||||
}
|
||||
|
||||
- public PlayerAdvancements getPlayerAdvancements(ServerPlayer serverplayer) {
|
||||
- UUID uuid = serverplayer.getUUID();
|
||||
- PlayerAdvancements playeradvancements = (PlayerAdvancements) this.advancements.get(uuid);
|
||||
+ public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
|
||||
+ UUID uuid = player.getUUID();
|
||||
+ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit
|
||||
|
||||
if (playeradvancements == null) {
|
||||
Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uuid + ".json");
|
||||
|
||||
- playeradvancements = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, serverplayer);
|
||||
- this.advancements.put(uuid, playeradvancements);
|
||||
+ advancementdataplayer = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player);
|
||||
+ // this.advancements.put(uuid, advancementdataplayer); // CraftBukkit
|
||||
}
|
||||
|
||||
playeradvancements.setPlayer(serverplayer);
|
||||
@@ -985,13 +1297,20 @@
|
||||
}
|
||||
|
||||
public void reloadResources() {
|
||||
- Iterator iterator = this.advancements.values().iterator();
|
||||
+ // CraftBukkit start
|
||||
+ /*Iterator iterator = this.advancements.values().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
PlayerAdvancements playeradvancements = (PlayerAdvancements) iterator.next();
|
||||
|
||||
- playeradvancements.reload(this.server.getAdvancements());
|
||||
+ advancementdataplayer.reload(this.server.getAdvancements());
|
||||
+ }*/
|
||||
+
|
||||
+ for (ServerPlayer player : players) {
|
||||
+ player.getAdvancements().reload(this.server.getAdvancements());
|
||||
+ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries)));
|
||||
ClientboundUpdateRecipesPacket clientboundupdaterecipespacket = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes());
|
|
@ -0,0 +1,48 @@
|
|||
--- a/net/minecraft/server/players/SleepStatus.java
|
||||
+++ b/net/minecraft/server/players/SleepStatus.java
|
||||
@@ -17,10 +17,13 @@
|
||||
return this.sleepingPlayers >= this.sleepersNeeded(i);
|
||||
}
|
||||
|
||||
- public boolean areEnoughDeepSleeping(int i, List<ServerPlayer> list) {
|
||||
- int j = (int) list.stream().filter(Player::isSleepingLongEnough).count();
|
||||
+ public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List<ServerPlayer> sleepingPlayers) {
|
||||
+ // CraftBukkit start
|
||||
+ int j = (int) sleepingPlayers.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count();
|
||||
+ boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough);
|
||||
|
||||
- return j >= this.sleepersNeeded(i);
|
||||
+ return anyDeepSleep && j >= this.sleepersNeeded(requiredSleepPercentage);
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public int sleepersNeeded(int i) {
|
||||
@@ -41,19 +44,25 @@
|
||||
|
||||
this.activePlayers = 0;
|
||||
this.sleepingPlayers = 0;
|
||||
- Iterator iterator = list.iterator();
|
||||
+ Iterator iterator = players.iterator();
|
||||
+ boolean anySleep = false; // CraftBukkit
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ServerPlayer serverplayer = (ServerPlayer) iterator.next();
|
||||
|
||||
if (!serverplayer.isSpectator()) {
|
||||
++this.activePlayers;
|
||||
- if (serverplayer.isSleeping()) {
|
||||
+ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit
|
||||
++this.sleepingPlayers;
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ if (entityplayer.isSleeping()) {
|
||||
+ anySleep = true;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
|
||||
- return (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers);
|
||||
+ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
--- a/net/minecraft/server/rcon/RconConsoleSource.java
|
||||
+++ b/net/minecraft/server/rcon/RconConsoleSource.java
|
||||
@@ -8,15 +8,23 @@
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
-
|
||||
+// CraftBukkit start
|
||||
+import java.net.SocketAddress;
|
||||
+import org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender;
|
||||
+// CraftBukkit end
|
||||
public class RconConsoleSource implements CommandSource {
|
||||
|
||||
private static final String RCON = "Rcon";
|
||||
private static final Component RCON_COMPONENT = Component.literal("Rcon");
|
||||
private final StringBuffer buffer = new StringBuffer();
|
||||
private final MinecraftServer server;
|
||||
+ // CraftBukkit start
|
||||
+ public final SocketAddress socketAddress;
|
||||
+ private final CraftRemoteConsoleCommandSender remoteConsole = new CraftRemoteConsoleCommandSender(this);
|
||||
|
||||
- public RconConsoleSource(MinecraftServer minecraftserver) {
|
||||
+ public RconConsoleSource(MinecraftServer minecraftserver, SocketAddress socketAddress) {
|
||||
+ this.socketAddress = socketAddress;
|
||||
+ // CraftBukkit end
|
||||
this.server = minecraftserver;
|
||||
}
|
||||
|
||||
@@ -34,7 +42,17 @@
|
||||
return new CommandSourceStack(this, Vec3.atLowerCornerOf(serverlevel.getSharedSpawnPos()), Vec2.ZERO, serverlevel, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - Send a String
|
||||
+ public void sendMessage(String message) {
|
||||
+ this.buffer.append(message);
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) {
|
||||
+ return this.remoteConsole;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
public void sendSystemMessage(Component component) {
|
||||
this.buffer.append(component.getString());
|
|
@ -0,0 +1,74 @@
|
|||
--- a/net/minecraft/server/rcon/thread/RconClient.java
|
||||
+++ b/net/minecraft/server/rcon/thread/RconClient.java
|
||||
@@ -9,6 +10,8 @@
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.server.ServerInterface;
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.rcon.PktUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -24,12 +27,15 @@
|
||||
private final Socket client;
|
||||
private final byte[] buf = new byte[1460];
|
||||
private final String rconPassword;
|
||||
- private final ServerInterface serverInterface;
|
||||
+ // CraftBukkit start
|
||||
+ private final DedicatedServer serverInterface;
|
||||
+ private final RconConsoleSource rconConsoleSource;
|
||||
+ // CraftBukkit end
|
||||
|
||||
- RconClient(ServerInterface serverinterface, String s, Socket socket) {
|
||||
- super("RCON Client " + socket.getInetAddress());
|
||||
- this.serverInterface = serverinterface;
|
||||
- this.client = socket;
|
||||
+ RconClient(ServerInterface serverInterface, String rconPassword, Socket client) {
|
||||
+ super("RCON Client " + client.getInetAddress());
|
||||
+ this.serverInterface = (DedicatedServer) serverInterface; // CraftBukkit
|
||||
+ this.client = client;
|
||||
|
||||
try {
|
||||
this.client.setSoTimeout(0);
|
||||
@@ -37,13 +43,16 @@
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
- this.rconPassword = s;
|
||||
+ this.rconPassword = rconPassword;
|
||||
+ this.rconConsoleSource = new net.minecraft.server.rcon.RconConsoleSource(this.serverInterface, client.getRemoteSocketAddress()); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
- while (true) {
|
||||
- try {
|
||||
+ // CraftBukkit start - decompile error: switch try / while statement
|
||||
+ try {
|
||||
+ while (true) {
|
||||
+ // CraftBukkit end
|
||||
if (!this.running) {
|
||||
return;
|
||||
}
|
||||
@@ -72,7 +80,7 @@
|
||||
String s = PktUtils.stringFromByteArray(this.buf, k, i);
|
||||
|
||||
try {
|
||||
- this.sendCmdResponse(l, this.serverInterface.runCommand(s));
|
||||
+ this.sendCmdResponse(l, this.serverInterface.runCommand(this.rconConsoleSource, s)); // CraftBukkit
|
||||
} catch (Exception exception) {
|
||||
this.sendCmdResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")");
|
||||
}
|
||||
@@ -110,8 +119,10 @@
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
- return;
|
||||
- }
|
||||
+ // CraftBukkit start - decompile error: switch try / while statement
|
||||
+ // return;
|
||||
+ // }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
private void send(int i, int j, String s) throws IOException {
|
|
@ -0,0 +1,28 @@
|
|||
--- a/net/minecraft/stats/ServerRecipeBook.java
|
||||
+++ b/net/minecraft/stats/ServerRecipeBook.java
|
||||
@@ -20,6 +20,8 @@
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
|
||||
+
|
||||
public class ServerRecipeBook extends RecipeBook {
|
||||
|
||||
public static final String RECIPE_BOOK_TAG = "recipeBook";
|
||||
@@ -36,11 +38,11 @@
|
||||
RecipeHolder<?> recipeholder = (RecipeHolder) iterator.next();
|
||||
ResourceLocation resourcelocation = recipeholder.id();
|
||||
|
||||
- if (!this.known.contains(resourcelocation) && !recipeholder.value().isSpecial()) {
|
||||
- this.add(resourcelocation);
|
||||
- this.addHighlight(resourcelocation);
|
||||
- list.add(resourcelocation);
|
||||
- CriteriaTriggers.RECIPE_UNLOCKED.trigger(serverplayer, recipeholder);
|
||||
+ if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial() && CraftEventFactory.handlePlayerRecipeListUpdateEvent(player, minecraftkey)) { // CraftBukkit
|
||||
+ this.add(minecraftkey);
|
||||
+ this.addHighlight(minecraftkey);
|
||||
+ list.add(minecraftkey);
|
||||
+ CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeholder);
|
||||
++i;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
--- a/net/minecraft/stats/StatsCounter.java
|
||||
+++ b/net/minecraft/stats/StatsCounter.java
|
||||
@@ -16,6 +16,12 @@
|
||||
public void increment(Player player, Stat<?> stat, int i) {
|
||||
int j = (int) Math.min((long) this.getValue(stat) + (long) i, 2147483647L);
|
||||
|
||||
+ // CraftBukkit start - fire Statistic events
|
||||
+ org.bukkit.event.Cancellable cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.handleStatisticsIncrease(player, stat, this.getValue(stat), j);
|
||||
+ if (cancellable != null && cancellable.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.setValue(player, stat, j);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
--- a/net/minecraft/util/SpawnUtil.java
|
||||
+++ b/net/minecraft/util/SpawnUtil.java
|
||||
@@ -20,9 +20,15 @@
|
||||
|
||||
public SpawnUtil() {}
|
||||
|
||||
- public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entitytype, MobSpawnType mobspawntype, ServerLevel serverlevel, BlockPos blockpos, int i, int j, int k, SpawnUtil.Strategy spawnutil_strategy) {
|
||||
- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable();
|
||||
+ public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entityType, EnumMobSpawn spawnType, ServerLevel level, BlockPos pos, int attempts, int j, int yOffset, SpawnUtil.Strategy strategy) {
|
||||
+ // CraftBukkit start
|
||||
+ return trySpawnMob(entityType, spawnType, level, pos, attempts, j, yOffset, strategy, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
|
||||
+ public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entitytypes, EnumMobSpawn enummobspawn, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ // CraftBukkit end
|
||||
+ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable();
|
||||
+
|
||||
for (int l = 0; l < i; ++l) {
|
||||
int i1 = Mth.randomBetweenInclusive(serverlevel.random, -j, j);
|
||||
int j1 = Mth.randomBetweenInclusive(serverlevel.random, -j, j);
|
||||
@@ -32,8 +38,8 @@
|
||||
T t0 = (Mob) entitytype.create(serverlevel, (CompoundTag) null, (Consumer) null, blockpos_mutableblockpos, mobspawntype, false, false);
|
||||
|
||||
if (t0 != null) {
|
||||
- if (t0.checkSpawnRules(serverlevel, mobspawntype) && t0.checkSpawnObstruction(serverlevel)) {
|
||||
- serverlevel.addFreshEntityWithPassengers(t0);
|
||||
+ if (t0.checkSpawnRules(worldserver, enummobspawn) && t0.checkSpawnObstruction(worldserver)) {
|
||||
+ worldserver.addFreshEntityWithPassengers(t0, reason); // CraftBukkit
|
||||
return Optional.of(t0);
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
--- a/net/minecraft/util/datafix/DataFixers.java
|
||||
+++ b/net/minecraft/util/datafix/DataFixers.java
|
||||
@@ -455,10 +279,22 @@
|
||||
datafixerbuilder.addFixer(new EntityItemFrameDirectionFix(schema44, false));
|
||||
Schema schema45 = datafixerbuilder.addSchema(1458, DataFixers.SAME_NAMESPACED);
|
||||
|
||||
- datafixerbuilder.addFixer(new EntityCustomNameToComponentFix(schema45, false));
|
||||
- datafixerbuilder.addFixer(new ItemCustomNameToComponentFix(schema45, false));
|
||||
- datafixerbuilder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false));
|
||||
- Schema schema46 = datafixerbuilder.addSchema(1460, V1460::new);
|
||||
+ // CraftBukkit start
|
||||
+ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) {
|
||||
+ @Override
|
||||
+ protected com.mojang.datafixers.TypeRewriteRule makeRule() {
|
||||
+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(DataConverterTypes.PLAYER), (typed) -> {
|
||||
+ return typed.update(DSL.remainderFinder(), (dynamic) -> {
|
||||
+ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic);
|
||||
+ });
|
||||
+ });
|
||||
+ }
|
||||
+ });
|
||||
+ // CraftBukkit end
|
||||
+ builder.addFixer(new EntityCustomNameToComponentFix(schema45, false));
|
||||
+ builder.addFixer(new ItemCustomNameToComponentFix(schema45, false));
|
||||
+ builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false));
|
||||
+ Schema schema46 = builder.addSchema(1460, V1460::new);
|
||||
|
||||
datafixerbuilder.addFixer(new EntityPaintingMotiveFix(schema46, false));
|
||||
Schema schema47 = datafixerbuilder.addSchema(1466, V1466::new);
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java
|
||||
+++ b/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java
|
||||
@@ -33,7 +32,7 @@
|
||||
Typed<?> typed1 = typed.getOrCreateTyped(opticfinder1);
|
||||
Dynamic<?> dynamic1 = (Dynamic) typed1.get(DSL.remainderFinder());
|
||||
|
||||
- dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0)));
|
||||
+ if (!dynamic1.getElement("map").result().isPresent()) dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); // CraftBukkit
|
||||
return typed.set(opticfinder1, typed1.set(DSL.remainderFinder(), dynamic1));
|
||||
} else {
|
||||
return typed;
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java
|
||||
+++ b/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java
|
||||
@@ -377,7 +376,7 @@
|
||||
Typed<?> typed2 = typed.getOrCreateTyped(opticfinder1);
|
||||
Dynamic<?> dynamic1 = (Dynamic) typed2.get(DSL.remainderFinder());
|
||||
|
||||
- dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i));
|
||||
+ if (i != 0) dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); // CraftBukkit
|
||||
typed1 = typed1.set(opticfinder1, typed2.set(DSL.remainderFinder(), dynamic1));
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
--- a/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
+++ b/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
@@ -64,13 +64,13 @@
|
||||
private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
|
||||
private final DimensionDataStorage overworldDataStorage;
|
||||
|
||||
- public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, Registry<LevelStem> registry, boolean flag) {
|
||||
- this.dimensions = registry;
|
||||
- this.levels = (Set) registry.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet());
|
||||
- this.eraseCache = flag;
|
||||
- this.dataFixer = datafixer;
|
||||
- this.levelStorage = levelstoragesource_levelstorageaccess;
|
||||
- this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), datafixer);
|
||||
+ public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelStoarge, DataFixer dataFixer, Registry<LevelStem> dimensions, boolean eraseCache) {
|
||||
+ this.dimensions = dimensions;
|
||||
+ this.levels = (Set) java.util.stream.Stream.of(levelStoarge.dimensionType).map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); // CraftBukkit
|
||||
+ this.eraseCache = eraseCache;
|
||||
+ this.dataFixer = dataFixer;
|
||||
+ this.levelStorage = levelStoarge;
|
||||
+ this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), dataFixer);
|
||||
this.thread = WorldUpgrader.THREAD_FACTORY.newThread(this::work);
|
||||
this.thread.setUncaughtExceptionHandler((thread, throwable) -> {
|
||||
WorldUpgrader.LOGGER.error("Error upgrading world", throwable);
|
||||
@@ -145,10 +145,10 @@
|
||||
if (compoundtag != null) {
|
||||
int j = ChunkStorage.getVersion(compoundtag);
|
||||
ChunkGenerator chunkgenerator = ((LevelStem) this.dimensions.getOrThrow(Registries.levelToLevelStem(resourcekey2))).generator();
|
||||
- CompoundTag compoundtag1 = chunkstorage.upgradeChunkTag(resourcekey2, () -> {
|
||||
+ CompoundTag nbttagcompound1 = ichunkloader.upgradeChunkTag(Registries.levelToLevelStem(resourcekey2), () -> { // CraftBukkit
|
||||
return this.overworldDataStorage;
|
||||
- }, compoundtag, chunkgenerator.getTypeNameForDataFixer());
|
||||
- ChunkPos chunkpos1 = new ChunkPos(compoundtag1.getInt("xPos"), compoundtag1.getInt("zPos"));
|
||||
+ }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer(), chunkcoordintpair, null); // CraftBukkit
|
||||
+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos"));
|
||||
|
||||
if (!chunkpos1.equals(chunkpos)) {
|
||||
WorldUpgrader.LOGGER.warn("Chunk {} has invalid position {}", chunkpos, chunkpos1);
|
|
@ -0,0 +1,57 @@
|
|||
--- a/net/minecraft/world/CompoundContainer.java
|
||||
+++ b/net/minecraft/world/CompoundContainer.java
|
||||
@@ -3,17 +3,42 @@
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import org.bukkit.Location;
|
||||
+
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class CompoundContainer implements Container {
|
||||
|
||||
private final Container container1;
|
||||
private final Container container2;
|
||||
|
||||
- public CompoundContainer(Container container, Container container1) {
|
||||
- this.container1 = container;
|
||||
- this.container2 = container1;
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
+
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ List<ItemStack> result = new ArrayList<ItemStack>(this.getContainerSize());
|
||||
+ for (int i = 0; i < this.getContainerSize(); i++) {
|
||||
+ result.add(this.getItem(i));
|
||||
+ }
|
||||
+ return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
+ public Location getLocation() {
|
||||
+ return container1.getLocation(); // TODO: right?
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ public CompoundContainer(Container container1, Container container2) {
|
||||
+ this.container1 = container1;
|
||||
+ this.container2 = container2;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
return this.container1.getContainerSize() + this.container2.getContainerSize();
|
||||
@@ -61,7 +105,7 @@
|
||||
@Override
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
- return this.container1.getMaxStackSize();
|
||||
+ return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,56 @@
|
|||
--- a/net/minecraft/world/Container.java
|
||||
+++ b/net/minecraft/world/Container.java
|
||||
@@ -6,8 +6,12 @@
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
+// CraftBukkit start
|
||||
+import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+// CraftBukkit end
|
||||
|
||||
public interface Container extends Clearable {
|
||||
|
||||
@@ -26,9 +30,7 @@
|
||||
|
||||
void setItem(int slot, ItemStack stack);
|
||||
|
||||
- default int getMaxStackSize() {
|
||||
- return 64;
|
||||
- }
|
||||
+ int getMaxStackSize(); // CraftBukkit
|
||||
|
||||
void setChanged();
|
||||
|
||||
@@ -88,4 +90,29 @@
|
||||
|
||||
return level == null ? false : (level.getBlockEntity(blockpos) != blockentity ? false : player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) <= (double) (i * i));
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ java.util.List<ItemStack> getContents();
|
||||
+
|
||||
+ void onOpen(CraftHumanEntity who);
|
||||
+
|
||||
+ void onClose(CraftHumanEntity who);
|
||||
+
|
||||
+ java.util.List<org.bukkit.entity.HumanEntity> getViewers();
|
||||
+
|
||||
+ org.bukkit.inventory.InventoryHolder getOwner();
|
||||
+
|
||||
+ void setMaxStackSize(int size);
|
||||
+
|
||||
+ org.bukkit.Location getLocation();
|
||||
+
|
||||
+ default RecipeHolder<?> getCurrentRecipe() {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ default void setCurrentRecipe(RecipeHolder<?> recipe) {
|
||||
+ }
|
||||
+
|
||||
+ int MAX_STACK = 64;
|
||||
+ // CraftBukkit end
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue