Update to 1.19.1

This commit is contained in:
IzzelAliz 2022-08-01 17:08:20 +08:00
parent 7e754e7eec
commit 6a6a573a7d
196 changed files with 2399 additions and 1448 deletions

View File

@ -4,13 +4,14 @@ A Bukkit server implementation utilizing Mixin.
![Actions](https://img.shields.io/github/workflow/status/IzzelAliz/Arclight/Java%20CI%20with%20Gradle?style=flat-square) ![GitHub](https://img.shields.io/github/license/IzzelAliz/Arclight?style=flat-square)
| Minecraft | Forge | Status | Build |
| :----: |:-------:| :---: | :---: |
| 1.18.x | 40.1.59 | ACTIVE | [![1.18 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-18?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-18) |
| 1.17.x | 37.1.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.17/1.0.2) | [![1.17 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-17?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-17) |
| 1.16.x | 36.2.26 | ACTIVE | [![1.16 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-16?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-16) |
| 1.15.x | 31.2.48 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.15/1.0.19) | [![1.15 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-15?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-15) |
| 1.14.x | 28.2.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.0.6) | [![1.14 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight) |
| Minecraft | Forge | Status | Build |
|:---------:|:-------:| :---: |:------------------------------------------------------------------------------------------------------------------------------------------------------:|
| 1.19.x | 42.0.0 | ACTIVE | [![1.19 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-19?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-19) |
| 1.18.x | 40.1.59 | ACTIVE | [![1.18 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-18?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-18) |
| 1.17.x | 37.1.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.17/1.0.2) | [![1.17 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-17?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-17) |
| 1.16.x | 36.2.26 | ACTIVE | [![1.16 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-16?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-16) |
| 1.15.x | 31.2.48 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.15/1.0.19) | [![1.15 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-15?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-15) |
| 1.14.x | 28.2.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.0.6) | [![1.14 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight) |
* Legacy version still accepts pull requests.

View File

@ -24,7 +24,7 @@ apply plugin: 'io.izzel.arclight'
arclight {
mcVersion = minecraftVersion
forgeVersion = project.ext.forgeVersion
bukkitVersion = 'v1_18_R2'
bukkitVersion = 'v1_19_R1'
wipeVersion = true
reobfVersion = true
accessTransformer = project.file('bukkit.at')

View File

@ -1,10 +0,0 @@
package io.izzel.arclight.common.bridge.core.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
public interface NoteBlockBridge {
void bridge$play(Level worldIn, BlockPos pos, BlockState state);
}

View File

@ -1,7 +1,7 @@
package io.izzel.arclight.common.bridge.core.entity;
import io.izzel.arclight.common.bridge.core.command.ICommandSourceBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.core.PositionImpl;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import org.bukkit.craftbukkit.v.entity.CraftEntity;
@ -11,7 +11,7 @@ import java.util.List;
public interface EntityBridge extends ICommandSourceBridge {
Entity bridge$teleportTo(ServerLevel world, BlockPos blockPos);
Entity bridge$teleportTo(ServerLevel world, PositionImpl blockPos);
void bridge$setOnFire(int tick, boolean callEvent);

View File

@ -1,11 +1,8 @@
package io.izzel.arclight.common.bridge.core.entity;
import net.minecraft.core.BlockPos;
import org.bukkit.craftbukkit.v.entity.CraftEntity;
public interface InternalEntityBridge {
CraftEntity internal$getBukkitEntity();
BlockPos internal$capturedPos();
}

View File

@ -1,20 +1,20 @@
package io.izzel.arclight.common.bridge.core.entity;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v.entity.CraftLivingEntity;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import java.util.Optional;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
public interface LivingEntityBridge extends EntityBridge {
void bridge$setSlot(EquipmentSlot slotIn, ItemStack stack, boolean silent);
void bridge$playEquipSound(ItemStack stack, boolean silent);
void bridge$playEquipSound(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem, boolean silent);
boolean bridge$canPickUpLoot();

View File

@ -1,6 +0,0 @@
package io.izzel.arclight.common.bridge.core.entity.ai.attributes;
public interface RangedAttributeBridge {
void bridge$setMaximumValue(double maximumValue);
}

View File

@ -26,10 +26,6 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge {
void bridge$setCompassTarget(Location location);
void bridge$sendMessage(Component[] ichatbasecomponent, UUID uuid);
void bridge$sendMessage(Component component, UUID uuid);
boolean bridge$isJoining();
void bridge$reset();

View File

@ -3,7 +3,6 @@ package io.izzel.arclight.common.bridge.core.network.play;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerTeleportEvent;
// todo
public interface ServerPlayNetHandlerBridge {
void bridge$pushTeleportCause(PlayerTeleportEvent.TeleportCause cause);

View File

@ -1,13 +1,14 @@
package io.izzel.arclight.common.bridge.core.server.management;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
import net.minecraft.world.entity.player.ProfilePublicKey;
import org.bukkit.craftbukkit.v.CraftServer;
import java.net.SocketAddress;
import java.util.List;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
public interface PlayerListBridge {
@ -17,7 +18,7 @@ public interface PlayerListBridge {
CraftServer bridge$getCraftServer();
ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler);
ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler, ProfilePublicKey profilePublicKey);
void bridge$sendMessage(Component[] components);
}

View File

@ -34,4 +34,6 @@ public interface WorldBridge extends IWorldWriterBridge, IWorldBridge {
Object2LongOpenHashMap<SpawnCategory> bridge$ticksPerSpawnCategory();
ResourceKey<LevelStem> bridge$getTypeKey();
void bridge$setLastPhysicsProblem(BlockPos pos);
}

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.bukkit.MaterialBridge;
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraftforge.registries.ForgeRegistries;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.BlockState;
@ -36,6 +37,6 @@ public abstract class CraftBlockMixin {
*/
@Overwrite
public static Biome biomeBaseToBiome(Registry<net.minecraft.world.level.biome.Biome> registry, Holder<net.minecraft.world.level.biome.Biome> base) {
return Biome.valueOf(ResourceLocationUtil.standardize(base.value().getRegistryName()));
return Biome.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.BIOMES.getKey(base.value())));
}
}

View File

@ -56,7 +56,7 @@ public abstract class CraftEntityMixin implements org.bukkit.entity.Entity {
@Override
public @NotNull EntityType getType() {
if (this.arclight$type == null) {
ResourceLocation location = ForgeRegistries.ENTITIES.getKey(entity.getType());
ResourceLocation location = ForgeRegistries.ENTITY_TYPES.getKey(entity.getType());
if (location == null) throw new IllegalArgumentException("Unregistered entity type " + entity.getType());
if (location.getNamespace().equals("minecraft")) {
this.arclight$type = Objects.requireNonNull(EntityType.fromName(location.getPath().toUpperCase(Locale.ROOT)));

View File

@ -13,7 +13,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.players.PlayerList;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.CommandEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.level.LevelEvent;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
@ -112,7 +112,7 @@ public abstract class CraftServerMixin implements CraftServerBridge {
@Inject(method = "unloadWorld(Lorg/bukkit/World;Z)Z", remap = false, require = 1, at = @At(value = "INVOKE", ordinal = 1, target = "Ljava/util/Map;remove(Ljava/lang/Object;)Ljava/lang/Object;"))
private void arclight$unloadForge(World world, boolean save, CallbackInfoReturnable<Boolean> cir) {
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(((CraftWorld) world).getHandle()));
MinecraftForge.EVENT_BUS.post(new LevelEvent.Unload(((CraftWorld) world).getHandle()));
this.console.markWorldsDirty();
}

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.bukkit;
import io.izzel.arclight.common.mod.util.ResourceLocationUtil;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraftforge.registries.ForgeRegistries;
import org.bukkit.craftbukkit.v.entity.CraftVillager;
import org.bukkit.entity.Villager;
import org.spongepowered.asm.mixin.Mixin;
@ -16,6 +17,6 @@ public class CraftVillagerMixin {
*/
@Overwrite
public static Villager.Profession nmsToBukkitProfession(VillagerProfession nms) {
return Villager.Profession.valueOf(ResourceLocationUtil.standardize(nms.getRegistryName()));
return Villager.Profession.valueOf(ResourceLocationUtil.standardize(ForgeRegistries.VILLAGER_PROFESSIONS.getKey(nms)));
}
}

View File

@ -461,7 +461,7 @@ public abstract class MaterialMixin implements MaterialBridge {
private static int tryGetMaxStackSize(Item item) {
try {
return item.getItemStackLimit(new ItemStack(item));
return item.getMaxStackSize(new ItemStack(item));
} catch (Throwable t) {
try {
return item.getMaxStackSize();

View File

@ -1,12 +1,17 @@
package io.izzel.arclight.common.mixin.core.commands;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.tree.CommandNode;
import io.izzel.arclight.common.bridge.core.command.CommandSourceBridge;
import io.izzel.arclight.common.bridge.core.command.ICommandSourceBridge;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.mod.compat.CommandNodeHooks;
import net.minecraft.commands.CommandSource;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.PlayerList;
import net.minecraftforge.common.util.FakePlayer;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v.CraftServer;
@ -16,6 +21,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(CommandSourceStack.class)
@ -38,6 +44,11 @@ public abstract class CommandSourceStackMixin implements CommandSourceBridge {
}
}
@Redirect(method = "broadcastToAdmins", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;isOp(Lcom/mojang/authlib/GameProfile;)Z"))
private boolean arclight$feedbackPermission(PlayerList instance, GameProfile profile) {
return ((ServerPlayerEntityBridge) instance.getPlayer(profile.getId())).bridge$getBukkitEntity().hasPermission("minecraft.admin.command_feedback");
}
public boolean hasPermission(int i, String bukkitPermission) {
// World is null when loading functions
return ((getLevel() == null || !((CraftServer) Bukkit.getServer()).ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission);

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.commands;
import com.google.common.collect.Maps;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
@ -33,7 +34,8 @@ import java.util.Map;
public abstract class CommandsMixin {
// @formatter:off
@Shadow public abstract int performCommand(CommandSourceStack source, String command);
@Shadow public abstract int performCommand(ParseResults<CommandSourceStack> p_242844_, String p_242841_);
@Shadow public abstract int performPrefixedCommand(CommandSourceStack p_230958_, String p_230959_);
@Mutable @Shadow @Final private CommandDispatcher<CommandSourceStack> dispatcher;
@Shadow protected abstract void fillUsableCommands(CommandNode<CommandSourceStack> rootCommandSource, CommandNode<SharedSuggestionProvider> rootSuggestion, CommandSourceStack source, Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode);
// @formatter:on
@ -43,8 +45,12 @@ public abstract class CommandsMixin {
this.dispatcher.setConsumer((context, b, i) -> context.getSource().onCommandComplete(context, b, i));
}
public int performCommand(CommandSourceStack source, String command, String label, boolean strip) {
return this.performCommand(source, command);
public int performPrefixedCommand(CommandSourceStack commandSourceStack, String s, String label) {
return this.performPrefixedCommand(commandSourceStack, s);
}
public int performCommand(ParseResults<CommandSourceStack> parseResults, String s, String label) {
return this.performCommand(parseResults, s);
}
/**

View File

@ -2,6 +2,8 @@ package io.izzel.arclight.common.mixin.core.commands.arguments.blocks;
import com.mojang.brigadier.StringReader;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.core.HolderLookup;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.properties.Property;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -22,7 +24,7 @@ public class BlockStateParserMixin {
// @formatter:on
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(StringReader readerIn, boolean allowTags, CallbackInfo ci) {
private void arclight$init(HolderLookup<Block> registry, StringReader readerIn, boolean forTesting, boolean allowTags, CallbackInfo ci) {
this.properties = new LinkedHashMap<>(properties);
}
}

View File

@ -1,81 +1,10 @@
package io.izzel.arclight.common.mixin.core.commands.synchronization;
import com.mojang.brigadier.arguments.ArgumentType;
import io.netty.buffer.Unpooled;
import net.minecraft.commands.synchronization.ArgumentTypes;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.slf4j.Logger;
import org.spigotmc.SpigotConfig;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Mixin(ArgumentTypes.class)
@Mixin(ArgumentTypeInfos.class)
public abstract class ArgumentTypesMixin {
// @formatter:off
@Shadow @Final private static Logger LOGGER;
@Shadow @Nullable private static ArgumentTypes.Entry<?> get(ArgumentType<?> type) { return null; }
@Shadow @Final private static Map<ResourceLocation, ArgumentTypes.Entry<?>> BY_NAME;
// @formatter:on
private static final Set<ResourceLocation> INTERNAL_TYPES = new HashSet<>();
@Inject(method = "bootStrap", at = @At("HEAD"))
private static void arclight$beginRegister(CallbackInfo ci) {
INTERNAL_TYPES.addAll(BY_NAME.keySet());
}
@Inject(method = "bootStrap", at = @At("RETURN"))
private static void arclight$endRegister(CallbackInfo ci) {
HashSet<ResourceLocation> set = new HashSet<>(BY_NAME.keySet());
set.removeAll(INTERNAL_TYPES);
INTERNAL_TYPES.clear();
INTERNAL_TYPES.addAll(set);
INTERNAL_TYPES.add(new ResourceLocation("forge", "enum"));
INTERNAL_TYPES.add(new ResourceLocation("forge", "modid"));
}
private static boolean arclight$reentrant = false;
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public static <T extends ArgumentType<?>> void serialize(FriendlyByteBuf buffer, T type) {
ArgumentTypes.Entry<T> entry = (ArgumentTypes.Entry<T>) get(type);
if (entry == null) {
LOGGER.error("Could not serialize {} ({}) - will not be sent to client!", type, type.getClass());
buffer.writeResourceLocation(new ResourceLocation(""));
} else {
boolean wrap;
if (!arclight$reentrant && SpigotConfig.bungee && !INTERNAL_TYPES.contains(entry.name)) {
arclight$reentrant = wrap = true;
} else {
wrap = false;
}
if (wrap) {
buffer.writeUtf("arclight:wrapped");
}
buffer.writeResourceLocation(entry.name);
FriendlyByteBuf buf = wrap ? new FriendlyByteBuf(Unpooled.buffer()) : buffer;
entry.serializer.serializeToNetwork(type, buf);
if (wrap) {
buffer.writeVarInt(buf.writerIndex());
buffer.writeBytes(buf);
arclight$reentrant = false;
}
}
}
// TODO FIXME 1.19 command arguments
}

View File

@ -5,6 +5,7 @@ import io.izzel.arclight.common.mod.util.DistValidate;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
@ -21,8 +22,6 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(LavaFluid.class)
public abstract class LavaFluidMixin {
@ -36,7 +35,7 @@ public abstract class LavaFluidMixin {
* @reason
*/
@Overwrite
public void randomTick(Level world, BlockPos pos, FluidState state, Random random) {
public void randomTick(Level world, BlockPos pos, FluidState state, RandomSource random) {
if (world.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
int i = random.nextInt(3);
if (i > 0) {

View File

@ -9,7 +9,6 @@ import net.minecraft.SharedConstants;
import net.minecraft.network.Connection;
import net.minecraft.network.ConnectionProtocol;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.handshake.ClientIntentionPacket;
import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
import net.minecraft.server.MinecraftServer;
@ -61,7 +60,7 @@ public class ServerHandshakeNetHandlerMixin {
synchronized (throttleTracker) {
if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) {
throttleTracker.put(address, currentTime);
TranslatableComponent component = new TranslatableComponent("Connection throttled! Please wait before reconnecting.");
var component = Component.translatable("Connection throttled! Please wait before reconnecting.");
this.connection.send(new ClientboundLoginDisconnectPacket(component));
this.connection.disconnect(component);
return;
@ -79,13 +78,13 @@ public class ServerHandshakeNetHandlerMixin {
if (packetIn.getProtocolVersion() > SharedConstants.getCurrentVersion().getProtocolVersion()) {
TranslatableComponent component = new TranslatableComponent(MessageFormat.format(SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName()));
var component = Component.translatable(MessageFormat.format(SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName()));
this.connection.send(new ClientboundLoginDisconnectPacket(component));
this.connection.disconnect(component);
break;
}
if (packetIn.getProtocolVersion() < SharedConstants.getCurrentVersion().getProtocolVersion()) {
TranslatableComponent component = new TranslatableComponent(MessageFormat.format(SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName()));
var component = Component.translatable(MessageFormat.format(SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName()));
this.connection.send(new ClientboundLoginDisconnectPacket(component));
this.connection.disconnect(component);
break;
@ -100,7 +99,7 @@ public class ServerHandshakeNetHandlerMixin {
this.connection.address = new InetSocketAddress(split[1], ((InetSocketAddress) this.connection.getRemoteAddress()).getPort());
((NetworkManagerBridge) this.connection).bridge$setSpoofedUUID(UUIDTypeAdapter.fromString(split[2]));
} else {
TranslatableComponent component = new TranslatableComponent("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!");
var component = Component.literal("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!");
this.connection.send(new ClientboundLoginDisconnectPacket(component));
this.connection.disconnect(component);
return;

View File

@ -7,15 +7,15 @@ import io.izzel.arclight.common.bridge.core.network.login.ServerLoginNetHandlerB
import io.izzel.arclight.common.bridge.core.server.MinecraftServerBridge;
import io.izzel.arclight.common.bridge.core.server.management.PlayerListBridge;
import net.minecraft.DefaultUncaughtExceptionHandler;
import net.minecraft.core.UUIDUtil;
import net.minecraft.network.Connection;
import net.minecraft.network.PacketSendListener;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.ThrowingComponent;
import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
import net.minecraft.network.protocol.login.ClientboundGameProfilePacket;
import net.minecraft.network.protocol.login.ClientboundHelloPacket;
import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket;
import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
import net.minecraft.network.protocol.login.ServerboundHelloPacket;
import net.minecraft.network.protocol.login.ServerboundKeyPacket;
import net.minecraft.server.MinecraftServer;
@ -23,7 +23,8 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
import net.minecraft.util.Crypt;
import net.minecraft.util.CryptException;
import net.minecraft.world.entity.player.Player;
import net.minecraft.util.SignatureValidator;
import net.minecraft.world.entity.player.ProfilePublicKey;
import net.minecraftforge.fml.util.thread.SidedThreadGroups;
import org.apache.commons.lang3.Validate;
import org.bukkit.Bukkit;
@ -45,10 +46,11 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.PrivateKey;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import static net.minecraft.server.network.ServerLoginPacketListenerImpl.isValidUsername;
@Mixin(ServerLoginPacketListenerImpl.class)
public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandlerBridge {
@ -64,6 +66,8 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
@Shadow public abstract void disconnect(Component reason);
@Shadow public abstract String getUserName();
@Shadow private ServerPlayer delayedAcceptPlayer;
@Shadow @Nullable private ProfilePublicKey.Data profilePublicKeyData;
@Shadow @Nullable private static ProfilePublicKey validatePublicKey(@org.jetbrains.annotations.Nullable ProfilePublicKey.Data p_240244_, UUID p_240245_, SignatureValidator p_240246_, boolean p_240247_) throws ThrowingComponent { return null; }
// @formatter:on
public String hostname;
@ -79,14 +83,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
}
public void disconnect(final String s) {
try {
final Component ichatbasecomponent = new TextComponent(s);
LOGGER.info("Disconnecting {}: {}", this.getUserName(), s);
this.connection.send(new ClientboundLoginDisconnectPacket(ichatbasecomponent));
this.connection.disconnect(ichatbasecomponent);
} catch (Exception exception) {
LOGGER.error("Error whilst disconnecting player", exception);
}
this.disconnect(Component.literal(s));
}
/**
@ -100,16 +97,34 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
this.loginGameProfile = this.getOfflineProfile(this.loginGameProfile);
}
*/
ProfilePublicKey profilePublicKey = null;
ServerPlayer entity = ((PlayerListBridge) this.server.getPlayerList()).bridge$canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile, (ServerLoginPacketListenerImpl) (Object) this);
if (!this.server.usesAuthentication()) {
// this.gameProfile = this.createFakeProfile(this.gameProfile); // Spigot - Moved to initUUID
// Spigot end
} else {
try {
SignatureValidator signaturevalidator = this.server.getServiceSignatureValidator();
profilePublicKey = validatePublicKey(this.profilePublicKeyData, this.gameProfile.getId(), signaturevalidator, this.server.enforceSecureProfile());
} catch (ThrowingComponent e) {
LOGGER.error(e.getMessage(), e.getCause());
if (!this.connection.isMemoryConnection()) {
this.disconnect(e.getComponent());
return;
}
}
}
ServerPlayer entity = ((PlayerListBridge) this.server.getPlayerList()).bridge$canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile, (ServerLoginPacketListenerImpl) (Object) this, profilePublicKey);
if (entity == null) {
// this.disconnect(itextcomponent);
} else {
this.state = ServerLoginPacketListenerImpl.State.ACCEPTED;
if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) {
this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), (p_210149_1_) -> {
this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> {
this.connection.setupCompression(this.server.getCompressionThreshold(), true);
});
}));
}
this.connection.send(new ClientboundGameProfilePacket(this.gameProfile));
@ -123,7 +138,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
}
} catch (Exception exception) {
LOGGER.error("Couldn't place player in world", exception);
TranslatableComponent chatmessage = new TranslatableComponent("multiplayer.disconnect.invalid_player_data");
var chatmessage = Component.translatable("multiplayer.disconnect.invalid_player_data");
this.connection.send(new ClientboundDisconnectPacket(chatmessage));
this.connection.disconnect(chatmessage);
@ -138,31 +153,39 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
@Overwrite
public void handleHello(ServerboundHelloPacket packetIn) {
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
this.gameProfile = packetIn.getGameProfile();
if (this.server.usesAuthentication() && !this.connection.isMemoryConnection()) {
this.state = ServerLoginPacketListenerImpl.State.KEY;
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce));
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
Validate.validState(isValidUsername(packetIn.name()), "Invalid characters in username");
this.profilePublicKeyData = packetIn.publicKey().orElse(null);
GameProfile gameprofile = this.server.getSingleplayerProfile();
if (gameprofile != null && packetIn.name().equalsIgnoreCase(gameprofile.getName())) {
this.gameProfile = gameprofile;
this.state = ServerLoginPacketListenerImpl.State.NEGOTIATING; // FORGE: continue NEGOTIATING, we move to READY_TO_ACCEPT after Forge is ready
} else {
class Handler extends Thread {
this.gameProfile = new GameProfile(null, packetIn.name());
if (this.server.usesAuthentication() && !this.connection.isMemoryConnection()) {
this.state = ServerLoginPacketListenerImpl.State.KEY;
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce));
} else {
class Handler extends Thread {
Handler() {
super(SidedThreadGroups.SERVER, "User Authenticator #" + UNIQUE_THREAD_ID.incrementAndGet());
}
Handler() {
super(SidedThreadGroups.SERVER, "User Authenticator #" + UNIQUE_THREAD_ID.incrementAndGet());
}
@Override
public void run() {
try {
initUUID();
arclight$preLogin();
} catch (Exception ex) {
disconnect("Failed to verify username!");
LOGGER.warn("Exception verifying {} ", gameProfile.getName(), ex);
@Override
public void run() {
try {
initUUID();
arclight$preLogin();
} catch (Exception ex) {
disconnect("Failed to verify username!");
LOGGER.warn("Exception verifying {} ", gameProfile.getName(), ex);
}
}
}
new Handler().start();
}
new Handler().start();
}
}
public void initUUID() {
@ -170,7 +193,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
if (((NetworkManagerBridge) this.connection).bridge$getSpoofedUUID() != null) {
uuid = ((NetworkManagerBridge) this.connection).bridge$getSpoofedUUID();
} else {
uuid = Player.createPlayerUUID(this.gameProfile.getName());
uuid = UUIDUtil.createOfflinePlayerUUID(this.gameProfile.getName());
}
this.gameProfile = new GameProfile(uuid, this.gameProfile.getName());
if (((NetworkManagerBridge) this.connection).bridge$getSpoofedProfile() != null) {
@ -189,11 +212,16 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
@Overwrite
public void handleKey(ServerboundKeyPacket packetIn) {
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.KEY, "Unexpected key packet");
PrivateKey privatekey = this.server.getKeyPair().getPrivate();
final String s;
try {
if (!Arrays.equals(this.nonce, packetIn.getNonce(privatekey))) {
PrivateKey privatekey = this.server.getKeyPair().getPrivate();
if (this.profilePublicKeyData != null) {
ProfilePublicKey profilepublickey = ProfilePublicKey.createTrusted(this.profilePublicKeyData);
if (!packetIn.isChallengeSignatureValid(this.nonce, profilepublickey)) {
throw new IllegalStateException("Protocol error");
}
} else if (!packetIn.isNonceValid(this.nonce, privatekey)) {
throw new IllegalStateException("Protocol error");
}
@ -228,7 +256,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
gameProfile = createFakeProfile(gameprofile);
state = ServerLoginPacketListenerImpl.State.NEGOTIATING;
} else {
disconnect(new TranslatableComponent("multiplayer.disconnect.unverified_username"));
disconnect(Component.translatable("multiplayer.disconnect.unverified_username"));
LOGGER.error("Username '{}' tried to join with an invalid session", gameprofile.getName());
}
} catch (Exception var3) {
@ -237,7 +265,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
gameProfile = createFakeProfile(gameprofile);
state = ServerLoginPacketListenerImpl.State.NEGOTIATING;
} else {
disconnect(new TranslatableComponent("multiplayer.disconnect.authservers_down"));
disconnect(Component.translatable("multiplayer.disconnect.authservers_down"));
LOGGER.error("Couldn't verify username because servers are unavailable");
}
}

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.network;
import com.google.common.base.Charsets;
import com.mojang.brigadier.ParseResults;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge;
@ -10,23 +11,28 @@ import io.izzel.arclight.common.bridge.core.server.MinecraftServerBridge;
import io.izzel.arclight.common.bridge.core.server.management.PlayerInteractionManagerBridge;
import io.izzel.arclight.common.bridge.core.server.management.PlayerListBridge;
import io.izzel.arclight.common.mod.ArclightConstants;
import io.izzel.arclight.common.mod.server.ArclightServer;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import net.minecraft.ChatFormatting;
import net.minecraft.SharedConstants;
import net.minecraft.Util;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.commands.CommandRuntimeException;
import net.minecraft.commands.CommandSigningContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.Connection;
import net.minecraft.network.PacketSendListener;
import net.minecraft.network.chat.ChatDecorator;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.FilterMask;
import net.minecraft.network.chat.LastSeenMessages;
import net.minecraft.network.chat.OutgoingPlayerChatMessage;
import net.minecraft.network.chat.PlayerChatMessage;
import net.minecraft.network.chat.PreviewableCommand;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketUtils;
import net.minecraft.network.protocol.game.*;
@ -34,9 +40,10 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.FilteredText;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.network.TextFilter;
import net.minecraft.server.players.PlayerList;
import net.minecraft.util.FutureChain;
import net.minecraft.util.Mth;
import net.minecraft.util.StringUtil;
import net.minecraft.world.InteractionHand;
@ -71,8 +78,6 @@ import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.ForgeHooks;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@ -97,7 +102,9 @@ import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.SmithItemEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerChatPreviewEvent;
import org.bukkit.event.player.PlayerAnimationEvent;
import org.bukkit.event.player.PlayerAnimationType;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
@ -116,9 +123,11 @@ import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.SmithingInventory;
import org.slf4j.Logger;
import org.spigotmc.SpigotConfig;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -126,12 +135,15 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.UnaryOperator;
import java.util.logging.Level;
@ -174,12 +186,24 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
@Shadow private int dropSpamTickCount;
@Shadow protected abstract boolean noBlocksAround(Entity p_241162_1_);
@Shadow protected abstract boolean isPlayerCollidingWithAnythingNew(LevelReader p_241163_1_, AABB p_241163_2_);
@Shadow protected abstract void updateBookPages(List<TextFilter.FilteredText> p_143635_, UnaryOperator<String> p_143636_, ItemStack p_143637_);
@Shadow private static double clampHorizontal(double p_143610_) { return 0; }
@Shadow private static double clampVertical(double p_143654_) { return 0; }
@Shadow private static boolean containsInvalidValues(double p_143664_, double p_143665_, double p_143666_, float p_143667_, float p_143668_) { return false; }
@Shadow @Final @Mutable private FutureChain chatMessageChain;
@Shadow protected abstract void updateBookPages(List<FilteredText> p_143635_, UnaryOperator<String> p_143636_, ItemStack p_143637_);
@Shadow public abstract void ackBlockChangesUpTo(int p_215202_);
@Shadow private static boolean isChatMessageIllegal(String p_215215_) { return false; }
@Shadow protected abstract boolean tryHandleChat(String p_242372_, Instant p_242311_, LastSeenMessages.Update p_242217_);
@Shadow protected abstract PlayerChatMessage getSignedMessage(ServerboundChatPacket p_242875_);
@Shadow protected abstract boolean verifyChatMessage(PlayerChatMessage p_242942_);
@Shadow protected abstract CompletableFuture<FilteredText> filterTextPacket(String p_243213_);
@Shadow protected abstract ParseResults<CommandSourceStack> parseCommand(String p_242938_);
@Shadow protected abstract Map<String, PlayerChatMessage> collectSignedArguments(ServerboundChatCommandPacket p_242876_, PreviewableCommand<?> p_242848_);
// @formatter:on
@Shadow
protected abstract void detectRateSpam();
private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6;
private static final int CREATIVE_PLACE_DISTANCE_SQUARED = 7 * 7;
private CraftServer cserver;
@ -218,6 +242,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
lastPitch = Float.MAX_VALUE;
lastYaw = Float.MAX_VALUE;
justTeleported = false;
this.chatMessageChain = new FutureChain(ArclightServer.getChatExecutor());
}
/**
@ -233,6 +258,26 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (this.processedDisconnect) {
return;
}
if (!this.cserver.isPrimaryThread()) {
Waitable<?> waitable = new Waitable<>() {
@Override
protected Object evaluate() {
disconnect(s);
return null;
}
};
((MinecraftServerBridge) this.server).bridge$queuedProcess(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(getCraftPlayer(), s, leaveMessage);
if (this.cserver.getServer().isRunning()) {
@ -241,10 +286,9 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (event.isCancelled()) {
return;
}
s = event.getReason();
ArclightCaptures.captureQuitMessage(event.getLeaveMessage());
Component textComponent = CraftChatMessage.fromString(s, true)[0];
this.connection.send(new ClientboundDisconnectPacket(textComponent), future -> this.connection.disconnect(textComponent));
Component textComponent = CraftChatMessage.fromString(event.getReason(), true)[0];
this.connection.send(new ClientboundDisconnectPacket(textComponent), PacketSendListener.thenRun(() -> this.connection.disconnect(textComponent)));
this.onDisconnect(textComponent);
this.connection.setReadOnly();
this.server.executeBlocking(this.connection::handleDisconnection);
@ -263,7 +307,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
public void handleMoveVehicle(final ServerboundMoveVehiclePacket packetplayinvehiclemove) {
PacketUtils.ensureRunningOnSameThread(packetplayinvehiclemove, (ServerGamePacketListenerImpl) (Object) this, this.player.getLevel());
if (containsInvalidValues(packetplayinvehiclemove.getX(), packetplayinvehiclemove.getY(), packetplayinvehiclemove.getZ(), packetplayinvehiclemove.getYRot(), packetplayinvehiclemove.getXRot())) {
this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement"));
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_vehicle_movement"));
} else {
Entity entity = this.player.getRootVehicle();
if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) {
@ -418,7 +462,6 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
this.lastBookTick = ArclightConstants.currentTick - 20;
}
if (this.lastBookTick + 20 > ArclightConstants.currentTick) {
PacketUtils.ensureRunningOnSameThread(packetIn, (ServerGamePacketListenerImpl) (Object) this, this.server);
this.disconnect("Book edited too quickly!");
return;
}
@ -430,7 +473,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
* @reason
*/
@Overwrite
private void updateBookContents(List<TextFilter.FilteredText> list, int slot) {
private void updateBookContents(List<FilteredText> list, int slot) {
ItemStack old = this.player.getInventory().getItem(slot);
if (old.is(Items.WRITABLE_BOOK)) {
ItemStack itemstack = old.copy();
@ -444,7 +487,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
* @reason
*/
@Overwrite
private void signBook(TextFilter.FilteredText text, List<TextFilter.FilteredText> list, int slot) {
private void signBook(FilteredText text, List<FilteredText> list, int slot) {
ItemStack old = this.player.getInventory().getItem(slot);
if (old.is(Items.WRITABLE_BOOK)) {
ItemStack itemStack = new ItemStack(Items.WRITTEN_BOOK);
@ -455,13 +498,13 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
itemStack.addTagElement("author", StringTag.valueOf(this.player.getName().getString()));
if (this.player.isTextFilteringEnabled()) {
itemStack.addTagElement("title", StringTag.valueOf(text.getFiltered()));
itemStack.addTagElement("title", StringTag.valueOf(text.filteredOrEmpty()));
} else {
itemStack.addTagElement("filtered_title", StringTag.valueOf(text.getFiltered()));
itemStack.addTagElement("title", StringTag.valueOf(text.getRaw()));
itemStack.addTagElement("filtered_title", StringTag.valueOf(text.filteredOrEmpty()));
itemStack.addTagElement("title", StringTag.valueOf(text.raw()));
}
this.updateBookPages(list, (p_143659_) -> Component.Serializer.toJson(new TextComponent(p_143659_)), itemStack);
this.updateBookPages(list, (p_143659_) -> Component.Serializer.toJson(Component.literal(p_143659_)), itemStack);
this.player.getInventory().setItem(slot, CraftEventFactory.handleEditBookEvent(this.player, slot, old, itemStack));
}
}
@ -474,7 +517,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
public void handleMovePlayer(ServerboundMovePlayerPacket packetplayinflying) {
PacketUtils.ensureRunningOnSameThread(packetplayinflying, (ServerGamePacketListenerImpl) (Object) this, this.player.getLevel());
if (containsInvalidValues(packetplayinflying.getX(0.0D), packetplayinflying.getY(0.0D), packetplayinflying.getZ(0.0D), packetplayinflying.getYRot(0.0F), packetplayinflying.getXRot(0.0F))) {
this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"));
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"));
} else {
ServerLevel worldserver = this.player.getLevel();
if (!this.player.wonGame && !((ServerPlayerEntityBridge) this.player).bridge$isMovementBlocked()) {
@ -724,7 +767,8 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
case START_DESTROY_BLOCK:
case ABORT_DESTROY_BLOCK:
case STOP_DESTROY_BLOCK: {
this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packetplayinblockdig.getDirection(), this.player.level.getMaxBuildHeight());
this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packetplayinblockdig.getDirection(), this.player.level.getMaxBuildHeight(), packetplayinblockdig.getSequence());
this.player.connection.ackBlockChangesUpTo(packetplayinblockdig.getSequence());
return;
}
default: {
@ -778,6 +822,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (!this.checkLimit(((TimestampedPacket) packet).bridge$timestamp())) {
return;
}
this.ackBlockChangesUpTo(packet.getSequence());
ServerLevel worldserver = this.player.getLevel();
InteractionHand enumhand = packet.getHand();
ItemStack itemstack = this.player.getItemInHand(enumhand);
@ -840,8 +885,8 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
@Redirect(method = "onDisconnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/ChatType;Ljava/util/UUID;)V"))
public void arclight$captureQuit(PlayerList playerList, Component p_232641_1_, ChatType p_232641_2_, UUID p_232641_3_) {
@Redirect(method = "onDisconnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Z)V"))
public void arclight$captureQuit(PlayerList instance, Component p_240618_, boolean p_240644_) {
// do nothing
}
@ -853,8 +898,8 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
@Inject(method = "send(Lnet/minecraft/network/protocol/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V", cancellable = true, at = @At("HEAD"))
private void arclight$updateCompassTarget(Packet<?> packetIn, GenericFutureListener<? extends Future<? super Void>> futureListeners, CallbackInfo ci) {
@Inject(method = "send(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketSendListener;)V", cancellable = true, at = @At("HEAD"))
private void arclight$updateCompassTarget(Packet<?> packetIn, PacketSendListener futureListeners, CallbackInfo ci) {
if (packetIn == null || processedDisconnect) {
ci.cancel();
return;
@ -902,90 +947,99 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (this.server.isStopped()) {
return;
}
String s = StringUtils.normalizeSpace(packet.getMessage());
for (int i = 0; i < s.length(); ++i) {
if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) {
this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"));
if (isChatMessageIllegal(packet.message())) {
this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters"));
} else {
if (this.tryHandleChat(packet.message(), packet.timeStamp(), packet.lastSeenMessages())) {
PlayerChatMessage playerchatmessage = this.getSignedMessage(packet);
if (this.verifyChatMessage(playerchatmessage)) {
this.chatMessageChain.append(() -> {
CompletableFuture<FilteredText> completablefuture = this.filterTextPacket(playerchatmessage.signedContent().plain());
CompletableFuture<PlayerChatMessage> completablefuture1 = ForgeHooks.getServerChatSubmittedDecorator().decorate(this.player, playerchatmessage);
return CompletableFuture.allOf(completablefuture, completablefuture1).thenAcceptAsync((ovoid) -> {
FilterMask filtermask = completablefuture.join().mask();
PlayerChatMessage playerchatmessage1 = completablefuture1.join().filter(filtermask);
this.broadcastChatMessage(playerchatmessage1);
}, ArclightServer.getChatExecutor()); // CraftBukkit - async chat
});
}
}
}
}
@Redirect(method = "queryChatPreview", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraftforge/common/ForgeHooks;getServerChatPreviewDecorator()Lnet/minecraft/network/chat/ChatDecorator;"))
private ChatDecorator arclight$asyncChatPreview() {
return (player, component) -> ForgeHooks.getServerChatPreviewDecorator().decorate(player, component)
.thenApplyAsync(forgeComponent -> {
AsyncPlayerChatPreviewEvent event = new AsyncPlayerChatPreviewEvent(true, ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity(), CraftChatMessage.fromComponent(forgeComponent), new LazyPlayerSet(server));
String originalFormat = event.getFormat(), originalMessage = event.getMessage();
this.cserver.getPluginManager().callEvent(event);
if (originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) {
return forgeComponent;
}
return CraftChatMessage.fromStringOrNull(String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()));
}, ArclightServer.getChatExecutor());
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
private void performChatCommand(ServerboundChatCommandPacket packet) {
String command = "/" + packet.command();
LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command);
PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server));
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
command = event.getMessage().substring(1);
ParseResults<CommandSourceStack> parseresults = this.parseCommand(command);
Map<String, PlayerChatMessage> map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, PreviewableCommand.of(parseresults)) : Collections.emptyMap();
for (PlayerChatMessage playerchatmessage : map.values()) {
if (!this.verifyChatMessage(playerchatmessage)) {
return;
}
}
if (s.startsWith("/")) {
PacketUtils.ensureRunningOnSameThread(packet, (ServerGamePacketListenerImpl) (Object) this, this.player.getLevel());
}
this.handleChat(TextFilter.FilteredText.passThrough(s));
CommandSigningContext commandsigningcontext = new CommandSigningContext.SignedArguments(map);
parseresults = Commands.mapSource(parseresults, (p_242749_) -> {
return p_242749_.withSigningContext(commandsigningcontext);
});
this.server.getCommands().performCommand(parseresults, command);
}
private void handleChat(TextFilter.FilteredText text) {
if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) {
this.send(new ClientboundChatPacket((new TranslatableComponent("chat.cannotSend")).withStyle(ChatFormatting.RED), ChatType.SYSTEM, Util.NIL_UUID));
} else {
this.player.resetLastActionTime();
String s = text.getRaw();
boolean isSync = s.startsWith("/");
if (isSync) {
try {
this.cserver.playerCommandState = true;
this.handleCommand(s);
} finally {
this.cserver.playerCommandState = false;
}
} else if (s.isEmpty()) {
LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message");
} else if (this.getCraftPlayer().isConversing()) {
String conversationInput = s;
((MinecraftServerBridge) this.server).bridge$queuedProcess(() -> this.getCraftPlayer().acceptConversationInput(conversationInput));
} else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) {
this.send(new ClientboundChatPacket((new TranslatableComponent("chat.cannotSend")).withStyle(ChatFormatting.RED), ChatType.SYSTEM, Util.NIL_UUID));
} else {
this.chat(s, true);
}
boolean counted = true;
for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
if (exclude != null && s.startsWith(exclude)) {
counted = false;
break;
}
}
if (counted) {
this.chatSpamTickCount += 20;
if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
if (!isSync) {
class Disconnect2 extends Waitable {
@Override
protected Object evaluate() {
disconnect(new TranslatableComponent("disconnect.spam"));
return null;
}
}
Waitable waitable2 = new Disconnect2();
((MinecraftServerBridge) this.server).bridge$queuedProcess(waitable2);
try {
waitable2.get();
return;
} catch (InterruptedException e4) {
Thread.currentThread().interrupt();
return;
} catch (ExecutionException e2) {
throw new RuntimeException(e2);
}
}
this.disconnect(new TranslatableComponent("disconnect.spam"));
}
}
@Inject(method = "tryHandleChat", cancellable = true, at = @At("HEAD"))
private void arclight$deadMenTellNoTales(String p_242372_, Instant p_242311_, LastSeenMessages.Update p_242217_, CallbackInfoReturnable<Boolean> cir) {
if (this.player.isRemoved()) {
this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false));
cir.setReturnValue(false);
}
}
public void chat(String s, boolean async) {
// TODO ChatType.RAW
public void chat(String s, PlayerChatMessage original, boolean async) {
if (s.isEmpty() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) {
return;
}
ServerGamePacketListenerImpl handler = (ServerGamePacketListenerImpl) (Object) this;
OutgoingPlayerChatMessage outgoing = OutgoingPlayerChatMessage.create(original);
if (!async && s.startsWith("/")) {
this.handleCommand(s);
} else if (this.player.getChatVisibility() != ChatVisiblity.SYSTEM) {
Player thisPlayer = this.getCraftPlayer();
AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, thisPlayer, s, new LazyPlayerSet(this.server));
String originalFormat = event.getFormat(), originalMessage = event.getMessage();
this.cserver.getPluginManager().callEvent(event);
if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) {
PlayerChatEvent queueEvent = new PlayerChatEvent(thisPlayer, event.getMessage(), event.getFormat(), event.getRecipients());
@ -996,22 +1050,32 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
protected Object evaluate() {
Bukkit.getPluginManager().callEvent(queueEvent);
if (queueEvent.isCancelled()) {
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
return null;
}
String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage());
var event = ForgeHooks.onServerChatEvent(handler, queueEvent.getMessage(), ForgeHooks.newChatWithLinks(message), queueEvent.getMessage(), ForgeHooks.newChatWithLinks(message));
var component = event == null ? null : event.getComponent();
if (component == null) return null;
Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component));
if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) {
for (ServerPlayer player : server.getPlayerList().players) {
((ServerPlayerEntityBridge) player).bridge$sendMessage(component, thisPlayer.getUniqueId());
if (!org.spigotmc.SpigotConfig.bungee && originalFormat.equals(queueEvent.getFormat()) && originalMessage.equals(queueEvent.getMessage()) && queueEvent.getPlayer().getName().equalsIgnoreCase(queueEvent.getPlayer().getDisplayName())) { // Spigot
server.getPlayerList().broadcastChatMessage(original, player, ChatType.bind(ChatType.CHAT, player));
return null;
} else if (!org.spigotmc.SpigotConfig.bungee && CraftChatMessage.fromComponent(original.serverContent()).equals(message)) { // Spigot
// TODO server.getPlayerList().broadcastChatMessage(original, player, ChatType.bind(ChatType.RAW, player));
return null;
}
for (ServerPlayer recipient : server.getPlayerList().players) {
((ServerPlayerEntityBridge) recipient).bridge$getBukkitEntity().sendMessage(player.getUUID(), message);
}
} else {
for (Player player2 : queueEvent.getRecipients()) {
((ServerPlayerEntityBridge) ((CraftPlayer) player2).getHandle()).bridge$sendMessage(component, thisPlayer.getUniqueId());
player2.sendMessage(thisPlayer.getUniqueId(), message);
}
}
Bukkit.getConsoleSender().sendMessage(message);
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
return null;
}
}
@ -1032,45 +1096,38 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
if (event.isCancelled()) {
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
return;
}
s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
Component chatWithLinks = ForgeHooks.newChatWithLinks(s);
class ForgeChat extends Waitable<Void> {
@Override
protected Void evaluate() {
// this is called on main thread
var chatEvent = ForgeHooks.onServerChatEvent(handler, event.getMessage(), chatWithLinks, event.getMessage(), chatWithLinks);
var component = chatEvent != null ? chatEvent.getComponent() : null;
if (component == null) return null;
Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component));
if (((LazyPlayerSet) event.getRecipients()).isLazy()) {
for (ServerPlayer recipient : server.getPlayerList().players) {
((ServerPlayerEntityBridge) recipient).bridge$sendMessage(component, thisPlayer.getUniqueId());
}
} else {
for (Player recipient2 : event.getRecipients()) {
((ServerPlayerEntityBridge) ((CraftPlayer) recipient2).getHandle()).bridge$sendMessage(component, thisPlayer.getUniqueId());
}
}
return null;
s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
if (((LazyPlayerSet) event.getRecipients()).isLazy()) {
if (!org.spigotmc.SpigotConfig.bungee && originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) { // Spigot
server.getPlayerList().broadcastChatMessage(original, player, ChatType.bind(ChatType.CHAT, player));
return;
} else if (!org.spigotmc.SpigotConfig.bungee && CraftChatMessage.fromComponent(original.serverContent()).equals(s)) { // Spigot
// TODO server.getPlayerList().broadcastChatMessage(original, player, ChatType.bind(ChatType.RAW, player));
return;
}
for (ServerPlayer recipient : server.getPlayerList().players) {
((ServerPlayerEntityBridge) recipient).bridge$getBukkitEntity().sendMessage(player.getUUID(), s);
}
} else {
for (Player recipient : event.getRecipients()) {
recipient.sendMessage(player.getUUID(), s);
}
}
Waitable<Void> waitable = new ForgeChat();
if (async) {
((MinecraftServerBridge) server).bridge$queuedProcess(waitable);
} else {
waitable.run();
Bukkit.getConsoleSender().sendMessage(s);
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
}
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
private void handleCommand(String s) {
if (SpigotConfig.logCommands) {
LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s);
@ -1089,6 +1146,27 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
private void broadcastChatMessage(PlayerChatMessage playerchatmessage) {
String s = playerchatmessage.signedContent().plain();
if (s.isEmpty()) {
LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message");
} else if (getCraftPlayer().isConversing()) {
final String conversationInput = s;
((MinecraftServerBridge) this.server).bridge$queuedProcess(() -> getCraftPlayer().acceptConversationInput(conversationInput));
} else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check
this.send(new ClientboundSystemChatPacket(Component.translatable("chat.cannotSend").withStyle(ChatFormatting.RED), false));
} else {
this.chat(s, playerchatmessage, true);
}
// this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player));
this.detectRateSpam();
}
/**
* @author IzzelAliz
* @reason
@ -1118,7 +1196,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (result == null || result.getType() != HitResult.Type.BLOCK) {
CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
}
PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer());
PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), packet.getHand() == InteractionHand.MAIN_HAND ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING);
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
@ -1184,7 +1262,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
// Fish bucket - SPIGOT-4048
if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) {
send(new ClientboundAddMobPacket((LivingEntity) entity));
send(new ClientboundAddEntityPacket((LivingEntity) entity));
player.containerMenu.sendAllDataToRemote();
}
@ -1247,7 +1325,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
player.containerMenu.sendAllDataToRemote();
}
} else {
disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"));
disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked"));
LOGGER.warn("Player {} tried to attack an invalid entity", player.getName().getString());
}
}
@ -1279,6 +1357,8 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if
if (false/*this.player.isSpectator()*/) { // CraftBukkit
this.player.containerMenu.sendAllDataToRemote();
} else if (!this.player.containerMenu.stillValid(this.player)) {
LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu);
} else {
boolean flag = packet.getStateId() != this.player.containerMenu.getStateId();
@ -1599,9 +1679,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
final CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack);
if (!itemstack.isEmpty() && nbttagcompound != null && nbttagcompound.contains("x") && nbttagcompound.contains("y") && nbttagcompound.contains("z")) {
BlockPos blockpos = BlockEntity.getPosFromTag(nbttagcompound);
BlockEntity blockentity = this.player.level.getBlockEntity(blockpos);
if (blockentity != null) {
blockentity.saveToItem(itemstack);
if (this.player.level.isLoaded(blockpos)) {
BlockEntity blockentity = this.player.level.getBlockEntity(blockpos);
if (blockentity != null) {
blockentity.saveToItem(itemstack);
}
}
}
final boolean flag2 = packetplayinsetcreativeslot.getSlotNum() >= 1 && packetplayinsetcreativeslot.getSlotNum() <= 45;
@ -1653,7 +1735,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
* @reason
*/
@Overwrite
private void updateSignText(ServerboundSignUpdatePacket packet, List<TextFilter.FilteredText> list) {
private void updateSignText(ServerboundSignUpdatePacket packet, List<FilteredText> list) {
if (((ServerPlayerEntityBridge) player).bridge$isMovementBlocked()) {
return;
}
@ -1680,12 +1762,12 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
String[] lines = new String[4];
for (int i = 0; i < list.size(); ++i) {
TextFilter.FilteredText text = list.get(i);
FilteredText text = list.get(i);
if (this.player.isTextFilteringEnabled()) {
lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(text.getFiltered())).getString());
lines[i] = ChatFormatting.stripFormatting(text.filteredOrEmpty());
} else {
lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(text.getRaw())).getString());
lines[i] = ChatFormatting.stripFormatting(text.raw());
}
}
SignChangeEvent event = new SignChangeEvent(player.getWorld().getBlockAt(x, y, z), player, lines);
@ -1703,11 +1785,6 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
@Inject(method = "handleKeepAlive", at = @At("HEAD"))
private void arclight$syncKeepAlive(ServerboundKeepAlivePacket packetIn, CallbackInfo ci) {
PacketUtils.ensureRunningOnSameThread(packetIn, (ServerGamePacketListenerImpl) (Object) this, this.player.getLevel());
}
/**
* @author IzzelAliz
* @reason
@ -1729,6 +1806,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register");
private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister");
// TODO FIXME handle custom payload on main thread
@Inject(method = "handleCustomPayload", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraftforge/network/NetworkHooks;onCustomPayload(Lnet/minecraftforge/network/ICustomPacket;Lnet/minecraft/network/Connection;)Z"))
private void arclight$customPayload(ServerboundCustomPayloadPacket packet, CallbackInfo ci) {
if (packet.identifier.equals(CUSTOM_REGISTER)) {

View File

@ -54,6 +54,7 @@ public class ServerStatusNetHandlerMixin {
playerSample.setSample(profiles.toArray(new GameProfile[0]));
}
ServerStatus ping = new ServerStatus();
ping.setPreviewsChat(event.shouldSendChatPreviews());
ping.setFavicon(event.icon.value);
ping.setDescription(CraftChatMessage.fromString(event.getMotd(), true)[0]);
ping.setPlayers(playerSample);

View File

@ -1,32 +0,0 @@
package io.izzel.arclight.common.mixin.core.network.protocol.game;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.minecraft.network.protocol.game.ServerGamePacketListener;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Mixin(ServerboundChatPacket.class)
public class CChatMessagePacketMixin {
@Shadow @Final private String message;
private static final ExecutorService executors = Executors.newCachedThreadPool(
new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()
);
@Inject(method = "handle(Lnet/minecraft/network/protocol/game/ServerGamePacketListener;)V", cancellable = true, at = @At("HEAD"))
private void arclight$asyncChat(ServerGamePacketListener handler, CallbackInfo ci) {
if (!this.message.startsWith("/")) {
executors.submit(() -> handler.handleChat((ServerboundChatPacket) (Object) this));
ci.cancel();
}
}
}

View File

@ -1,41 +0,0 @@
package io.izzel.arclight.common.mixin.core.network.protocol.game;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundChatPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.io.IOException;
import java.util.UUID;
@Mixin(ClientboundChatPacket.class)
public class SChatPacketMixin {
// @formatter:off
@Shadow private Component message;
@Shadow private ChatType type;
@Shadow private UUID sender;
// @formatter:on
public BaseComponent[] components;
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public void write(FriendlyByteBuf buf) throws IOException {
if (components != null) {
buf.writeUtf(ComponentSerializer.toString(components));
} else {
buf.writeComponent(this.message);
}
buf.writeByte(this.type.getIndex());
buf.writeUUID(this.sender);
}
}

View File

@ -1,8 +1,6 @@
package io.izzel.arclight.common.mixin.core.server;
import com.google.common.collect.ImmutableList;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.DynamicOps;
import io.izzel.arclight.common.bridge.core.command.ICommandSourceBridge;
@ -26,7 +24,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.status.ServerStatus;
import net.minecraft.obfuscate.DontObfuscate;
import net.minecraft.resources.RegistryOps;
@ -34,6 +32,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ReloadableServerResources;
import net.minecraft.server.ServerFunctionManager;
import net.minecraft.server.Services;
import net.minecraft.server.TickTask;
import net.minecraft.server.WorldStem;
import net.minecraft.server.level.ServerChunkCache;
@ -46,7 +45,6 @@ import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.server.packs.resources.CloseableResourceManager;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.server.players.GameProfileCache;
import net.minecraft.server.players.PlayerList;
import net.minecraft.util.Unit;
import net.minecraft.util.profiling.ProfilerFiller;
@ -58,11 +56,12 @@ import net.minecraft.world.level.ForcedChunksSavedData;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WorldData;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.internal.BrandingControl;
import net.minecraftforge.server.ServerLifecycleHooks;
import org.bukkit.Bukkit;
@ -93,10 +92,8 @@ import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.Proxy;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@ -142,7 +139,6 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
@Shadow protected abstract void endMetricsRecordingTick();
@Shadow public abstract SystemReport fillSystemReport(SystemReport p_177936_);
@Shadow private float averageTickTime;
@Shadow @Final @Nullable private GameProfileCache profileCache;
@Shadow @Final private PackRepository packRepository;
@Shadow public abstract boolean isDedicatedServer();
@Shadow public abstract int getFunctionCompilationLevel();
@ -152,7 +148,11 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
@Shadow private static DataPackConfig getSelectedPacks(PackRepository p_129818_) { return null; }
@Shadow public abstract PlayerList getPlayerList();
@Shadow @Final private ServerFunctionManager functionManager;
@Shadow @Final private StructureManager structureManager;
@Shadow public abstract boolean previewsChat();
@Shadow public abstract boolean enforceSecureProfile();
@Shadow @Final protected Services services;
@Shadow private static CrashReport constructOrExtractCrashReport(Throwable p_206569_) { return null; }
@Shadow @Final private StructureTemplateManager structureTemplateManager;
// @formatter:on
public MinecraftServerMixin(String name) {
@ -190,7 +190,7 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
}
@Inject(method = "<init>", at = @At("RETURN"))
public void arclight$loadOptions(Thread p_206546_, LevelStorageSource.LevelStorageAccess p_206547_, PackRepository p_206548_, WorldStem p_206549_, Proxy p_206550_, DataFixer p_206551_, @Nullable MinecraftSessionService p_206552_, @Nullable GameProfileRepository p_206553_, @Nullable GameProfileCache p_206554_, ChunkProgressListenerFactory p_206555_, CallbackInfo ci) {
public void arclight$loadOptions(Thread p_236723_, LevelStorageSource.LevelStorageAccess p_236724_, PackRepository p_236725_, WorldStem worldStem, Proxy p_236727_, DataFixer p_236728_, Services p_236729_, ChunkProgressListenerFactory p_236730_, CallbackInfo ci) {
String[] arguments = ManagementFactory.getRuntimeMXBean().getInputArguments().toArray(new String[0]);
OptionParser parser = new BukkitOptionParser();
try {
@ -199,8 +199,8 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
e.printStackTrace();
}
this.datapackconfiguration = ArclightCaptures.getDatapackConfig();
this.registryreadops = RegistryOps.create(NbtOps.INSTANCE, p_206549_.registryAccess());
this.vanillaCommandDispatcher = p_206549_.dataPackResources().getCommands();
this.registryreadops = RegistryOps.create(NbtOps.INSTANCE, worldStem.registryAccess());
this.vanillaCommandDispatcher = worldStem.dataPackResources().getCommands();
}
/**
@ -210,81 +210,70 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
@Overwrite
protected void runServer() {
try {
if (this.initServer()) {
ServerLifecycleHooks.handleServerStarted((MinecraftServer) (Object) this);
this.nextTickTime = Util.getMillis();
this.status.setDescription(new TextComponent(this.motd));
this.status.setVersion(new ServerStatus.Version(SharedConstants.getCurrentVersion().getName(), SharedConstants.getCurrentVersion().getProtocolVersion()));
this.updateStatusIcon(this.status);
Arrays.fill(recentTps, 20);
long curTime, tickSection = Util.getMillis(), tickCount = 1;
while (this.running) {
long i = (curTime = Util.getMillis()) - this.nextTickTime;
if (i > 2000L && this.nextTickTime - this.lastOverloadWarning >= 15000L) {
long j = i / 50L;
if (server.getWarnOnOverload()) {
LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j);
}
this.nextTickTime += j * 50L;
this.lastOverloadWarning = this.nextTickTime;
}
if (tickCount++ % SAMPLE_INTERVAL == 0) {
double currentTps = 1E3 / (curTime - tickSection) * SAMPLE_INTERVAL;
recentTps[0] = calcTps(recentTps[0], 0.92, currentTps); // 1/exp(5sec/1min)
recentTps[1] = calcTps(recentTps[1], 0.9835, currentTps); // 1/exp(5sec/5min)
recentTps[2] = calcTps(recentTps[2], 0.9945, currentTps); // 1/exp(5sec/15min)
tickSection = curTime;
}
currentTick = (int) (System.currentTimeMillis() / 50);
this.nextTickTime += 50L;
this.startMetricsRecordingTick();
this.profiler.push("tick");
this.tickServer(this::haveTime);
this.profiler.popPush("nextTickWait");
this.mayHaveDelayedTasks = true;
this.delayedTasksMaxNextTickTime = Math.max(Util.getMillis() + 50L, this.nextTickTime);
this.waitUntilNextTick();
this.profiler.pop();
this.endMetricsRecordingTick();
this.isReady = true;
JvmProfiler.INSTANCE.onServerTick(this.averageTickTime);
}
ServerLifecycleHooks.handleServerStopping((MinecraftServer) (Object) this);
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
} else {
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
this.onServerCrash(null);
if (!this.initServer()) {
throw new IllegalStateException("Failed to initialize server");
}
ServerLifecycleHooks.handleServerStarted((MinecraftServer) (Object) this);
this.nextTickTime = Util.getMillis();
this.status.setDescription(Component.literal(this.motd));
this.status.setVersion(new ServerStatus.Version(SharedConstants.getCurrentVersion().getName(), SharedConstants.getCurrentVersion().getProtocolVersion()));
this.status.setPreviewsChat(this.previewsChat());
this.status.setEnforcesSecureChat(this.enforceSecureProfile());
this.updateStatusIcon(this.status);
Arrays.fill(recentTps, 20);
long curTime, tickSection = Util.getMillis(), tickCount = 1;
while (this.running) {
long i = (curTime = Util.getMillis()) - this.nextTickTime;
if (i > 2000L && this.nextTickTime - this.lastOverloadWarning >= 15000L) {
long j = i / 50L;
if (server.getWarnOnOverload()) {
LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j);
}
this.nextTickTime += j * 50L;
this.lastOverloadWarning = this.nextTickTime;
}
if (tickCount++ % SAMPLE_INTERVAL == 0) {
double currentTps = 1E3 / (curTime - tickSection) * SAMPLE_INTERVAL;
recentTps[0] = calcTps(recentTps[0], 0.92, currentTps); // 1/exp(5sec/1min)
recentTps[1] = calcTps(recentTps[1], 0.9835, currentTps); // 1/exp(5sec/5min)
recentTps[2] = calcTps(recentTps[2], 0.9945, currentTps); // 1/exp(5sec/15min)
tickSection = curTime;
}
currentTick = (int) (System.currentTimeMillis() / 50);
this.nextTickTime += 50L;
this.startMetricsRecordingTick();
this.profiler.push("tick");
this.tickServer(this::haveTime);
this.profiler.popPush("nextTickWait");
this.mayHaveDelayedTasks = true;
this.delayedTasksMaxNextTickTime = Math.max(Util.getMillis() + 50L, this.nextTickTime);
this.waitUntilNextTick();
this.profiler.pop();
this.endMetricsRecordingTick();
this.isReady = true;
JvmProfiler.INSTANCE.onServerTick(this.averageTickTime);
}
ServerLifecycleHooks.handleServerStopping((MinecraftServer) (Object) this);
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
} catch (Throwable throwable1) {
LOGGER.error("Encountered an unexpected exception", throwable1);
if (throwable1.getCause() != null) {
LOGGER.error("\tCause of unexpected exception was", throwable1.getCause());
}
CrashReport crashreport;
if (throwable1 instanceof ReportedException) {
crashreport = ((ReportedException) throwable1).getReport();
} else {
crashreport = new CrashReport("Exception in server tick loop", throwable1);
}
CrashReport crashreport = constructOrExtractCrashReport(throwable1);
this.fillSystemReport(crashreport.getSystemReport());
File file1 = new File(new File(this.getServerDirectory(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt");
File file1 = new File(new File(this.getServerDirectory(), "crash-reports"), "crash-" + Util.getFilenameFormattedDateTime() + "-server.txt");
if (crashreport.saveToFile(file1)) {
LOGGER.error("This crash report has been saved to: {}", file1.getAbsolutePath());
} else {
LOGGER.error("We were unable to save this crash report to disk.");
}
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
net.minecraftforge.server.ServerLifecycleHooks.expectServerStopped(); // Forge: Has to come before MinecraftServer#onServerCrash to avoid race conditions
this.onServerCrash(crashreport);
} finally {
try {
@ -293,8 +282,8 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
} catch (Throwable throwable) {
LOGGER.error("Exception stopping the server", throwable);
} finally {
if (this.profileCache != null) {
this.profileCache.clearExecutor();
if (this.services.profileCache() != null) {
this.services.profileCache().clearExecutor();
}
WatchdogThread.doStop();
ServerLifecycleHooks.handleServerStopped((MinecraftServer) (Object) this);
@ -451,7 +440,7 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
// bukkit methods
public void prepareLevels(ChunkProgressListener listener, ServerLevel serverWorld) {
this.markWorldsDirty();
MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(serverWorld));
MinecraftForge.EVENT_BUS.post(new LevelEvent.Load(serverWorld));
if (!((WorldBridge) serverWorld).bridge$getWorld().getKeepSpawnInMemory()) {
return;
}
@ -513,16 +502,16 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
}, this).thenCompose((p_212913_) -> {
CloseableResourceManager closeableresourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, p_212913_);
return ReloadableServerResources.loadResources(closeableresourcemanager, registryaccess$frozen, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((p_212907_, p_212908_) -> {
if (p_212908_ != null) {
closeableresourcemanager.close();
}
if (p_212908_ != null) {
closeableresourcemanager.close();
}
}).thenApply((p_212904_) -> {
return new MinecraftServer.ReloadableResources(closeableresourcemanager, p_212904_);
return new MinecraftServer.ReloadableResources(closeableresourcemanager, p_212904_);
});
}).thenAcceptAsync((p_212919_) -> {
this.resources.close();
this.resources= p_212919_;
this.resources = p_212919_;
this.server.syncCommands();
this.packRepository.setSelected(p_129862_);
this.worldData.setDataPackConfig(getSelectedPacks(this.packRepository));
@ -530,7 +519,7 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
this.getPlayerList().saveAll();
this.getPlayerList().reloadResources();
this.functionManager.replaceLibrary(this.resources.managers().getFunctionLibrary());
this.structureManager.onResourceManagerReload(this.resources.resourceManager());
this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager());
this.getPlayerList().getPlayers().forEach(this.getPlayerList()::sendPlayerPermissionLevel); //Forge: Fix newly added/modified commands not being sent to the client when commands reload.
}, this);
if (this.isSameThread()) {

View File

@ -0,0 +1,21 @@
package io.izzel.arclight.common.mixin.core.server;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldLoader;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.world.level.DataPackConfig;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(WorldLoader.PackConfig.class)
public class WorldLoader_PackConfigMixin {
@Redirect(method = "createResourceManager", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;configurePackRepository(Lnet/minecraft/server/packs/repository/PackRepository;Lnet/minecraft/world/level/DataPackConfig;Z)Lnet/minecraft/world/level/DataPackConfig;"))
private DataPackConfig arclight$capturePack(PackRepository s, DataPackConfig s1, boolean pack) {
var dataPackConfig = MinecraftServer.configurePackRepository(s, s1, pack);
ArclightCaptures.captureDatapackConfig(dataPackConfig);
return dataPackConfig;
}
}

View File

@ -1,21 +0,0 @@
package io.izzel.arclight.common.mixin.core.server;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldStem;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.world.level.DataPackConfig;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(WorldStem.class)
public class WorldStemMixin {
@Redirect(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;configurePackRepository(Lnet/minecraft/server/packs/repository/PackRepository;Lnet/minecraft/world/level/DataPackConfig;Z)Lnet/minecraft/world/level/DataPackConfig;"))
private static DataPackConfig arclight$captureDatapackCodec(PackRepository p_240772_0_, DataPackConfig p_240772_1_, boolean p_240772_2_) {
DataPackConfig datapackCodec = MinecraftServer.configurePackRepository(p_240772_0_, p_240772_1_, p_240772_2_);
ArclightCaptures.captureDatapackConfig(datapackCodec);
return datapackCodec;
}
}

View File

@ -53,7 +53,7 @@ public abstract class DedicatedServerMixin extends MinecraftServerMixin {
this.remoteConsole = new CraftRemoteConsoleCommandSender(this.rconConsoleSource);
}
@Redirect(method = "handleConsoleInputs", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;performCommand(Lnet/minecraft/commands/CommandSourceStack;Ljava/lang/String;)I"))
@Redirect(method = "handleConsoleInputs", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;performPrefixedCommand(Lnet/minecraft/commands/CommandSourceStack;Ljava/lang/String;)I"))
private int arclight$serverCommandEvent(Commands commands, CommandSourceStack source, String command) {
if (command.isEmpty()) {
return 0;

View File

@ -1,23 +1,40 @@
package io.izzel.arclight.common.mixin.core.server.level;
import com.mojang.datafixers.DataFixer;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.bridge.core.world.server.ChunkMapBridge;
import io.izzel.arclight.common.mod.util.ArclightCallbackExecutor;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LightChunkGetter;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.entity.ChunkStatusUpdateListener;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import java.util.concurrent.Executor;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
@Mixin(ChunkMap.class)
public abstract class ChunkMapMixin implements ChunkMapBridge {
@ -27,11 +44,18 @@ public abstract class ChunkMapMixin implements ChunkMapBridge {
@Shadow protected abstract Iterable<ChunkHolder> getChunks();
@Shadow protected abstract void tick();
@Shadow @Mutable public ChunkGenerator generator;
@Shadow @Final public ServerLevel level;
@Shadow private RandomState randomState;
@Invoker("tick") public abstract void bridge$tick(BooleanSupplier hasMoreTime);
@Invoker("setViewDistance") public abstract void bridge$setViewDistance(int i);
// @formatter:on
@Redirect(method = "readChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;dimension()Lnet/minecraft/resources/ResourceKey;"))
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$updateRandom(ServerLevel p_214836_, LevelStorageSource.LevelStorageAccess p_214837_, DataFixer p_214838_, StructureTemplateManager p_214839_, Executor p_214840_, BlockableEventLoop p_214841_, LightChunkGetter p_214842_, ChunkGenerator p_214843_, ChunkProgressListener p_214844_, ChunkStatusUpdateListener p_214845_, Supplier p_214846_, int p_214847_, boolean p_214848_, CallbackInfo ci) {
this.bridge$setChunkGenerator(this.generator);
}
@Redirect(method = "upgradeChunkTag", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;dimension()Lnet/minecraft/resources/ResourceKey;"))
private ResourceKey<LevelStem> arclight$useTypeKey(ServerLevel serverWorld) {
return ((WorldBridge) serverWorld).bridge$getTypeKey();
}
@ -61,5 +85,13 @@ public abstract class ChunkMapMixin implements ChunkMapBridge {
@Override
public void bridge$setChunkGenerator(ChunkGenerator generator) {
this.generator = generator;
if (generator instanceof CustomChunkGenerator custom) {
generator = custom.getDelegate();
}
if (generator instanceof NoiseBasedChunkGenerator noisebasedchunkgenerator) {
this.randomState = RandomState.create(noisebasedchunkgenerator.generatorSettings().value(), this.level.registryAccess().registryOrThrow(Registry.NOISE_REGISTRY), this.level.getSeed());
} else {
this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), this.level.registryAccess().registryOrThrow(Registry.NOISE_REGISTRY), this.level.getSeed());
}
}
}

View File

@ -33,7 +33,8 @@ public abstract class DistanceManagerMixin implements TicketManagerBridge {
@Shadow private static int getTicketLevelAt(SortedArraySet<Ticket<?>> p_229844_0_) { return 0; }
@Shadow @Final public Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets;
@Shadow abstract TickingTracker tickingTracker();
@Shadow@Final private Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets;@Invoker("purgeStaleTickets") public abstract void bridge$tick();
@Shadow @Final private Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets;
@Invoker("purgeStaleTickets") public abstract void bridge$tick();
// @formatter:on
@Inject(method = "removePlayer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", remap = false, target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;remove(Ljava/lang/Object;)Z"))

View File

@ -6,7 +6,6 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBrid
import io.izzel.arclight.common.bridge.core.world.ServerEntityBridge;
import io.izzel.arclight.common.mod.ArclightConstants;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundAddMobPacket;
import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
@ -17,6 +16,7 @@ import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.network.protocol.game.VecDeltaCodec;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
@ -69,12 +69,9 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
@Shadow @Final private int updateInterval;
@Shadow private int yRotp;
@Shadow private int xRotp;
@Shadow protected abstract void updateSentPos();
@Shadow @Final private VecDeltaCodec positionCodec;
@Shadow private boolean wasRiding;
@Shadow private int teleportDelay;
@Shadow private long xp;
@Shadow private long yp;
@Shadow private long zp;
@Shadow private boolean wasOnGround;
@Shadow @Final private boolean trackDelta;
@Shadow private Vec3 ap;
@ -150,29 +147,22 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
this.yRotp = i1;
this.xRotp = l1;
}
this.updateSentPos();
this.positionCodec.setBase(this.entity.trackingPosition());
this.sendDirtyEntityData();
this.wasRiding = true;
} else {
this.teleportDelay += elapsedTicks;
int l = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F);
int k1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F);
Vec3 vector3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp));
boolean flag3 = vector3d.lengthSqr() >= (double) 7.6293945E-6F;
Vec3 vector3d = this.entity.trackingPosition();
boolean flag3 = this.positionCodec.delta(vector3d).lengthSqr() >= 7.62939453125E-6D;
Packet<?> ipacket1 = null;
boolean flag4 = flag3 || this.tickCount / 60 != this.lastPosUpdate;
boolean flag = Math.abs(l - this.yRotp) >= 1 || Math.abs(k1 - this.xRotp) >= 1;
if (flag4) {
this.updateSentPos();
}
if (flag) {
this.yRotp = l;
this.xRotp = k1;
}
if (this.tickCount > 0 || this.entity instanceof AbstractArrow) {
long i = ClientboundMoveEntityPacket.entityToPacket(vector3d.x);
long j = ClientboundMoveEntityPacket.entityToPacket(vector3d.y);
long k = ClientboundMoveEntityPacket.entityToPacket(vector3d.z);
long i = this.positionCodec.encodeX(vector3d);
long j = this.positionCodec.encodeY(vector3d);
long k = this.positionCodec.encodeZ(vector3d);
boolean flag1 = i < -32768L || i > 32767L || j < -32768L || j > 32767L || k < -32768L || k > 32767L;
if (!flag1 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround()) {
if ((!flag4 || !flag) && !(this.entity instanceof AbstractArrow)) {
@ -202,6 +192,13 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
this.broadcast.accept(ipacket1);
}
this.sendDirtyEntityData();
if (flag4) {
this.positionCodec.setBase(vector3d);
}
if (flag) {
this.yRotp = l;
this.xRotp = k1;
}
this.wasRiding = false;
}
int j1 = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F);
@ -279,7 +276,7 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
}
}
this.ap = this.entity.getDeltaMovement();
if (flag && !(packet instanceof ClientboundAddMobPacket)) {
if (flag && !(this.entity instanceof LivingEntity)) {
consumer.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.ap));
}
if (this.entity instanceof LivingEntity) {

View File

@ -20,7 +20,6 @@ import io.izzel.arclight.common.mod.util.DelegateWorldInfo;
import io.izzel.arclight.common.mod.util.DistValidate;
import io.izzel.arclight.i18n.ArclightConfig;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.network.protocol.Packet;
@ -39,34 +38,38 @@ import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.level.CustomSpawner;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.storage.DerivedLevelData;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.v.util.WorldUUID;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.LightningStrike;
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.PortalCreateEvent;
import org.bukkit.event.world.TimeSkipEvent;
import org.bukkit.event.world.WorldSaveEvent;
@ -109,8 +112,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
// @formatter:on
@SuppressWarnings({"FieldCanBeLocal", "unused"})
public PrimaryLevelData M; // TODO f_8549_ check on update
private int tickPosition;
public PrimaryLevelData N; // TODO f_8549_ check on update
public LevelStorageSource.LevelStorageAccess convertable;
public UUID uuid;
public ResourceKey<LevelStem> typeKey;
@ -120,12 +122,12 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
return this.typeKey;
}
public void arclight$constructor(MinecraftServer server, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData serverWorldInfo, ResourceKey<net.minecraft.world.level.Level> dimension, Holder<DimensionType> dimensionType, ChunkProgressListener statusListener, ChunkGenerator chunkGenerator, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking) {
public void arclight$constructor(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData worldInfo, ResourceKey<Level> dimension, LevelStem levelStem, ChunkProgressListener statusListener, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking) {
throw new RuntimeException();
}
public void arclight$constructor(MinecraftServer server, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData serverWorldInfo, ResourceKey<net.minecraft.world.level.Level> dimension, Holder<DimensionType> dimensionType, ChunkProgressListener statusListener, ChunkGenerator chunkGenerator, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
arclight$constructor(server, backgroundExecutor, levelSave, serverWorldInfo, dimension, dimensionType, statusListener, chunkGenerator, isDebug, seed, specialSpawners, shouldBeTicking);
public void arclight$constructor(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, PrimaryLevelData worldInfo, ResourceKey<Level> dimension, LevelStem levelStem, ChunkProgressListener statusListener, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
arclight$constructor(minecraftServer, backgroundExecutor, levelSave, worldInfo, dimension, levelStem, statusListener, isDebug, seed, specialSpawners, shouldBeTicking);
this.generator = gen;
this.environment = env;
this.biomeProvider = biomeProvider;
@ -136,8 +138,8 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
bridge$getWorld();
}
@Inject(method = "<init>(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/world/level/storage/ServerLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/Holder;Lnet/minecraft/server/level/progress/ChunkProgressListener;Lnet/minecraft/world/level/chunk/ChunkGenerator;ZJLjava/util/List;Z)V", at = @At("RETURN"))
private void arclight$init(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData worldInfo, ResourceKey<net.minecraft.world.level.Level> dimension, Holder<DimensionType> dimensionType, ChunkProgressListener statusListener, ChunkGenerator chunkGenerator, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking, CallbackInfo ci) {
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData worldInfo, ResourceKey<Level> dimension, LevelStem levelStem, ChunkProgressListener statusListener, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking, CallbackInfo ci) {
this.pvpMode = minecraftServer.isPvpAllowed();
this.convertable = levelSave;
var typeKey = ((LevelStorageSourceBridge.LevelStorageAccessBridge) levelSave).bridge$getTypeKey();
@ -145,18 +147,18 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
this.typeKey = typeKey;
} else {
var dimensions = shadow$getServer().getWorldData().worldGenSettings().dimensions();
var levelStem = dimensions.get(dimension.location());
if (levelStem != null) {
this.typeKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, dimension.location());
var key = dimensions.getKey(levelStem);
if (key != null) {
this.typeKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, key);
} else {
throw new IllegalStateException("No level stem for dimension " + dimension.location());
}
}
if (worldInfo instanceof PrimaryLevelData) {
this.M = (PrimaryLevelData) worldInfo;
this.N = (PrimaryLevelData) worldInfo;
} else if (worldInfo instanceof DerivedLevelData) {
// damn spigot again
this.M = DelegateWorldInfo.wrap(((DerivedLevelData) worldInfo));
this.N = DelegateWorldInfo.wrap(((DerivedLevelData) worldInfo));
((DerivedWorldInfoBridge) worldInfo).bridge$setDimType(this.getTypeKey());
if (ArclightConfig.spec().getCompat().isSymlinkWorld()) {
WorldSymlink.create((DerivedLevelData) worldInfo, levelSave.getDimensionPath(this.dimension()).toFile());
@ -165,7 +167,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
this.spigotConfig = new SpigotWorldConfig(worldInfo.getLevelName());
this.uuid = WorldUUID.getUUID(levelSave.getDimensionPath(this.dimension()).toFile());
((ServerChunkProviderBridge) this.chunkSource).bridge$setViewDistance(spigotConfig.viewDistance);
((WorldInfoBridge) this.M).bridge$setWorld((ServerLevel) (Object) this);
((WorldInfoBridge) this.N).bridge$setWorld((ServerLevel) (Object) this);
var data = this.getDataStorage().computeIfAbsent(LevelPersistentData::new, () -> new LevelPersistentData(null), "bukkit_pdc");
this.bridge$getWorld().readBukkitValues(data.getTag());
}
@ -176,6 +178,17 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
data.save(this.world);
}
@Inject(method = "gameEvent", cancellable = true, at = @At("HEAD"))
private void arclight$gameEventEvent(GameEvent gameEvent, Vec3 pos, GameEvent.Context context, CallbackInfo ci) {
var entity = context.sourceEntity();
var i = gameEvent.getNotificationRadius();
GenericGameEvent event = new GenericGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(gameEvent))), new Location(this.getWorld(), pos.x(), pos.y(), pos.z()), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), i, !Bukkit.isPrimaryThread());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
ci.cancel();
}
}
public LevelChunk getChunkIfLoaded(int x, int z) {
return this.chunkSource.getChunk(x, z, false);
}

View File

@ -14,16 +14,13 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.mod.server.ArclightServer;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.UUIDUtil;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket;
import net.minecraft.network.protocol.game.ClientboundChatPacket;
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
@ -52,6 +49,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.ProfilePublicKey;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.BiomeManager;
@ -116,14 +114,12 @@ public abstract class PlayerListMixin implements PlayerListBridge {
@Shadow @Final private MinecraftServer server;
@Shadow public abstract UserBanList getBans();
@Shadow public abstract IpBanList getIpBans();
@Shadow(remap = false) public abstract boolean removePlayer(ServerPlayer player);
@Shadow public abstract void sendLevelInfo(ServerPlayer playerIn, ServerLevel worldIn);
@Shadow public abstract void sendPlayerPermissionLevel(ServerPlayer player);
@Shadow(remap = false) public abstract boolean addPlayer(ServerPlayer player);
@Shadow @Final private Map<UUID, ServerPlayer> playersByUUID;
@Shadow public abstract void sendAllPlayerInfo(ServerPlayer playerIn);
@Shadow public abstract void broadcastMessage(Component p_232641_1_, ChatType p_232641_2_, UUID p_232641_3_);
@Shadow @Nullable public abstract ServerPlayer getPlayer(UUID playerUUID);
@Shadow public abstract void broadcastSystemMessage(Component p_240618_, boolean p_240644_);
// @formatter:on
private CraftServer cserver;
@ -160,8 +156,8 @@ public abstract class PlayerListMixin implements PlayerListBridge {
return ((WorldBridge) playerIn.getLevel()).bridge$spigotConfig().simulationDistance;
}
@Eject(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/ChatType;Ljava/util/UUID;)V"))
private void arclight$playerJoin(PlayerList playerList, Component component, ChatType chatType, UUID uuid, CallbackInfo ci, Connection netManager, ServerPlayer playerIn) {
@Eject(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Z)V"))
private void arclight$playerJoin(PlayerList playerList, Component component, boolean flag, CallbackInfo ci, Connection netManager, ServerPlayer playerIn) {
PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity(), CraftChatMessage.fromComponent(component));
this.players.add(playerIn);
this.playersByUUID.put(playerIn.getUUID(), playerIn);
@ -174,7 +170,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
String joinMessage = playerJoinEvent.getJoinMessage();
if (joinMessage != null && joinMessage.length() > 0) {
for (Component line : CraftChatMessage.fromString(joinMessage)) {
this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID));
this.server.getPlayerList().broadcastSystemMessage(line, flag);
}
}
}
@ -201,8 +197,8 @@ public abstract class PlayerListMixin implements PlayerListBridge {
}
@Override
public ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler) {
UUID uuid = net.minecraft.world.entity.player.Player.createPlayerUUID(gameProfile);
public ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler, ProfilePublicKey profilePublicKey) {
UUID uuid = UUIDUtil.getOrCreatePlayerUUID(gameProfile);
List<ServerPlayer> list = Lists.newArrayList();
for (ServerPlayer entityplayer : this.players) {
if (entityplayer.getUUID().equals(uuid)) {
@ -211,9 +207,9 @@ public abstract class PlayerListMixin implements PlayerListBridge {
}
for (ServerPlayer entityplayer : list) {
this.save(entityplayer);
entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login"));
entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login"));
}
ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile);
ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, profilePublicKey);
Player player = ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity();
String hostname = handler == null ? "" : ((ServerLoginNetHandlerBridge) handler).bridge$getHostname();
@ -222,18 +218,18 @@ public abstract class PlayerListMixin implements PlayerListBridge {
PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((InetSocketAddress) socketAddress).getAddress(), realAddress);
if (this.getBans().isBanned(gameProfile) && !this.getBans().get(gameProfile).hasExpired()) {
UserBanListEntry gameprofilebanentry = this.bans.get(gameProfile);
TranslatableComponent chatmessage = new TranslatableComponent("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason());
var chatmessage = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason());
if (gameprofilebanentry.getExpires() != null) {
chatmessage.append(new TranslatableComponent("multiplayer.disconnect.banned.expiration", BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires())));
chatmessage.append(Component.translatable("multiplayer.disconnect.banned.expiration", BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires())));
}
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage));
} else if (!this.isWhiteListed(gameProfile)) {
event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, SpigotConfig.whitelistMessage);
} else if (this.getIpBans().isBanned(socketAddress) && !this.getIpBans().get(socketAddress).hasExpired()) {
IpBanListEntry ipbanentry = this.ipBans.get(socketAddress);
TranslatableComponent chatmessage = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason());
var chatmessage = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason());
if (ipbanentry.getExpires() != null) {
chatmessage.append(new TranslatableComponent("multiplayer.disconnect.banned_ip.expiration", BAN_DATE_FORMAT.format(ipbanentry.getExpires())));
chatmessage.append(Component.translatable("multiplayer.disconnect.banned_ip.expiration", BAN_DATE_FORMAT.format(ipbanentry.getExpires())));
}
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage));
} else if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)) {
@ -249,10 +245,9 @@ public abstract class PlayerListMixin implements PlayerListBridge {
return entity;
}
// todo check these two
public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean flag, Location location, boolean avoidSuffocation) {
playerIn.stopRiding();
this.removePlayer(playerIn);
this.players.remove(playerIn);
playerIn.getLevel().removePlayerImmediately(playerIn, Entity.RemovalReason.DISCARDED);
playerIn.revive();
BlockPos pos = playerIn.getRespawnPosition();
@ -325,7 +320,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
playerIn.setPos(playerIn.getX(), playerIn.getY() + 1.0, playerIn.getZ());
}
LevelData worlddata = serverWorld.getLevelData();
playerIn.connection.send(new ClientboundRespawnPacket(serverWorld.dimensionTypeRegistration(), serverWorld.dimension(), BiomeManager.obfuscateSeed(serverWorld.getSeed()), playerIn.gameMode.getGameModeForPlayer(), playerIn.gameMode.getPreviousGameModeForPlayer(), serverWorld.isDebug(), serverWorld.isFlat(), flag));
playerIn.connection.send(new ClientboundRespawnPacket(serverWorld.dimensionTypeId(), serverWorld.dimension(), BiomeManager.obfuscateSeed(serverWorld.getSeed()), playerIn.gameMode.getGameModeForPlayer(), playerIn.gameMode.getPreviousGameModeForPlayer(), serverWorld.isDebug(), serverWorld.isFlat(), flag, playerIn.getLastDeathLocation()));
playerIn.connection.send(new ClientboundSetChunkCacheRadiusPacket(((WorldBridge) serverWorld).bridge$spigotConfig().viewDistance));
playerIn.connection.send(new ClientboundSetSimulationDistancePacket(((WorldBridge) serverWorld).bridge$spigotConfig().simulationDistance));
playerIn.setLevel(serverWorld);
@ -338,13 +333,13 @@ public abstract class PlayerListMixin implements PlayerListBridge {
this.sendPlayerPermissionLevel(playerIn);
if (!((ServerPlayNetHandlerBridge) playerIn.connection).bridge$isDisconnected()) {
serverWorld.addDuringCommandTeleport(playerIn);
this.addPlayer(playerIn);
this.players.add(playerIn);
this.playersByUUID.put(playerIn.getUUID(), playerIn);
}
playerIn.setHealth(playerIn.getHealth());
ForgeEventFactory.firePlayerChangedDimensionEvent(playerIn, ((CraftWorld) fromWorld).getHandle().dimension, serverWorld.dimension);
if (flag3) {
playerIn.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), 1.0f, 1.0f));
playerIn.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), 1.0f, 1.0f, serverWorld.random.nextLong()));
}
this.sendAllPlayerInfo(playerIn);
playerIn.onUpdateAbilities();
@ -377,7 +372,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
boolean avoidSuffocation = arclight$suffo == null || arclight$suffo;
arclight$suffo = null;
playerIn.stopRiding();
this.removePlayer(playerIn);
this.players.remove(playerIn);
playerIn.getLevel().removePlayerImmediately(playerIn, Entity.RemovalReason.DISCARDED);
BlockPos pos = playerIn.getRespawnPosition();
float f = playerIn.getRespawnAngle();
@ -439,7 +434,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
ServerLevel serverWorld = ((CraftWorld) location.getWorld()).getHandle();
ServerPlayer serverplayerentity = new ServerPlayer(this.server, serverWorld, playerIn.getGameProfile());
ServerPlayer serverplayerentity = new ServerPlayer(this.server, serverWorld, playerIn.getGameProfile(), playerIn.getProfilePublicKey());
// Forward to new player instance
((InternalEntityBridge) playerIn).internal$getBukkitEntity().setHandle(serverplayerentity);
@ -471,7 +466,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
}
LevelData iworldinfo = serverplayerentity.level.getLevelData();
serverplayerentity.connection.send(new ClientboundRespawnPacket(serverplayerentity.level.dimensionTypeRegistration(), serverplayerentity.level.dimension(), BiomeManager.obfuscateSeed(serverplayerentity.getLevel().getSeed()), serverplayerentity.gameMode.getGameModeForPlayer(), serverplayerentity.gameMode.getPreviousGameModeForPlayer(), serverplayerentity.getLevel().isDebug(), serverplayerentity.getLevel().isFlat(), conqueredEnd));
serverplayerentity.connection.send(new ClientboundRespawnPacket(serverplayerentity.level.dimensionTypeId(), serverplayerentity.level.dimension(), BiomeManager.obfuscateSeed(serverplayerentity.getLevel().getSeed()), serverplayerentity.gameMode.getGameModeForPlayer(), serverplayerentity.gameMode.getPreviousGameModeForPlayer(), serverplayerentity.getLevel().isDebug(), serverplayerentity.getLevel().isFlat(), conqueredEnd, serverplayerentity.getLastDeathLocation()));
serverplayerentity.connection.send(new ClientboundSetChunkCacheRadiusPacket(((WorldBridge) serverWorld).bridge$spigotConfig().viewDistance));
serverplayerentity.connection.send(new ClientboundSetSimulationDistancePacket(((WorldBridge) serverWorld).bridge$spigotConfig().simulationDistance));
serverplayerentity.setLevel(serverWorld);
@ -484,14 +479,14 @@ public abstract class PlayerListMixin implements PlayerListBridge {
this.sendPlayerPermissionLevel(serverplayerentity);
if (!((ServerPlayNetHandlerBridge) serverplayerentity.connection).bridge$isDisconnected()) {
serverWorld.addRespawnedPlayer(serverplayerentity);
this.addPlayer(serverplayerentity);
this.players.add(serverplayerentity);
this.playersByUUID.put(serverplayerentity.getUUID(), serverplayerentity);
}
serverplayerentity.initInventoryMenu();
serverplayerentity.setHealth(serverplayerentity.getHealth());
ForgeEventFactory.firePlayerRespawnEvent(serverplayerentity, conqueredEnd);
if (flag2) {
serverplayerentity.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 1.0F, 1.0F));
serverplayerentity.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 1.0F, 1.0F, serverWorld.random.nextLong()));
}
this.sendAllPlayerInfo(serverplayerentity);
serverplayerentity.onUpdateAbilities();
@ -542,7 +537,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
public void broadcastMessage(Component[] components) {
for (Component component : components) {
this.broadcastMessage(component, ChatType.SYSTEM, Util.NIL_UUID);
broadcastSystemMessage(component, false);
}
}

View File

@ -7,7 +7,6 @@ import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.protocol.game.ClientboundBlockBreakAckPacket;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.server.level.ServerLevel;
@ -20,10 +19,8 @@ import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.DoubleHighBlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
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.TrapDoorBlock;
@ -69,7 +66,8 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
@Shadow private boolean hasDelayedDestroy;
@Shadow private BlockPos delayedDestroyPos;
@Shadow private int delayedTickStart;
@Shadow public abstract void destroyAndAck(BlockPos p_229860_1_, ServerboundPlayerActionPacket.Action p_229860_2_, String p_229860_3_);
@Shadow public abstract void destroyAndAck(BlockPos p_215117_, int p_215118_, String p_215119_);
@Shadow protected abstract void debugLogging(BlockPos p_215126_, boolean p_215127_, int p_215128_, String p_215129_);
// @formatter:on
public boolean interactResult = false;
@ -89,34 +87,25 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
* @reason
*/
@Overwrite
public void handleBlockBreakAction(BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, int i) {
public void handleBlockBreakAction(BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, int i, int j) {
if (!this.level.hasChunkAt(blockPos)) {
return;
}
double d0 = this.player.getX() - (blockPos.getX() + 0.5);
double d2 = this.player.getY() - (blockPos.getY() + 0.5) + 1.5;
double d3 = this.player.getZ() - (blockPos.getZ() + 0.5);
double d4 = d0 * d0 + d2 * d2 + d3 * d3;
net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock forgeEvent = net.minecraftforge.common.ForgeHooks.onLeftClickBlock(player, blockPos, direction);
if (forgeEvent.isCanceled() || (!this.isCreative() && forgeEvent.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY)) { // Restore block and te data
player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, level.getBlockState(blockPos), action, false, "mod canceled"));
level.sendBlockUpdated(blockPos, level.getBlockState(blockPos), level.getBlockState(blockPos), 3);
return;
}
if (!this.player.canInteractWith(blockPos, 1)) {
BlockState state;
if (this.player.level.getServer() != null && this.player.chunkPosition().getChessboardDistance(new ChunkPos(blockPos)) < this.player.level.getServer().getPlayerList().getViewDistance()) {
state = this.level.getBlockState(blockPos);
} else {
state = Blocks.AIR.defaultBlockState();
}
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, state, action, false, "too far"));
this.debugLogging(blockPos, false, j, "too far");
} else if (blockPos.getY() >= i) {
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, this.level.getBlockState(blockPos), action, false, "too high"));
this.player.connection.send(new ClientboundBlockUpdatePacket(blockPos, this.level.getBlockState(blockPos)));
this.debugLogging(blockPos, false, j, "too high");
} else if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) {
if (!this.level.mayInteract(this.player, blockPos)) {
CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockPos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND);
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, this.level.getBlockState(blockPos), action, false, "may not interact"));
this.player.connection.send(new ClientboundBlockUpdatePacket(blockPos, this.level.getBlockState(blockPos)));
this.debugLogging(blockPos, false, j, "may not interact");
BlockEntity tileentity = this.level.getBlockEntity(blockPos);
if (tileentity != null) {
this.player.connection.send(tileentity.getUpdatePacket());
@ -133,11 +122,12 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
return;
}
if (this.isCreative()) {
this.destroyAndAck(blockPos, action, "creative destroy");
this.destroyAndAck(blockPos, j, "creative destroy");
return;
}
if (this.player.blockActionRestricted(this.level, blockPos, this.gameModeForPlayer)) {
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, this.level.getBlockState(blockPos), action, false, "block action restricted"));
this.player.connection.send(new ClientboundBlockUpdatePacket(blockPos, this.level.getBlockState(blockPos)));
this.debugLogging(blockPos, false, j, "block action restricted");
return;
}
this.destroyProgressStart = this.gameTicks;
@ -173,18 +163,19 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
f = 2.0f;
}
if (!iblockdata.isAir() && f >= 1.0f) {
this.destroyAndAck(blockPos, action, "insta mine");
this.destroyAndAck(blockPos, j, "insta mine");
} else {
if (this.isDestroyingBlock) {
this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, false, "abort destroying since another started (client insta mine, server disagreed)"));
this.player.connection.send(new ClientboundBlockUpdatePacket(this.destroyPos, this.level.getBlockState(this.destroyPos)));
this.debugLogging(blockPos, false, j, "abort destroying since another started (client insta mine, server disagreed)");
}
this.isDestroyingBlock = true;
this.destroyPos = blockPos;
int j = (int) (f * 10.0f);
this.level.destroyBlockProgress(this.player.getId(), blockPos, j);
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, this.level.getBlockState(blockPos), action, true, "actual start of destroying"));
int state = (int) (f * 10.0f);
this.level.destroyBlockProgress(this.player.getId(), blockPos, state);
this.debugLogging(blockPos, true, j, "actual start of destroying");
CraftEventFactory.callBlockDamageAbortEvent(this.player, blockPos, this.player.getInventory().getSelected());
this.lastSentState = j;
this.lastSentState = state;
}
} else if (action == ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK) {
if (blockPos.equals(this.destroyPos)) {
@ -195,7 +186,7 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
if (f2 >= 0.7f) {
this.isDestroyingBlock = false;
this.level.destroyBlockProgress(this.player.getId(), blockPos, -1);
this.destroyAndAck(blockPos, action, "destroyed");
this.destroyAndAck(blockPos, j, "destroyed");
return;
}
if (!this.hasDelayedDestroy) {
@ -206,16 +197,16 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
}
}
}
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, this.level.getBlockState(blockPos), action, true, "stopped destroying"));
this.debugLogging(blockPos, true, j, "stopped destroying");
} else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
this.isDestroyingBlock = false;
if (!Objects.equals(this.destroyPos, blockPos)) {
ArclightMod.LOGGER.debug("Mismatch in destroy block pos: " + this.destroyPos + " " + blockPos);
this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1);
this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying"));
this.debugLogging(blockPos, true, j, "aborted mismatched destroying");
}
this.level.destroyBlockProgress(this.player.getId(), blockPos, -1);
this.player.connection.send(new ClientboundBlockBreakAckPacket(blockPos, this.level.getBlockState(blockPos), action, true, "aborted destroying"));
this.debugLogging(blockPos, true, j, "aborted destroying");
}
}

View File

@ -7,12 +7,14 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.world.ExplosionBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
@ -49,11 +51,10 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
@Mixin(Explosion.class)
@ -63,7 +64,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@Shadow @Final private Level level;
@Shadow @Final private Explosion.BlockInteraction blockInteraction;
@Shadow @Mutable @Final private float radius;
@Shadow @Final private List<BlockPos> toBlow;
@Shadow @Final private ObjectArrayList<BlockPos> toBlow;
@Shadow @Final private double x;
@Shadow @Final private double y;
@Shadow @Final private double z;
@ -75,9 +76,10 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@Accessor("radius") public abstract void bridge$setSize(float size);
@Accessor("blockInteraction") public abstract Explosion.BlockInteraction bridge$getMode();
@Shadow @Final private boolean fire;
@Shadow @Final private Random random;
@Shadow @Final private RandomSource random;
@Shadow private static void addBlockDrops(ObjectArrayList<Pair<ItemStack, BlockPos>> dropPositionArray, ItemStack stack, BlockPos pos) { }
@Shadow @Final private ExplosionDamageCalculator damageCalculator;
@Shadow @Nullable public abstract LivingEntity getSourceMob();
// @formatter:on
@ -245,7 +247,8 @@ public abstract class ExplosionMixin implements ExplosionBridge {
if (flag) {
ObjectArrayList<Pair<ItemStack, BlockPos>> objectarraylist = new ObjectArrayList<>();
Collections.shuffle(this.toBlow, this.level.random);
boolean flag2 = this.getSourceMob() instanceof Player;
Util.shuffle(this.toBlow, this.level.random);
float yield = this.callBlockExplodeEvent();
@ -260,20 +263,20 @@ public abstract class ExplosionMixin implements ExplosionBridge {
if (!blockstate.isAir()) {
BlockPos blockpos1 = blockpos.immutable();
this.level.getProfiler().push("explosion_blocks");
if (blockstate.canDropFromExplosion(this.level, blockpos, (Explosion) (Object) this) && this.level instanceof ServerLevel) {
if (blockstate.canDropFromExplosion(this.level, blockpos, (Explosion) (Object) this) && this.level instanceof ServerLevel serverLevel) {
BlockEntity tileentity = blockstate.hasBlockEntity() ? this.level.getBlockEntity(blockpos) : null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerLevel) this.level)).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, this.source);
LootContext.Builder lootcontext$builder = new LootContext.Builder(serverLevel).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, this.source);
if (this.blockInteraction == Explosion.BlockInteraction.DESTROY || yield < 1.0F) {
lootcontext$builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / yield);
}
blockstate.spawnAfterBreak(serverLevel, blockpos, ItemStack.EMPTY, flag2);
blockstate.getDrops(lootcontext$builder).forEach((stack) -> {
addBlockDrops(objectarraylist, stack, blockpos1);
});
}
blockstate.onBlockExploded(this.level, blockpos, (Explosion) (Object) this);
block.wasExploded(this.level, blockpos, (Explosion) (Object) this);
this.level.getProfiler().pop();
}
}

View File

@ -0,0 +1,33 @@
package io.izzel.arclight.common.mixin.core.world.effect;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffectUtil;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
@Mixin(MobEffectUtil.class)
public class MobEffectUtilMixin {
@Inject(method = "addEffectToPlayersAround", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V"))
private static void arclight$pushCause(ServerLevel p_216947_, Entity p_216948_, Vec3 p_216949_, double p_216950_, MobEffectInstance p_216951_, int p_216952_, CallbackInfoReturnable<List<ServerPlayer>> cir,
MobEffect effect, List<ServerPlayer> players) {
var cause = ArclightCaptures.getEffectCause();
if (cause != null) {
for (ServerPlayer player : players) {
((ServerPlayerEntityBridge) player).bridge$pushEffectCause(cause);
}
}
}
}

View File

@ -16,6 +16,7 @@ import net.minecraft.BlockUtil;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.PositionImpl;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor;
@ -25,8 +26,8 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
@ -47,7 +48,6 @@ import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.portal.PortalInfo;
import net.minecraft.world.level.portal.PortalShape;
@ -99,7 +99,6 @@ import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
@SuppressWarnings("ConstantConditions")
@ -135,7 +134,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Shadow @Nullable public abstract MinecraftServer getServer();
@Shadow public abstract Vec3 getDeltaMovement();
@Shadow public abstract EntityType<?> getType();
@Shadow @Final protected Random random;
@Shadow @Final protected RandomSource random;
@Shadow public abstract float getBbWidth();
@Shadow public abstract float getBbHeight();
@Shadow public abstract boolean isInvisible();
@ -216,6 +215,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Shadow public abstract void setSharedFlagOnFire(boolean p_146869_);
@Shadow public abstract int getMaxAirSupply();
@Shadow public abstract int getAirSupply();
@Shadow public abstract void gameEvent(GameEvent p_146851_);
// @formatter:on
private static final int CURRENT_LEVEL = 2;
@ -389,9 +389,9 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
if ((Object) this instanceof ServerPlayer) this.handleNetherPortal();// CraftBukkit - // Moved up to postTick
}
@Redirect(method = "updateFluidHeightAndDoFluidPushing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/material/FluidState;getFlow(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/phys/Vec3;"))
private Vec3 arclight$setLava(FluidState instance, BlockGetter level, BlockPos pos, TagKey<Fluid> tag) {
if (tag == FluidTags.LAVA) {
@Redirect(method = "updateFluidHeightAndDoFluidPushing()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/material/FluidState;getFlow(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/phys/Vec3;"))
private Vec3 arclight$setLava(FluidState instance, BlockGetter level, BlockPos pos) {
if (instance.getType().is(FluidTags.LAVA)) {
lastLavaContact = pos.immutable();
}
return instance.getFlow(level, pos);
@ -830,24 +830,15 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
return this.boardingCooldown;
}
private transient BlockPos arclight$tpPos;
private transient PositionImpl arclight$tpPos;
@Override
public BlockPos internal$capturedPos() {
try {
return arclight$tpPos;
} finally {
arclight$tpPos = null;
}
}
public Entity teleportTo(ServerLevel world, BlockPos blockPos) {
public Entity teleportTo(ServerLevel world, PositionImpl blockPos) {
arclight$tpPos = blockPos;
return changeDimension(world);
}
@Override
public Entity bridge$teleportTo(ServerLevel world, BlockPos blockPos) {
public Entity bridge$teleportTo(ServerLevel world, PositionImpl blockPos) {
return teleportTo(world, blockPos);
}
@ -866,7 +857,10 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
return null;
}
this.level.getProfiler().push("reposition");
PortalInfo portalinfo = teleporter.getPortalInfo((Entity) (Object) this, server, this::findDimensionEntryPoint);
var bukkitPos = arclight$tpPos;
arclight$tpPos = null;
PortalInfo portalinfo = bukkitPos == null ? teleporter.getPortalInfo((Entity) (Object) this, server, this::findDimensionEntryPoint)
: new PortalInfo(new Vec3(bukkitPos.x(), bukkitPos.y(), bukkitPos.z()), Vec3.ZERO, this.yRot, this.xRot);
if (portalinfo == null) {
return null;
} else {
@ -935,7 +929,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
double d0 = DimensionType.getTeleportationScale(this.level.dimensionType(), world.dimensionType());
BlockPos blockpos1 = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0);
CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, blockpos1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16);
CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, new PositionImpl(blockpos1.getX(), blockpos1.getY(), blockpos1.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16);
if (event == null) {
return null;
}
@ -969,23 +963,22 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
blockpos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, world.getSharedSpawnPos());
}
CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, blockpos, PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0);
CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, new PositionImpl(blockpos.getX() + 0.5D, blockpos.getY(), blockpos.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0);
if (event == null) {
return null;
}
blockpos = new BlockPos(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
PortalInfo portalInfo = new PortalInfo(new Vec3((double) blockpos.getX() + 0.5D, blockpos.getY(), (double) blockpos.getZ() + 0.5D), this.getDeltaMovement(), this.getYRot(), this.getXRot());
PortalInfo portalInfo = new PortalInfo(new Vec3(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot());
((PortalInfoBridge) portalInfo).bridge$setWorld(((CraftWorld) event.getTo().getWorld()).getHandle());
((PortalInfoBridge) portalInfo).bridge$setPortalEventInfo(event);
return portalInfo;
}
}
protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, BlockPos exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) {
protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, PositionImpl exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) {
CraftEntity bukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity();
Location enter = bukkitEntity.getLocation();
Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ());
Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.x(), exitPosition.y(), exitPosition.z());
EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) {

View File

@ -23,6 +23,7 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.stats.Stats;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.damagesource.CombatTracker;
import net.minecraft.world.damagesource.DamageSource;
@ -41,6 +42,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeMap;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
@ -51,7 +53,7 @@ import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.entity.living.PotionEvent;
import net.minecraftforge.event.entity.living.MobEffectEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.attribute.CraftAttributeMap;
@ -86,7 +88,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
@ -101,7 +102,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
@Shadow public abstract float getHealth();
@Shadow public abstract void setHealth(float health);
@Shadow public abstract float getYHeadRot();
@Shadow protected abstract int getExperienceReward(net.minecraft.world.entity.player.Player player);
@Shadow protected int lastHurtByPlayerTime;
@Shadow protected abstract boolean shouldDropExperience();
@Shadow protected abstract boolean isAlwaysExperienceDropper();
@ -157,7 +157,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
@Shadow @Nullable public LivingEntity lastHurtByMob;
@Shadow public CombatTracker combatTracker;
@Shadow public abstract ItemStack getOffhandItem();
@Shadow public abstract Random getRandom();
@Shadow public abstract RandomSource getRandom();
@Shadow public abstract Optional<BlockPos> getSleepingPos();
@Shadow @Final private static EntityDataAccessor<Integer> DATA_EFFECT_COLOR_ID;
@Shadow @Final private static EntityDataAccessor<Boolean> DATA_EFFECT_AMBIENCE_ID;
@ -176,11 +176,15 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
@Shadow protected abstract void onEffectUpdated(MobEffectInstance p_147192_, boolean p_147193_, @org.jetbrains.annotations.Nullable Entity p_147194_);
@Shadow protected abstract void onEffectAdded(MobEffectInstance p_147190_, @org.jetbrains.annotations.Nullable Entity p_147191_);
@Shadow public abstract void knockback(double p_147241_, double p_147242_, double p_147243_);
@Shadow protected abstract void equipEventAndSound(ItemStack p_147219_);
@Shadow public abstract boolean canAttack(LivingEntity p_21171_);
@Shadow public abstract boolean hasLineOfSight(Entity p_147185_);
@Shadow protected abstract void hurtHelmet(DamageSource p_147213_, float p_147214_);
@Shadow public abstract void stopUsingItem();
@Shadow protected abstract void playEquipSound(ItemStack p_217042_);
@Shadow protected abstract boolean doesEmitEquipEvent(EquipmentSlot p_217035_);
@Shadow protected abstract void verifyEquippedItem(ItemStack p_181123_);
@Shadow public abstract boolean wasExperienceConsumed();
@Shadow public abstract int getExperienceReward();
// @formatter:on
public int expToDrop;
@ -231,8 +235,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
@Overwrite
protected void dropExperience() {
// if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) {
if (true) {
int reward = ForgeEventFactory.getExperienceDrop((LivingEntity)(Object) this, this.lastHurtByPlayer, this.expToDrop);
if (!((Object) this instanceof EnderDragon)) {
int reward = ForgeEventFactory.getExperienceDrop((LivingEntity) (Object) this, this.lastHurtByPlayer, this.expToDrop);
ExperienceOrb.award((ServerLevel) this.level, this.position(), reward);
bridge$setExpToDrop(0);
}
@ -257,7 +261,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
if (!effectinstance.tick((LivingEntity) (Object) this, () -> {
onEffectUpdated(effectinstance, true, null);
})) {
if (!this.level.isClientSide && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) {
if (!this.level.isClientSide && !MinecraftForge.EVENT_BUS.post(new MobEffectEvent.Expired((LivingEntity) (Object) this, effectinstance))) {
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, EntityPotionEffectEvent.Cause.EXPIRATION);
if (event.isCancelled()) {
@ -345,7 +349,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
return false;
}
MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, entity));
MinecraftForge.EVENT_BUS.post(new MobEffectEvent.Added((LivingEntity) (Object) this, effectinstance, effectInstanceIn, entity));
if (effectinstance == null) {
this.activeEffects.put(effectInstanceIn.getEffect(), effectInstanceIn);
this.onEffectAdded(effectInstanceIn, entity);
@ -398,8 +402,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
public int getExpReward() {
if (!this.level.isClientSide && (this.lastHurtByPlayerTime > 0 || this.isAlwaysExperienceDropper()) && this.shouldDropExperience() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
int exp = this.getExperienceReward(this.lastHurtByPlayer);
if (this.level instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) {
int exp = this.getExperienceReward();
return ForgeEventFactory.getExperienceDrop((LivingEntity) (Object) this, this.lastHurtByPlayer, exp);
} else {
return 0;
@ -796,7 +800,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
if (!human) {
this.setAbsorptionAmount(this.getAbsorptionAmount() - f);
}
this.gameEvent(GameEvent.ENTITY_DAMAGED, damagesource.getEntity());
this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity());
return true;
} else {
@ -1102,14 +1106,23 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
this.setItemSlot(slotIn, stack, silent);
}
protected void equipEventAndSound(ItemStack stack, boolean silent) {
if (!silent) {
this.equipEventAndSound(stack);
protected void equipEventAndSound(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem, boolean silent) {
boolean flag = oldItem.isEmpty() && newItem.isEmpty();
if (!flag && !ItemStack.isSameIgnoreDurability(oldItem, newItem) && !this.firstTick) {
if (slot.getType() == EquipmentSlot.Type.ARMOR && !silent) {
this.playEquipSound(newItem);
}
if (this.doesEmitEquipEvent(slot)) {
this.gameEvent(GameEvent.EQUIP);
}
}
}
@Override
public void bridge$playEquipSound(ItemStack stack, boolean silent) {
this.equipEventAndSound(stack, silent);
public void bridge$playEquipSound(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem, boolean silent) {
this.equipEventAndSound(slot, oldItem, newItem, silent);
}
}

View File

@ -227,7 +227,6 @@ public abstract class MobMixin extends LivingEntityMixin implements MobEntityBri
}
this.setItemSlotAndDropWhenKilled(equipmentslottype, stack);
this.equipEventAndSound(stack);
return true;
} else {
return false;

View File

@ -1,29 +0,0 @@
package io.izzel.arclight.common.mixin.core.world.entity.ai.attributes;
import io.izzel.arclight.common.bridge.core.entity.ai.attributes.RangedAttributeBridge;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.RangedAttribute;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RangedAttribute.class)
public abstract class RangedAttributeMixin extends Attribute implements RangedAttributeBridge {
// @formatter:off
@Override @Accessor("maxValue") public abstract void bridge$setMaximumValue(double maximumValue);
// @formatter:on
protected RangedAttributeMixin(String attributeName, double defaultValue) {
super(attributeName, defaultValue);
}
@Inject(method = "sanitizeValue", cancellable = true, at = @At("HEAD"))
private void arclight$notNan(double value, CallbackInfoReturnable<Double> cir) {
if (Double.isNaN(value)) {
cir.setReturnValue(this.getDefaultValue());
}
}
}

View File

@ -36,7 +36,7 @@ public class AssignProfessionFromJobSiteMixin {
return world.getPoiManager().getType(globalpos.pos());
}).flatMap((poiType) -> {
return Registry.VILLAGER_PROFESSION.stream().filter((profession) -> {
return profession.getJobPoiType() == poiType;
return profession.heldJobSite().test(poiType);
}).findFirst();
}).ifPresent((profession) -> {
VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityIn, CraftVillager.nmsToBukkitProfession(profession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED);

View File

@ -19,7 +19,7 @@ public class StartAttackingMixin<E extends Mob> {
* @reason
*/
@Overwrite
private void setAttackTarget(E mob, LivingEntity livingEntity) {
public static <E extends Mob> void setAttackTarget(E mob, LivingEntity livingEntity) {
EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(mob, livingEntity, (livingEntity instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
if (event.isCancelled()) {
return;

View File

@ -18,14 +18,14 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(BehaviorUtils.class)
public class BrainUtilMixin {
@Inject(method = "throwItem", cancellable = true, at = @At("HEAD"))
private static void arclight$noEmptyLoot(LivingEntity entity, ItemStack stack, Vec3 offset, CallbackInfo ci) {
@Inject(method = "throwItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;F)V", cancellable = true, at = @At("HEAD"))
private static void arclight$noEmptyLoot(LivingEntity p_217134_, ItemStack stack, Vec3 p_217136_, Vec3 p_217137_, float p_217138_, CallbackInfo ci) {
if (stack.isEmpty()) ci.cancel();
}
@Inject(method = "throwItem", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
@Inject(method = "throwItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;F)V", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private static void arclight$entityDropItem(LivingEntity entity, ItemStack stack, Vec3 offset, CallbackInfo ci, double d, ItemEntity itemEntity) {
private static void arclight$entityDropItem(LivingEntity entity, ItemStack p_217135_, Vec3 p_217136_, Vec3 p_217137_, float p_217138_, CallbackInfo ci, double d0, ItemEntity itemEntity) {
EntityDropItemEvent event = new EntityDropItemEvent(((EntityBridge) entity).bridge$getBukkitEntity(), (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {

View File

@ -1,7 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.entity.animal;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.network.protocol.game.ClientboundAddMobPacket;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
@ -41,7 +41,7 @@ public interface BucketableMixin {
itemstack1 = CraftItemStack.asNMSCopy(event.getEntityBucket());
if (event.isCancelled()) {
player.containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
((ServerPlayer) player).connection.send(new ClientboundAddMobPacket(entity)); // We need to play out these packets as the client assumes the fish is gone
((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone
((ServerPlayer) player).connection.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); // Need to send data such as the display name to client
return Optional.of(InteractionResult.FAIL);
}

View File

@ -24,7 +24,7 @@ public abstract class Fox_EatBerriesGoalMixin extends MoveToBlockGoal {
super(creature, speedIn, length);
}
@Inject(method = "pickSweetBerries", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Random;nextInt(I)I"))
@Inject(method = "pickSweetBerries", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;nextInt(I)I"))
private void arclight$eatBerry(BlockState state, CallbackInfo ci) {
if (CraftEventFactory.callEntityChangeBlockEvent(outerThis, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1)).isCancelled()) {
ci.cancel();

View File

@ -0,0 +1,32 @@
package io.izzel.arclight.common.mixin.core.world.entity.animal.frog;
import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.animal.frog.Frog;
import net.minecraft.world.entity.animal.frog.Tadpole;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(Tadpole.class)
public abstract class TadpoleMixin {
// @formatter:off
@Shadow protected abstract void setAge(int p_218711_);
// @formatter:on
@Inject(method = "ageUp()V", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/frog/Tadpole;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V"))
private void arclight$transform(CallbackInfo ci, ServerLevel serverLevel, Frog frog) {
if (CraftEventFactory.callEntityTransformEvent((Tadpole) (Object) this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) {
this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled
ci.cancel();
} else {
((ServerWorldBridge) serverLevel).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.METAMORPHOSIS);
}
}
}

View File

@ -0,0 +1,31 @@
package io.izzel.arclight.common.mixin.core.world.entity.animal.goat;
import io.izzel.arclight.common.mixin.core.world.entity.animal.AnimalMixin;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.animal.goat.Goat;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemUtils;
import net.minecraft.world.item.Items;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Goat.class)
public abstract class GoatMixin extends AnimalMixin {
@Eject(method = "mobInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemUtils;createFilledResult(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;"))
private ItemStack arclight$bucketFill(ItemStack handItem, Player player, ItemStack p_41816_, CallbackInfoReturnable<InteractionResult> cir) {
org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, handItem, Items.MILK_BUCKET);
if (event.isCancelled()) {
cir.setReturnValue(InteractionResult.PASS);
return null;
}
return ItemUtils.createFilledResult(handItem, player, CraftItemStack.asNMSCopy(event.getItemStack()));
}
}

View File

@ -10,10 +10,11 @@ import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance;
import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.dimension.end.EndDragonFight;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.AABB;
@ -22,17 +23,22 @@ import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
@Mixin(EnderDragon.class)
public abstract class EnderDragonMixin extends MobMixin {
@Shadow @Final @Nullable private EndDragonFight dragonFight;
private Explosion explosionSource = new Explosion(null, (EnderDragon) (Object) this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY);
@Redirect(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/enderdragon/phases/DragonPhaseInstance;getFlyTargetLocation()Lnet/minecraft/world/phys/Vec3;"))
@ -71,7 +77,7 @@ public abstract class EnderDragonMixin extends MobMixin {
for (int i3 = k; i3 <= j2; ++i3) {
final BlockPos blockposition = new BlockPos(k2, l2, i3);
final BlockState iblockdata = this.level.getBlockState(blockposition);
if (!iblockdata.isAir() && iblockdata.getMaterial() != Material.FIRE) {
if (!iblockdata.isAir() && !iblockdata.is(BlockTags.DRAGON_TRANSPARENT)) {
if (net.minecraftforge.common.ForgeHooks.canEntityDestroy(this.level, blockposition, (EnderDragon) (Object) this) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) {
flag2 = true;
destroyedBlocks.add(CraftBlock.at(this.level, blockposition));
@ -106,11 +112,11 @@ public abstract class EnderDragonMixin extends MobMixin {
final net.minecraft.world.level.block.Block nmsBlock = craftBlock.getNMS().getBlock();
if (nmsBlock.dropFromExplosion(this.explosionSource)) {
BlockEntity tileentity = craftBlock.getNMS().hasBlockEntity() ? this.level.getBlockEntity(blockposition2) : null;
LootContext.Builder loottableinfo_builder = new LootContext.Builder((ServerLevel)this.level).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition2)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0f / event.getYield()).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity);
LootContext.Builder loottableinfo_builder = new LootContext.Builder((ServerLevel) this.level).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition2)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0f / event.getYield()).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity);
for (ItemStack stack : craftBlock.getNMS().getDrops(loottableinfo_builder)) {
Block.popResource(this.level, blockposition2, stack);
}
craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level, blockposition2, ItemStack.EMPTY);
craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level, blockposition2, ItemStack.EMPTY, false);
// net.minecraft.block.Block.spawnDrops(craftBlock.getNMS(), loottableinfo_builder);
}
nmsBlock.wasExploded(this.level, blockposition2, this.explosionSource);
@ -124,4 +130,17 @@ public abstract class EnderDragonMixin extends MobMixin {
return flag;
}
// TODO FIXME: exp patch for end dragon
@Override
public int getExpReward() {
// CraftBukkit - Moved from #tickDeath method
boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT);
short short0 = 500;
if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) {
short0 = 12000;
}
return flag ? short0 : 0;
}
}

View File

@ -162,14 +162,8 @@ public abstract class ArmorStandMixin extends LivingEntityMixin {
@Override
public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slotIn, ItemStack stack, boolean silent) {
switch (slotIn.getType()) {
case HAND -> {
this.bridge$playEquipSound(stack, silent);
this.handItems.set(slotIn.getIndex(), stack);
}
case ARMOR -> {
this.bridge$playEquipSound(stack, silent);
this.armorItems.set(slotIn.getIndex(), stack);
}
case HAND -> this.bridge$playEquipSound(slotIn, this.handItems.set(slotIn.getIndex(), stack), stack, silent);
case ARMOR -> this.bridge$playEquipSound(slotIn, this.armorItems.set(slotIn.getIndex(), stack), stack, silent);
}
}

View File

@ -22,7 +22,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ItemFrame.class)
public abstract class ItemFrameMixin extends HangingEntityMixin {
// @formatter:off
@Shadow @Final private static EntityDataAccessor<ItemStack> DATA_ITEM;
@Shadow protected abstract void onItemChanged(ItemStack p_218866_);
// @formatter:on
@Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ItemFrame;dropItem(Lnet/minecraft/world/entity/Entity;Z)V"))
private void arclight$damageNonLiving(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
@ -35,8 +38,8 @@ public abstract class ItemFrameMixin extends HangingEntityMixin {
if (!itemstack.isEmpty()) {
itemstack = itemstack.copy();
itemstack.setCount(1);
itemstack.setEntityRepresentation((ItemFrame) (Object) this);
}
this.onItemChanged(itemstack);
this.getEntityData().set(DATA_ITEM, itemstack);
if (!itemstack.isEmpty() && playSound) {
this.playSound(SoundEvents.ITEM_FRAME_ADD_ITEM, 1.0f, 1.0f);

View File

@ -1,22 +1,19 @@
package io.izzel.arclight.common.mixin.core.world.entity.monster;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.world.entity.monster.ElderGuardian;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ElderGuardian.class)
public abstract class ElderGuardianMixin extends PathfinderMobMixin {
@Redirect(method = "customServerAiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z"))
private boolean arclight$potionReason(ServerPlayer playerEntity, MobEffectInstance effectInstanceIn, Entity entity) {
((ServerPlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ATTACK);
return playerEntity.addEffect(effectInstanceIn);
@Inject(method = "customServerAiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/effect/MobEffectUtil;addEffectToPlayersAround(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;DLnet/minecraft/world/effect/MobEffectInstance;I)Ljava/util/List;"))
private void arclight$potionReason(CallbackInfo ci) {
ArclightCaptures.captureEffectCause(EntityPotionEffectEvent.Cause.ATTACK);
}
}

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.entity.monster;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
@ -13,8 +14,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Random;
@Mixin(targets = "net.minecraft.world.entity.monster.EnderMan$EndermanLeaveBlockGoal")
public class EnderMan_EndermanLeaveBlockGoalMixin {
@ -24,7 +23,7 @@ public class EnderMan_EndermanLeaveBlockGoalMixin {
@Inject(method = "tick", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
private void arclight$entityChangeBlock(CallbackInfo ci, Random random, Level world, int i, int j, int k, BlockPos blockPos, BlockState blockState, BlockPos blockPos1, BlockState blockState1, BlockState blockState2) {
private void arclight$entityChangeBlock(CallbackInfo ci, RandomSource random, Level world, int i, int j, int k, BlockPos blockPos, BlockState blockState, BlockPos blockPos1, BlockState blockState1, BlockState blockState2) {
if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockPos, blockState2).isCancelled()) {
ci.cancel();
}

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.entity.monster;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
@ -13,8 +14,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Random;
@Mixin(targets = "net.minecraft.world.entity.monster.EnderMan$EndermanTakeBlockGoal")
public class EnderMan_EndermanTakeBlockGoalMixin {
@ -24,7 +23,7 @@ public class EnderMan_EndermanTakeBlockGoalMixin {
@Inject(method = "tick", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/EnderMan;setCarriedBlock(Lnet/minecraft/world/level/block/state/BlockState;)V"))
private void arclight$entityChangeBlock(CallbackInfo ci, Random random, Level world, int i, int j, int k, BlockPos blockPos) {
private void arclight$entityChangeBlock(CallbackInfo ci, RandomSource random, Level world, int i, int j, int k, BlockPos blockPos) {
if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockPos, Blocks.AIR.defaultBlockState()).isCancelled()) {
ci.cancel();
}

View File

@ -7,7 +7,9 @@ import net.minecraft.core.Direction;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.monster.Shulker;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.ForgeEventFactory;
import org.bukkit.Bukkit;
@ -64,6 +66,7 @@ public abstract class ShulkerMixin extends PathfinderMobMixin {
this.setAttachFace(direction);
this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F);
this.setPos((double) blockpos1.getX() + 0.5D, blockpos1.getY(), (double) blockpos1.getZ() + 0.5D);
this.level.gameEvent(GameEvent.TELEPORT, blockpos, GameEvent.Context.of((Entity) (Object) this));
this.entityData.set(DATA_PEEK_ID, (byte) 0);
this.setTarget(null);
return true;

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster;
import io.izzel.arclight.api.ArclightVersion;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.monster.Silverfish;
import net.minecraft.world.level.Level;
@ -16,8 +17,6 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Random;
@Mixin(targets = "net.minecraft.world.entity.monster.Silverfish$SilverfishWakeUpFriendsGoal")
public abstract class Silverfish_WakeUpFriendsGoalMixin extends Goal {
@ -33,7 +32,7 @@ public abstract class Silverfish_WakeUpFriendsGoalMixin extends Goal {
--this.lookForFriends;
if (this.lookForFriends <= 0) {
Level world = this.silverfish.level;
Random random = this.silverfish.getRandom();
RandomSource random = this.silverfish.getRandom();
BlockPos blockpos = this.silverfish.blockPosition();
for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) {

View File

@ -0,0 +1,20 @@
package io.izzel.arclight.common.mixin.core.world.entity.monster;
import net.minecraft.world.entity.monster.Strider;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Strider.class)
public class StriderMixin {
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Strider;setSuffocating(Z)V"))
private void arclight$temperatureChange(Strider instance, boolean flag) {
if (flag ^ instance.isSuffocating()) {
if (CraftEventFactory.callStriderTemperatureChangeEvent(instance, flag)) {
instance.setSuffocating(flag);
}
}
}
}

View File

@ -68,13 +68,13 @@ public abstract class ZombieMixin extends PathfinderMobMixin {
}
}
@Eject(method = "killed", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;convertTo(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;"))
private <T extends Mob> T arclight$transform(Villager villagerEntity, EntityType<T> entityType, boolean flag, CallbackInfo ci) {
@Eject(method = "wasKilled", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;convertTo(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;"))
private <T extends Mob> T arclight$transform(Villager villagerEntity, EntityType<T> entityType, boolean flag, CallbackInfoReturnable<Boolean> cir) {
((WorldBridge) villagerEntity.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.INFECTION);
((MobEntityBridge) villagerEntity).bridge$pushTransformReason(EntityTransformEvent.TransformReason.INFECTION);
T t = villagerEntity.convertTo(entityType, flag);
if (t == null) {
ci.cancel();
cir.setReturnValue(false);
}
return t;
}

View File

@ -0,0 +1,21 @@
package io.izzel.arclight.common.mixin.core.world.entity.monster.warden;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.monster.warden.Warden;
import net.minecraft.world.phys.Vec3;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Warden.class)
public class WardenMixin {
@Inject(method = "applyDarknessAround", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/effect/MobEffectUtil;addEffectToPlayersAround(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;DLnet/minecraft/world/effect/MobEffectInstance;I)Ljava/util/List;"))
private static void arclight$reason(ServerLevel p_219376_, Vec3 p_219377_, Entity p_219378_, int p_219379_, CallbackInfo ci) {
ArclightCaptures.captureEffectCause(EntityPotionEffectEvent.Cause.WARDEN);
}
}

View File

@ -0,0 +1,51 @@
package io.izzel.arclight.common.mixin.core.world.entity.npc;
import io.izzel.arclight.common.mod.server.ArclightContainer;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.npc.InventoryCarrier;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(InventoryCarrier.class)
public interface InventoryCarrierMixin {
// @formatter:off
@Shadow SimpleContainer getInventory();
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
static void pickUpItem(Mob mob, InventoryCarrier carrier, ItemEntity itemEntity) {
ItemStack itemstack = itemEntity.getItem();
if (mob.wantsToPickUp(itemstack)) {
SimpleContainer simplecontainer = carrier.getInventory();
boolean flag = simplecontainer.canAddItem(itemstack);
if (!flag) {
return;
}
var remaining = ArclightContainer.copyOf(carrier.getInventory()).addItem(itemstack);
if (CraftEventFactory.callEntityPickupItemEvent(mob, itemEntity, remaining.getCount(), false).isCancelled()) {
return;
}
mob.onItemPickup(itemEntity);
int i = itemstack.getCount();
ItemStack itemstack1 = simplecontainer.addItem(itemstack);
mob.take(itemEntity, i - itemstack1.getCount());
if (itemstack1.isEmpty()) {
itemEntity.discard();
} else {
itemstack.setCount(itemstack1.getCount());
}
}
}
}

View File

@ -4,7 +4,6 @@ import io.izzel.arclight.common.bridge.core.item.MerchantOfferBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.animal.IronGolem;
import net.minecraft.world.entity.monster.Witch;
import net.minecraft.world.item.trading.MerchantOffer;
import org.bukkit.Bukkit;
@ -19,7 +18,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(net.minecraft.world.entity.npc.Villager.class)
@ -57,8 +55,13 @@ public abstract class VillagerMixin extends AbstractVillagerMixin {
}
}
@Inject(method = "trySpawnGolem", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private void arclight$ironGolemReason(ServerLevel world, CallbackInfoReturnable<IronGolem> cir) {
@Inject(method = "spawnGolemIfNeeded", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/SpawnUtil;trySpawnMob(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;IIILnet/minecraft/util/SpawnUtil$Strategy;)Ljava/util/Optional;"))
private void arclight$ironGolemReason(ServerLevel world, long p_35399_, int p_35400_, CallbackInfo ci) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE);
}
@Inject(method = "spawnGolemIfNeeded", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/util/SpawnUtil;trySpawnMob(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;IIILnet/minecraft/util/SpawnUtil$Strategy;)Ljava/util/Optional;"))
private void arclight$ironGolemReasonReset(ServerLevel world, long p_35399_, int p_35400_, CallbackInfo ci) {
((WorldBridge) world).bridge$pushAddEntityReason(null);
}
}

View File

@ -13,6 +13,7 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge;
import io.izzel.arclight.common.mixin.core.world.entity.LivingEntityMixin;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -43,6 +44,7 @@ import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Abilities;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.ProfilePublicKey;
import net.minecraft.world.food.FoodData;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.InventoryMenu;
@ -87,6 +89,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
import java.util.Optional;
@Mixin(net.minecraft.world.entity.player.Player.class)
public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEntityBridge, IForgePlayer {
@ -127,13 +130,15 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
@Shadow public abstract GameProfile getGameProfile();
@Shadow public abstract Inventory getInventory();
@Shadow public abstract Abilities getAbilities();
@Shadow public abstract void setLastDeathLocation(Optional<GlobalPos> p_219750_);
@Shadow public abstract Optional<GlobalPos> getLastDeathLocation();
// @formatter:on
public boolean fauxSleeping;
public int oldLevel;
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(Level p_i241920_1_, BlockPos p_i241920_2_, float p_i241920_3_, GameProfile p_i241920_4_, CallbackInfo ci) {
private void arclight$init(Level p_219727_, BlockPos p_219728_, float p_219729_, GameProfile p_219730_, ProfilePublicKey p_219731_, CallbackInfo ci) {
oldLevel = -1;
((FoodStatsBridge) this.foodData).bridge$setEntityHuman((net.minecraft.world.entity.player.Player) (Object) this);
((IInventoryBridge) this.enderChestInventory).setOwner(this.getBukkitEntity());
@ -418,7 +423,11 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
public Either<net.minecraft.world.entity.player.Player.BedSleepingProblem, Unit> startSleepInBed(BlockPos at, boolean force) {
this.arclight$forceSleep = force;
return this.startSleepInBed(at);
try {
return this.startSleepInBed(at);
} finally {
this.arclight$forceSleep = false;
}
}
@Override
@ -545,16 +554,14 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
}
@Override
public void setItemSlot(EquipmentSlot slotIn, ItemStack stack, boolean silent) {
if (slotIn == EquipmentSlot.MAINHAND) {
this.bridge$playEquipSound(stack, silent);
this.inventory.items.set(this.inventory.selected, stack);
} else if (slotIn == EquipmentSlot.OFFHAND) {
this.bridge$playEquipSound(stack, silent);
this.inventory.offhand.set(0, stack);
} else if (slotIn.getType() == EquipmentSlot.Type.ARMOR) {
this.bridge$playEquipSound(stack, silent);
this.inventory.armor.set(slotIn.getIndex(), stack);
public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
this.verifyEquippedItem(stack);
if (slot == EquipmentSlot.MAINHAND) {
this.equipEventAndSound(slot, this.inventory.items.set(this.inventory.selected, stack), stack, silent);
} else if (slot == EquipmentSlot.OFFHAND) {
this.equipEventAndSound(slot, this.inventory.offhand.set(0, stack), stack, silent);
} else if (slot.getType() == EquipmentSlot.Type.ARMOR) {
this.equipEventAndSound(slot, this.inventory.armor.set(slot.getIndex(), stack), stack, silent);
}
}

View File

@ -14,15 +14,15 @@ import io.izzel.arclight.common.mod.server.block.ChestBlockDoubleInventoryHacks;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.BlockUtil;
import net.minecraft.ChatFormatting;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.PositionImpl;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.PacketSendListener;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket;
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
import net.minecraft.network.protocol.game.ClientboundHorseScreenOpenPacket;
@ -68,6 +68,7 @@ import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.block.NetherPortalBlock;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.portal.PortalInfo;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.phys.AABB;
@ -102,7 +103,6 @@ import org.bukkit.event.player.PlayerLocaleChangeEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.MainHand;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@ -121,7 +121,6 @@ import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
import java.util.UUID;
import java.util.function.Consumer;
@Mixin(ServerPlayer.class)
@ -154,12 +153,10 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
@Shadow public abstract float getRespawnAngle();
@Shadow protected abstract void tellNeutralMobsThatIDied();
@Shadow protected abstract void createEndPlatform(ServerLevel p_242110_1_, BlockPos p_242110_2_);
@Shadow @Final private static Logger LOGGER;
@Shadow public abstract boolean isCreative();
@Shadow public abstract void setRespawnPosition(ResourceKey<Level> p_242111_1_, @org.jetbrains.annotations.Nullable BlockPos p_242111_2_, float p_242111_3_, boolean p_242111_4_, boolean p_242111_5_);
@Shadow protected abstract boolean bedBlocked(BlockPos p_241156_1_, Direction p_241156_2_);
@Shadow protected abstract boolean bedInRange(BlockPos p_241147_1_, Direction p_241147_2_);
@Shadow public abstract void sendMessage(Component component, UUID senderUUID);
@Shadow public abstract void setLevel(ServerLevel p_143426_);
@Shadow(remap = false) private boolean hasTabListName;
@Shadow(remap = false) private Component tabListDisplayName;
@ -316,6 +313,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
*/
@Overwrite
public void die(DamageSource damagesource) {
this.gameEvent(GameEvent.ENTITY_DIE);
if (net.minecraftforge.common.ForgeHooks.onLivingDeath((ServerPlayer) (Object) this, damagesource))
return;
boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
@ -358,30 +356,26 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
} else {
itextcomponent = CraftChatMessage.fromStringOrNull(deathMessage);
}
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), itextcomponent), (future) -> {
if (!future.isSuccess()) {
int i = 256;
String s = itextcomponent.getString(256);
Component itextcomponent1 = new TranslatableComponent("death.attack.message_too_long", (new TextComponent(s)).withStyle(ChatFormatting.YELLOW));
Component itextcomponent2 = (new TranslatableComponent("death.attack.even_more_magic", this.getDisplayName())).withStyle((p_212357_1_) -> {
return p_212357_1_.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, itextcomponent1));
});
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), itextcomponent2));
}
});
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), itextcomponent), PacketSendListener.exceptionallySend(() -> {
String s = itextcomponent.getString(256);
Component component1 = Component.translatable("death.attack.message_too_long", Component.literal(s).withStyle(ChatFormatting.YELLOW));
Component component2 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()).withStyle((p_143420_) -> {
return p_143420_.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, component1));
});
return new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), component2);
}));
Team scoreboardteambase = this.getTeam();
if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != Team.Visibility.ALWAYS) {
if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) {
this.server.getPlayerList().broadcastToTeam((ServerPlayer) (Object) this, itextcomponent);
this.server.getPlayerList().broadcastSystemToTeam((ServerPlayer) (Object) this, itextcomponent);
} else if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) {
this.server.getPlayerList().broadcastToAllExceptTeam((ServerPlayer) (Object) this, itextcomponent);
this.server.getPlayerList().broadcastSystemToAllExceptTeam((ServerPlayer) (Object) this, itextcomponent);
}
} else {
this.server.getPlayerList().broadcastMessage(itextcomponent, ChatType.SYSTEM, Util.NIL_UUID);
this.server.getPlayerList().broadcastSystemMessage(itextcomponent, false);
}
} else {
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), TextComponent.EMPTY));
this.connection.send(new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), CommonComponents.EMPTY));
}
this.removeEntitiesOnShoulder();
@ -412,6 +406,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
this.setTicksFrozen(0);
this.setSharedFlagOnFire(false);
this.getCombatTracker().recheckStatus();
this.setLastDeathLocation(Optional.of(GlobalPos.of(this.level.dimension(), this.blockPosition())));
}
@Redirect(method = "awardKillScore", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/scores/Scoreboard;forAllObjectives(Lnet/minecraft/world/scores/criteria/ObjectiveCriteria;Ljava/lang/String;Ljava/util/function/Consumer;)V"))
@ -494,7 +489,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
}
ServerLevel[] exitWorld = new ServerLevel[]{server};
LevelData iworldinfo = server.getLevelData();
this.connection.send(new ClientboundRespawnPacket(server.dimensionTypeRegistration(), server.dimension(), BiomeManager.obfuscateSeed(server.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), server.isDebug(), server.isFlat(), true));
this.connection.send(new ClientboundRespawnPacket(server.dimensionTypeId(), server.dimension(), BiomeManager.obfuscateSeed(server.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), server.isDebug(), server.isFlat(), true, this.getLastDeathLocation()));
this.connection.send(new ClientboundChangeDifficultyPacket(iworldinfo.getDifficulty(), iworldinfo.isDifficultyLocked()));
PlayerList playerlist = this.server.getPlayerList();
playerlist.sendPlayerPermissionLevel((ServerPlayer) (Object) this);
@ -528,7 +523,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
if (newWorld != exitWorld[0]) {
exitWorld[0] = newWorld;
LevelData newWorldInfo = exitWorld[0].getLevelData();
this.connection.send(new ClientboundRespawnPacket(exitWorld[0].dimensionTypeRegistration(), exitWorld[0].dimension(), BiomeManager.obfuscateSeed(exitWorld[0].getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), exitWorld[0].isDebug(), exitWorld[0].isFlat(), true));
this.connection.send(new ClientboundRespawnPacket(exitWorld[0].dimensionTypeId(), exitWorld[0].dimension(), BiomeManager.obfuscateSeed(exitWorld[0].getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), exitWorld[0].isDebug(), exitWorld[0].isFlat(), true, this.getLastDeathLocation()));
this.connection.send(new ClientboundChangeDifficultyPacket(newWorldInfo.getDifficulty(), newWorldInfo.isDifficultyLocked()));
}
@ -574,9 +569,9 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
}
@Override
protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, BlockPos exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) {
protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, PositionImpl exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) {
Location enter = this.getBukkitEntity().getLocation();
Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ(), this.getYRot(), this.getXRot());
Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.x(), exitPosition.y(), exitPosition.z(), this.getYRot(), this.getXRot());
PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, 128, true, creationRadius);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) {
@ -750,22 +745,6 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
this.lastSentExp = -1;
}
public void sendMessage(UUID uuid, Component[] components) {
for (final Component component : components) {
this.sendMessage(component, uuid == null ? Util.NIL_UUID : uuid);
}
}
@Override
public void bridge$sendMessage(Component[] components, UUID uuid) {
sendMessage(uuid, components);
}
@Override
public void bridge$sendMessage(Component component, UUID uuid) {
this.sendMessage(component, uuid == null ? Util.NIL_UUID : uuid);
}
@Inject(method = "updateOptions", at = @At("HEAD"))
private void arclight$settingChange(ServerboundClientInformationPacket packetIn, CallbackInfo ci) {
if (this.getMainArm() != packetIn.mainHand()) {

View File

@ -3,7 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.raid;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.bridge.core.world.raid.RaidBridge;
import net.minecraft.advancements.critereon.LocationTrigger;
import net.minecraft.advancements.critereon.PlayerTrigger;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@ -84,8 +84,8 @@ public class RaidMixin implements RaidBridge {
private transient List<Player> arclight$winners;
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/critereon/LocationTrigger;trigger(Lnet/minecraft/server/level/ServerPlayer;)V"))
public void arclight$addWinner(LocationTrigger trigger, ServerPlayer player) {
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/critereon/PlayerTrigger;trigger(Lnet/minecraft/server/level/ServerPlayer;)V"))
public void arclight$addWinner(PlayerTrigger trigger, ServerPlayer player) {
trigger.trigger(player);
if (arclight$winners == null) {
arclight$winners = new ArrayList<>();

View File

@ -18,6 +18,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseRailBlock;
import net.minecraft.world.level.block.PoweredRailBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -107,6 +108,7 @@ public abstract class AbstractMinecartMixin extends EntityMixin {
this.setHurtTime(10);
this.markHurt();
this.setDamage(this.getDamage() + amount * 10.0f);
this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
boolean flag = source.getEntity() instanceof Player && ((Player) source.getEntity()).getAbilities().instabuild;
if (flag || this.getDamage() > 40.0f) {
VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, passenger);

View File

@ -0,0 +1,67 @@
package io.izzel.arclight.common.mixin.core.world.entity.vehicle;
import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.entity.vehicle.ChestBoat;
import net.minecraft.world.item.ItemStack;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList;
import java.util.List;
@Mixin(ChestBoat.class)
public abstract class ChestBoatMixin extends BoatMixin implements IInventoryBridge, Container {
@Shadow private NonNullList<ItemStack> itemStacks;
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK;
@Override
public List<ItemStack> getContents() {
return this.itemStacks;
}
@Override
public void onOpen(CraftHumanEntity who) {
transaction.add(who);
}
@Override
public void onClose(CraftHumanEntity who) {
transaction.remove(who);
}
@Override
public List<HumanEntity> getViewers() {
return transaction;
}
@Override
public InventoryHolder getOwner() {
org.bukkit.entity.Entity entity = getBukkitEntity();
if (entity instanceof InventoryHolder) return (InventoryHolder) entity;
return null;
}
@Override
public int getMaxStackSize() {
return maxStack;
}
@Override
public void setMaxStackSize(int size) {
maxStack = size;
}
@Override
public Location getLocation() {
return getBukkitEntity().getLocation();
}
}

View File

@ -1,19 +0,0 @@
package io.izzel.arclight.common.mixin.core.world.gen.feature.structure;
import io.izzel.arclight.common.bridge.core.world.IWorldBridge;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.StructureFeatureManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(StructureFeatureManager.class)
public class StructureFeatureManagerMixin {
@Shadow @Final private LevelAccessor level;
public Level getWorld() {
return ((IWorldBridge) this.level).bridge$getMinecraftWorld();
}
}

View File

@ -2,26 +2,25 @@ package io.izzel.arclight.common.mixin.core.world.gen.feature.structure;
import io.izzel.arclight.common.bridge.core.world.IWorldWriterBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.SwamplandHutPiece;
import net.minecraft.world.level.levelgen.structure.structures.SwampHutPiece;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(SwamplandHutPiece.class)
@Mixin(SwampHutPiece.class)
public class SwampHutPieceMixin {
@Inject(method = "postProcess", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/WorldGenLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private void arclight$spawnReason1(WorldGenLevel level, StructureFeatureManager p_192667_, ChunkGenerator p_192668_, Random p_192669_, BoundingBox p_192670_, ChunkPos p_192671_, BlockPos p_192672_, CallbackInfo ci) {
private void arclight$spawnReason1(WorldGenLevel level, StructureManager p_229962_, ChunkGenerator p_229963_, RandomSource p_229964_, BoundingBox p_229965_, ChunkPos p_229966_, BlockPos p_229967_, CallbackInfo ci) {
((IWorldWriterBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.CHUNK_GEN);
}

View File

@ -1,29 +0,0 @@
package io.izzel.arclight.common.mixin.core.world.gen.feature.template;
import com.mojang.datafixers.DataFixer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.storage.LevelStorageSource;
@Mixin(StructureManager.class)
public class TemplateManagerMixin {
@Shadow @Final @Mutable private Map<ResourceLocation, StructureTemplate> structureRepository;
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(ResourceManager p_i232119_1_, LevelStorageSource.LevelStorageAccess p_i232119_2_, DataFixer fixer, CallbackInfo ci) {
this.structureRepository = Collections.synchronizedMap(this.structureRepository);
}
}

View File

@ -6,7 +6,6 @@ import io.izzel.arclight.common.bridge.core.inventory.container.SlotBridge;
import io.izzel.arclight.common.mod.server.ArclightContainer;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.SlotAccess;
@ -19,6 +18,7 @@ import net.minecraft.world.inventory.ContainerSynchronizer;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistries;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.inventory.CraftInventory;
@ -92,10 +92,11 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge {
public Component getTitle() {
if (this.title == null) {
if (this.menuType != null && this.menuType.getRegistryName() != null) {
return new TextComponent(this.menuType.getRegistryName().toString());
if (this.menuType != null) {
var key = ForgeRegistries.MENU_TYPES.getKey(this.menuType);
return Component.translatable(key.toString());
} else {
return new TextComponent(this.toString());
return Component.translatable(this.toString());
}
}
return this.title;
@ -261,8 +262,8 @@ public abstract class AbstractContainerMenuMixin implements ContainerBridge {
int j3 = clickaction == ClickAction.PRIMARY ? itemstack11.getCount() : 1;
this.setCarried(slot7.safeInsert(itemstack11, j3));
} else if (itemstack11.getCount() <= slot7.getMaxStackSize(itemstack11)) {
slot7.set(itemstack11);
this.setCarried(itemstack10);
slot7.set(itemstack11);
}
} else if (ItemStack.isSameItemSameTags(itemstack10, itemstack11)) {
Optional<ItemStack> optional = slot7.tryRemove(itemstack10.getCount(), itemstack11.getMaxStackSize() - itemstack11.getCount(), player);

View File

@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.util.RandomSource;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
@ -23,7 +24,6 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.EnchantmentTableBlock;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.registries.ForgeRegistries;
@ -49,7 +49,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
import java.util.Map;
import java.util.Random;
@Mixin(EnchantmentMenu.class)
public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMixin implements PosContainerBridge {
@ -57,7 +56,7 @@ public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMix
// @formatter:off
@Shadow @Final private Container enchantSlots;
@Shadow @Final private ContainerLevelAccess access;
@Shadow @Final private Random random;
@Shadow @Final private RandomSource random;
@Shadow @Final private DataSlot enchantmentSeed;
@Shadow @Final public int[] costs;
@Shadow @Final public int[] enchantClue;

View File

@ -3,7 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.inventory;
import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.inventory.CraftingInventoryBridge;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
@ -36,7 +36,7 @@ public abstract class PlayerContainerMixin extends AbstractContainerMenuMixin {
this.playerInventory = playerInventory;
((CraftingInventoryBridge) this.craftSlots).bridge$setOwner(playerInventory.player);
((CraftingInventoryBridge) this.craftSlots).bridge$setResultInventory(this.resultSlots);
this.setTitle(new TranslatableComponent("container.crafting"));
this.setTitle(Component.translatable("container.crafting"));
}
@Inject(method = "slotsChanged", at = @At("HEAD"))

View File

@ -2,7 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.inventory;
import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.util.IWorldPosCallableBridge;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.AnvilMenu;
import net.minecraft.world.inventory.DataSlot;
@ -181,7 +181,7 @@ public abstract class RepairContainerMixin extends ItemCombinerMixin {
} else if (!this.itemName.equals(itemstack.getHoverName().getString())) {
k = 1;
i += k;
itemstack1.setHoverName(new TextComponent(this.itemName));
itemstack1.setHoverName(Component.literal(this.itemName));
}
if (flag && !itemstack1.isBookEnchantable(itemstack2)) itemstack1 = ItemStack.EMPTY;

View File

@ -7,8 +7,8 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.PlaceOnWaterBlockItem;
import net.minecraft.world.item.SolidBucketItem;
import net.minecraft.world.item.WaterLilyBlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@ -43,7 +43,7 @@ public abstract class BlockItemMixin {
@Inject(method = "place", locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/item/BlockItem;getPlacementState(Lnet/minecraft/world/item/context/BlockPlaceContext;)Lnet/minecraft/world/level/block/state/BlockState;"))
private void arclight$prePlaceLilypad(BlockPlaceContext context, CallbackInfoReturnable<InteractionResult> cir, BlockPlaceContext context1) {
if ((Object) this instanceof WaterLilyBlockItem || (Object) this instanceof SolidBucketItem) {
if ((Object) this instanceof PlaceOnWaterBlockItem || (Object) this instanceof SolidBucketItem) {
this.arclight$state = CraftBlockStates.getBlockState(context1.getLevel(), context1.getClickedPos());
}
}

View File

@ -30,11 +30,12 @@ import java.util.List;
import java.util.function.Predicate;
@Mixin(BoatItem.class)
public class BoatItemMixin extends Item {
public abstract class BoatItemMixin extends Item {
// @formatter:off
@Shadow @Final private static Predicate<Entity> ENTITY_PREDICATE;
@Shadow @Final private Boat.Type type;
@Shadow protected abstract Boat getBoat(Level p_220017_, HitResult p_220018_);
// @formatter:on
public BoatItemMixin(Properties properties) {
@ -75,7 +76,7 @@ public class BoatItemMixin extends Item {
}
}
Boat boatentity = new Boat(worldIn, result.getLocation().x, result.getLocation().y, result.getLocation().z);
Boat boatentity = this.getBoat(worldIn, result);
boatentity.setType(this.type);
boatentity.setYRot(playerIn.getYRot());
if (!worldIn.noCollision(boatentity, boatentity.getBoundingBox().inflate(-0.1D))) {

View File

@ -13,6 +13,9 @@ import net.minecraft.world.item.ChorusFruitItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.event.ForgeEventFactory;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@ -60,8 +63,11 @@ public class ChorusFruitItemMixin extends Item {
if (entityLiving.isPassenger()) {
entityLiving.stopRiding();
}
Vec3 vec3d = entityLiving.position();
var event = ForgeEventFactory.onChorusFruitTeleport(entityLiving, d3, d4, d5);
if (event.isCanceled()) return itemstack;
if (entityLiving.randomTeleport(d3, d4, d5, true)) {
worldIn.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of(entityLiving));
SoundEvent soundevent = entityLiving instanceof Fox ? SoundEvents.FOX_TELEPORT : SoundEvents.CHORUS_FRUIT_TELEPORT;
worldIn.playSound(null, d0, d1, d2, soundevent, SoundSource.PLAYERS, 1.0F, 1.0F);
entityLiving.playSound(soundevent, 1.0F, 1.0F);

View File

@ -16,6 +16,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.FishHook;
import org.bukkit.event.player.PlayerFishEvent;
@ -46,6 +47,7 @@ public class FishingRodItemMixin extends Item {
playerIn.swing(handIn);
worldIn.playSound(null, playerIn.getX(), playerIn.getY(), playerIn.getZ(), SoundEvents.FISHING_BOBBER_RETRIEVE, SoundSource.NEUTRAL, 1.0F, 0.4F / (worldIn.getRandom().nextFloat() * 0.4F + 0.8F));
playerIn.gameEvent(GameEvent.ITEM_INTERACT_FINISH);
} else {
if (!worldIn.isClientSide) {
int k = EnchantmentHelper.getFishingSpeedBonus(itemstack);
@ -67,6 +69,7 @@ public class FishingRodItemMixin extends Item {
// playerIn.swingArm(handIn);
playerIn.awardStat(Stats.ITEM_USED.get(this));
playerIn.gameEvent(GameEvent.ITEM_INTERACT_START);
}
return InteractionResultHolder.sidedSuccess(itemstack, worldIn.isClientSide());

View File

@ -4,12 +4,13 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBrid
import io.izzel.arclight.common.bridge.core.item.ItemStackBridge;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.capabilities.CapabilityProvider;
import net.minecraftforge.registries.IRegistryDelegate;
import net.minecraftforge.registries.ForgeRegistries;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
@ -26,7 +27,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
import java.util.function.Consumer;
@Mixin(ItemStack.class)
@ -36,7 +36,7 @@ public abstract class ItemStackMixin extends CapabilityProvider<ItemStack> imple
@Shadow @Deprecated private Item item;
@Shadow private int count;
@Shadow(remap = false) private CompoundTag capNBT;
@Mutable @Shadow(remap = false) @Final private IRegistryDelegate<Item> delegate;
@Mutable @Shadow(remap = false) @Final private net.minecraft.core.Holder.Reference<Item> delegate;
// @formatter:on
protected ItemStackMixin(Class<ItemStack> baseClass) {
@ -69,8 +69,8 @@ public abstract class ItemStackMixin extends CapabilityProvider<ItemStack> imple
this.convertStack(version);
}
@ModifyVariable(method = "hurt", index = 1, name = "amount", at = @At(value = "JUMP", opcode = Opcodes.IFGT, ordinal = 0))
private int arclight$itemDamage(int i, int amount, Random rand, ServerPlayer damager) {
@ModifyVariable(method = "hurt", index = 1, at = @At(value = "JUMP", opcode = Opcodes.IFGT, ordinal = 0))
private int arclight$itemDamage(int i, int amount, RandomSource rand, ServerPlayer damager) {
if (damager != null) {
PlayerItemDamageEvent event = new PlayerItemDamageEvent(((ServerPlayerEntityBridge) damager).bridge$getBukkitEntity(), CraftItemStack.asCraftMirror((ItemStack) (Object) this), i);
event.getPlayer().getServer().getPluginManager().callEvent(event);
@ -96,6 +96,6 @@ public abstract class ItemStackMixin extends CapabilityProvider<ItemStack> imple
@Deprecated
public void setItem(Item item) {
this.item = item;
this.delegate = item.delegate;
this.delegate = ForgeRegistries.ITEMS.getDelegateOrThrow(item);
}
}

View File

@ -35,7 +35,7 @@ public abstract class RecipeManagerMixin implements RecipeManagerBridge {
// @formatter:off
@Shadow public Map<RecipeType<?>, Map<ResourceLocation, Recipe<?>>> recipes;
@Shadow protected abstract <C extends Container, T extends Recipe<C>> Map<ResourceLocation, Recipe<C>> byType(RecipeType<T> recipeTypeIn);
@Shadow protected abstract <C extends Container, T extends Recipe<C>> Map<ResourceLocation, T> byType(RecipeType<T> p_44055_);
@Shadow private boolean hasErrors;
@Shadow @Final private static Logger LOGGER;
@Shadow(remap = false) public static Recipe<?> fromJson(ResourceLocation recipeId, JsonObject json, ICondition.IContext context) { return null; }
@ -65,7 +65,7 @@ public abstract class RecipeManagerMixin implements RecipeManagerBridge {
try {
if (entry.getValue().isJsonObject() && !CraftingHelper.processConditions(entry.getValue().getAsJsonObject(), "conditions", this.context)) {
LOGGER.info("Skipping loading recipe {} as it's conditions were not met", resourcelocation);
LOGGER.debug("Skipping loading recipe {} as it's conditions were not met", resourcelocation);
continue;
}
Recipe<?> irecipe = fromJson(resourcelocation, GsonHelper.convertToJsonObject(entry.getValue(), "top element"), this.context);
@ -92,8 +92,8 @@ public abstract class RecipeManagerMixin implements RecipeManagerBridge {
*/
@Overwrite
public <C extends Container, T extends Recipe<C>> Optional<T> getRecipeFor(RecipeType<T> recipeTypeIn, C inventoryIn, Level worldIn) {
Optional<T> optional = this.byType(recipeTypeIn).values().stream().flatMap((p_44064_) -> {
return recipeTypeIn.tryMatch(p_44064_, worldIn, inventoryIn).stream();
Optional<T> optional = this.byType(recipeTypeIn).values().stream().filter((recipe) -> {
return recipe.matches(inventoryIn, worldIn);
}).findFirst();
((IInventoryBridge) inventoryIn).setCurrentRecipe(optional.orElse(null));
return optional;

View File

@ -1,6 +1,5 @@
package io.izzel.arclight.common.mixin.core.world.level;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.bridge.core.world.border.WorldBorderBridge;
import io.izzel.arclight.common.bridge.core.world.level.levelgen.ChunkGeneratorBridge;
@ -22,19 +21,16 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelWriter;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.block.CraftBlock;
@ -43,12 +39,10 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.generator.CraftWorldInfo;
import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator;
import org.bukkit.craftbukkit.v.generator.CustomWorldChunkManager;
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.v.util.CraftSpawnCategory;
import org.bukkit.entity.SpawnCategory;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.world.GenericGameEvent;
import org.bukkit.generator.ChunkGenerator;
import org.spigotmc.SpigotWorldConfig;
import org.spongepowered.asm.mixin.Final;
@ -59,7 +53,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
@ -76,9 +69,10 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter {
@Shadow @Final private WorldBorder worldBorder;
@Shadow public abstract long getDayTime();
@Shadow public abstract MinecraftServer shadow$getServer();
@Shadow @Final private DimensionType dimensionType;
@Shadow public abstract LevelData getLevelData();
@Shadow public abstract ResourceKey<Level> dimension();
@Shadow(remap = false) public abstract void markAndNotifyBlock(BlockPos p_46605_,@org.jetbrains.annotations.Nullable LevelChunk levelchunk, BlockState blockstate, BlockState p_46606_, int p_46607_, int p_46608_);
@Shadow public abstract DimensionType dimensionType();
@Accessor("thread") public abstract Thread arclight$getMainThread();
// @formatter:on
@ -95,20 +89,20 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter {
private static BlockPos lastPhysicsProblem; // Spigot
public boolean preventPoiUpdated = false;
public void arclight$constructor(WritableLevelData worldInfo, ResourceKey<Level> dimension, final Holder<DimensionType> dimensionType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed) {
public void arclight$constructor(WritableLevelData worldInfo, ResourceKey<Level> dimension, final Holder<DimensionType> dimensionType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, int maxNeighborUpdate) {
throw new RuntimeException();
}
public void arclight$constructor(WritableLevelData worldInfo, ResourceKey<Level> dimension, final Holder<DimensionType> dimensionType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
arclight$constructor(worldInfo, dimension, dimensionType, profiler, isRemote, isDebug, seed);
public void arclight$constructor(WritableLevelData worldInfo, ResourceKey<Level> dimension, final Holder<DimensionType> dimensionType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, int maxNeighborUpdate, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
arclight$constructor(worldInfo, dimension, dimensionType, profiler, isRemote, isDebug, seed, maxNeighborUpdate);
this.generator = gen;
this.environment = env;
this.biomeProvider = biomeProvider;
bridge$getWorld();
}
@Inject(method = "<init>(Lnet/minecraft/world/level/storage/WritableLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/Holder;Ljava/util/function/Supplier;ZZJ)V", at = @At("RETURN"))
private void arclight$init(WritableLevelData info, ResourceKey<Level> dimension, Holder<DimensionType> dimType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, CallbackInfo ci) {
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(WritableLevelData info, ResourceKey<Level> dimension, Holder<DimensionType> dimType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, int maxNeighborUpdates, CallbackInfo ci) {
((WorldBorderBridge) this.worldBorder).bridge$setWorld((Level) (Object) this);
for (SpawnCategory spawnCategory : SpawnCategory.values()) {
if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
@ -117,6 +111,11 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter {
}
}
@Override
public void bridge$setLastPhysicsProblem(BlockPos pos) {
lastPhysicsProblem = pos;
}
@Override
public Object2LongOpenHashMap<SpawnCategory> bridge$ticksPerSpawnCategory() {
return this.ticksPerSpawnCategory;
@ -174,31 +173,8 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter {
}
}
@Inject(method = "neighborChanged", cancellable = true,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;neighborChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/core/BlockPos;Z)V"),
locals = LocalCapture.CAPTURE_FAILHARD)
private void arclight$callBlockPhysics2(BlockPos pos, Block blockIn, BlockPos fromPos, CallbackInfo ci, BlockState blockState) {
try {
if (this.world != null) {
LevelAccessor iWorld = (LevelAccessor) this;
BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(iWorld, pos), CraftBlockData.fromData(blockState), CraftBlock.at(iWorld, fromPos));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
ci.cancel();
}
}
} catch (StackOverflowError e) {
lastPhysicsProblem = pos;
}
}
@Inject(method = "postGameEventInRadius", cancellable = true, at = @At("HEAD"))
private void arclight$gameEventEvent(Entity entity, GameEvent gameEvent, BlockPos pos, int i, CallbackInfo ci) {
GenericGameEvent event = new GenericGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(gameEvent))), new Location(this.getWorld(), pos.getX(), pos.getY(), pos.getZ()), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), i);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
ci.cancel();
}
public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, BlockState oldBlock, BlockState newBlock, BlockState actualBlock, int i, int j) {
this.markAndNotifyBlock(blockposition, chunk, oldBlock, newBlock, i, j);
}
public CraftServer getCraftServer() {
@ -222,7 +198,7 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter {
generator = getCraftServer().getGenerator(((ServerLevelData) this.getLevelData()).getLevelName());
if (generator != null && (Object) this instanceof ServerLevel serverWorld) {
org.bukkit.generator.WorldInfo worldInfo = new CraftWorldInfo((ServerLevelData) getLevelData(),
((ServerWorldBridge) this).bridge$getConvertable(), environment, this.dimensionType);
((ServerWorldBridge) this).bridge$getConvertable(), environment, this.dimensionType());
if (biomeProvider == null && generator != null) {
biomeProvider = generator.getDefaultBiomeProvider(worldInfo);
}

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BambooBlock;
import net.minecraft.world.level.block.Blocks;
@ -17,8 +18,6 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.Random;
@Mixin(BambooBlock.class)
public abstract class BambooBlockMixin extends BlockMixin {
@ -40,7 +39,7 @@ public abstract class BambooBlockMixin extends BlockMixin {
* @reason
*/
@Overwrite
protected void growBamboo(BlockState blockStateIn, Level worldIn, BlockPos posIn, Random rand, int height) {
protected void growBamboo(BlockState blockStateIn, Level worldIn, BlockPos posIn, RandomSource rand, int height) {
BlockState blockstate = worldIn.getBlockState(posIn.below());
BlockPos blockpos = posIn.below(2);
BlockState blockstate1 = worldIn.getBlockState(blockpos);

View File

@ -1,12 +1,18 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.dimension.LevelStem;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityCombustByBlockEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.At;
@ -15,6 +21,18 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BaseFireBlock.class)
public class BaseFireBlockMixin {
// fireExtinguished implemented per class
@Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V"))
private void arclight$onFire(Entity instance, int seconds, BlockState state, Level level, BlockPos pos) {
var event = new EntityCombustByBlockEvent(CraftBlock.at(level, pos), ((EntityBridge) instance).bridge$getBukkitEntity(), seconds);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
((EntityBridge) instance).bridge$setOnFire(event.getDuration(), false);
}
}
@Redirect(method = "onPlace", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;removeBlock(Lnet/minecraft/core/BlockPos;Z)Z"))
public boolean arclight$extinguish2(Level world, BlockPos pos, boolean isMoving) {
if (!CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.AIR.defaultBlockState()).isCancelled()) {

View File

@ -1,9 +1,86 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BedPart;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.BlockHitResult;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import static net.minecraft.world.level.block.HorizontalDirectionalBlock.FACING;
// todo 重新检查爆炸和 BedEvent 实现
@Mixin(BedBlock.class)
public class BedBlockMixin {
public abstract class BedBlockMixin {
// @formatter:off
@Shadow @Final public static EnumProperty<BedPart> PART;
@Shadow @Final public static BooleanProperty OCCUPIED;
@Shadow protected abstract boolean kickVillagerOutOfBed(Level p_49491_, BlockPos p_49492_);
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public InteractionResult use(BlockState p_49515_, Level level, BlockPos p_49517_, Player p_49518_, InteractionHand p_49519_, BlockHitResult p_49520_) {
if (level.isClientSide) {
return InteractionResult.CONSUME;
} else {
if (p_49515_.getValue(PART) != BedPart.HEAD) {
p_49517_ = p_49517_.relative(p_49515_.getValue(FACING));
p_49515_ = level.getBlockState(p_49517_);
if (!p_49515_.is((BedBlock) (Object) this)) {
return InteractionResult.CONSUME;
}
}
/* if (!canSetSpawn(level)) {
level.removeBlock(p_49517_, false);
BlockPos blockpos = p_49517_.relative(p_49515_.getValue(FACING).getOpposite());
if (level.getBlockState(blockpos).is((BedBlock) (Object) this)) {
level.removeBlock(blockpos, false);
}
level.explode((Entity) null, DamageSource.badRespawnPointExplosion(), (ExplosionDamageCalculator) null, (double) p_49517_.getX() + 0.5D, (double) p_49517_.getY() + 0.5D, (double) p_49517_.getZ() + 0.5D, 5.0F, true, Explosion.BlockInteraction.DESTROY);
return InteractionResult.SUCCESS;
} else */
if (p_49515_.getValue(OCCUPIED)) {
if (!this.kickVillagerOutOfBed(level, p_49517_)) {
p_49518_.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true);
}
return InteractionResult.SUCCESS;
} else {
var pos = p_49517_;
var state = p_49515_;
p_49518_.startSleepInBed(pos).ifLeft((p_49477_) -> {
if (!level.dimensionType().bedWorks()) {
level.removeBlock(pos, false);
BlockPos blockpos = pos.relative(state.getValue(FACING).getOpposite());
if (level.getBlockState(blockpos).is((BedBlock) (Object) this)) {
level.removeBlock(blockpos, false);
}
level.explode(null, DamageSource.badRespawnPointExplosion(), null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0F, true, Explosion.BlockInteraction.DESTROY);
} else if (p_49477_.getMessage() != null) {
p_49518_.displayClientMessage(p_49477_.getMessage(), true);
}
});
return InteractionResult.SUCCESS;
}
}
}
}

View File

@ -0,0 +1,57 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.mod.util.DistValidate;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BigDripleafBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Tilt;
import net.minecraft.world.phys.BlockHitResult;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityInteractEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(BigDripleafBlock.class)
public class BigDripleafBlockMixin {
@Shadow @Final private static EnumProperty<Tilt> TILT;
@Inject(method = "onProjectileHit", cancellable = true, at = @At("HEAD"))
private void arclight$projectileHit(Level level, BlockState state, BlockHitResult hitResult, Projectile projectile, CallbackInfo ci) {
if (DistValidate.isValid(level) && CraftEventFactory.callEntityChangeBlockEvent(projectile, hitResult.getBlockPos(), state.setValue(TILT, Tilt.FULL)).isCancelled()) {
ci.cancel();
}
}
@Inject(method = "entityInside", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/BigDripleafBlock;setTiltAndScheduleTick(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/properties/Tilt;Lnet/minecraft/sounds/SoundEvent;)V"))
private void arclight$entityInteract(BlockState state, Level level, BlockPos pos, Entity entity, CallbackInfo ci) {
if (!DistValidate.isValid(level)) return;
org.bukkit.event.Cancellable cancellable;
if (entity instanceof Player) {
cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
} else {
cancellable = new EntityInteractEvent(((EntityBridge) entity).bridge$getBukkitEntity(), CraftBlock.at(level, pos));
Bukkit.getPluginManager().callEvent((EntityInteractEvent) cancellable);
}
if (cancellable.isCancelled()) {
ci.cancel();
return;
}
if (CraftEventFactory.callEntityChangeBlockEvent(entity, pos, state.setValue(TILT, Tilt.FULL)).isCancelled()) {
ci.cancel();
}
}
}

View File

@ -1,12 +1,14 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import io.izzel.arclight.common.bridge.core.block.BlockBridge;
import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.mixin.core.world.level.block.state.BlockBehaviourMixin;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.izzel.arclight.common.mod.util.DistValidate;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.valueproviders.IntProvider;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
@ -23,6 +25,7 @@ import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityExhaustionEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@ -63,15 +66,30 @@ public abstract class BlockMixin extends BlockBehaviourMixin implements BlockBri
}
}
public int getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack) {
int silkTouch = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemStack);
int fortune = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, itemStack);
return ((IForgeBlock) this).getExpDrop(blockState, world, blockPos, fortune, silkTouch);
public int getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack, boolean flag) {
int silkTouch = itemStack.getEnchantmentLevel(Enchantments.SILK_TOUCH);
int fortune = itemStack.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE);
return ((IForgeBlock) this).getExpDrop(blockState, world, world.random, blockPos, fortune, silkTouch);
}
protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) {
int i = intprovider.sample(worldserver.random);
if (i > 0) {
return i;
}
}
return 0;
}
@Override
public int bridge$getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack) {
return getExpDrop(blockState, world, blockPos, itemStack);
return getExpDrop(blockState, world, blockPos, itemStack, true);
}
@Inject(method = "playerDestroy", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V"))
private void arclight$reason(Level p_49827_, Player player, BlockPos p_49829_, BlockState p_49830_, BlockEntity p_49831_, ItemStack p_49832_, CallbackInfo ci) {
((PlayerEntityBridge) player).bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED);
}
@Inject(method = "playerDestroy", at = @At("RETURN"))

View File

@ -0,0 +1,19 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.BuddingAmethystBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BuddingAmethystBlock.class)
public class BuddingAmethystBlockMixin {
@Redirect(method = "randomTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z"))
private boolean arclight$blockSpread(ServerLevel instance, BlockPos pos, BlockState state, BlockState p_220898_, ServerLevel p_220899_, BlockPos oldPos) {
return CraftEventFactory.handleBlockSpreadEvent(instance, oldPos, pos, state);
}
}

View File

@ -1,6 +1,17 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.ButtonBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v.block.CraftBlock;
@ -16,17 +27,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.ButtonBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
@Mixin(ButtonBlock.class)
public class ButtonBlockMixin {
@ -96,7 +96,7 @@ public class ButtonBlockMixin {
}
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
private void arclight$blockRedstone2(BlockState state, ServerLevel worldIn, BlockPos pos, Random rand, CallbackInfo ci) {
private void arclight$blockRedstone2(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource rand, CallbackInfo ci) {
Block block = CraftBlock.at(worldIn, pos);
BlockRedstoneEvent event = new BlockRedstoneEvent(block, 15, 0);

View File

@ -0,0 +1,71 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.ChangeOverTimeBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Optional;
@Mixin(ChangeOverTimeBlock.class)
public interface ChangeOverTimeBlockMixin<T extends Enum<T>> {
// @formatter:off
@Shadow T getAge();
@Shadow float getChanceModifier();
@Shadow Optional<BlockState> getNext(BlockState p_153040_);
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
default void applyChangeOverTime(BlockState p_220953_, ServerLevel level, BlockPos pos, RandomSource p_220956_) {
int i = this.getAge().ordinal();
int j = 0;
int k = 0;
for (BlockPos blockpos : BlockPos.withinManhattan(pos, 4, 4, 4)) {
int l = blockpos.distManhattan(pos);
if (l > 4) {
break;
}
if (!blockpos.equals(pos)) {
BlockState blockstate = level.getBlockState(blockpos);
Block block = blockstate.getBlock();
if (block instanceof ChangeOverTimeBlock) {
Enum<?> oenum = ((ChangeOverTimeBlock) block).getAge();
if (this.getAge().getClass() == oenum.getClass()) {
int i1 = oenum.ordinal();
if (i1 < i) {
return;
}
if (i1 > i) {
++k;
} else {
++j;
}
}
}
}
}
float f = (float) (k + 1) / (float) (k + j + 1);
float f1 = f * f * this.getChanceModifier();
if (p_220956_.nextFloat() < f1) {
this.getNext(p_220953_).ifPresent((newState) -> {
// level.setBlockAndUpdate(pos, newState);
CraftEventFactory.handleBlockFormEvent(level, pos, newState);
});
}
}
}

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
@ -23,7 +24,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import java.util.Random;
@Mixin(ChorusFlowerBlock.class)
public abstract class ChorusFlowerBlockMixin extends BlockMixin {
@ -41,7 +41,7 @@ public abstract class ChorusFlowerBlockMixin extends BlockMixin {
* @reason
*/
@Overwrite
public void randomTick(BlockState state, ServerLevel worldIn, BlockPos pos, Random random) {
public void randomTick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) {
BlockPos blockpos = pos.above();
if (worldIn.isEmptyBlock(blockpos) && blockpos.getY() < 256) {
int i = state.getValue(AGE);

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.CoralBlock;
import net.minecraft.world.level.block.state.BlockState;
@ -13,8 +14,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(CoralBlock.class)
public class CoralBlockMixin {
@ -23,7 +22,7 @@ public class CoralBlockMixin {
// @formatter:on
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, Random random, CallbackInfo ci) {
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci) {
if (CraftEventFactory.callBlockFadeEvent(worldIn, pos, this.deadBlock.defaultBlockState()).isCancelled()) {
ci.cancel();
}

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.BaseCoralPlantTypeBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.CoralFanBlock;
@ -14,8 +15,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(CoralFanBlock.class)
public class CoralFanBlockMixin {
@ -24,7 +23,7 @@ public class CoralFanBlockMixin {
// @formatter:on
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, Random random, CallbackInfo ci) {
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci) {
if (CraftEventFactory.callBlockFadeEvent(worldIn, pos, this.deadBlock.defaultBlockState().setValue(BaseCoralPlantTypeBlock.WATERLOGGED, false)).isCancelled()) {
ci.cancel();
}

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.BaseCoralPlantTypeBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.CoralPlantBlock;
@ -14,8 +15,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(CoralPlantBlock.class)
public class CoralPlantBlockMixin {
@ -24,7 +23,7 @@ public class CoralPlantBlockMixin {
// @formatter:on
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, Random random, CallbackInfo ci) {
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci) {
if (CraftEventFactory.callBlockFadeEvent(worldIn, pos, this.deadBlock.defaultBlockState().setValue(BaseCoralPlantTypeBlock.WATERLOGGED, false)).isCancelled()) {
ci.cancel();
}

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.BaseCoralPlantTypeBlock;
import net.minecraft.world.level.block.BaseCoralWallFanBlock;
import net.minecraft.world.level.block.Block;
@ -15,8 +16,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(CoralWallFanBlock.class)
public class CoralWallFanBlockMixin {
@ -25,7 +24,7 @@ public class CoralWallFanBlockMixin {
// @formatter:on
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, Random random, CallbackInfo ci) {
public void arclight$blockFade(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci) {
if (CraftEventFactory.callBlockFadeEvent(worldIn, pos, this.deadBlock.defaultBlockState()
.setValue(BaseCoralPlantTypeBlock.WATERLOGGED, Boolean.FALSE)
.setValue(BaseCoralWallFanBlock.FACING, state.getValue(BaseCoralWallFanBlock.FACING))).isCancelled()) {

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.DiodeBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
@ -10,20 +11,18 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(DiodeBlock.class)
public class DiodeBlockMixin {
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public void arclight$turnOff(BlockState state, ServerLevel worldIn, BlockPos pos, Random random, CallbackInfo ci) {
public void arclight$turnOff(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci) {
if (CraftEventFactory.callRedstoneChange(worldIn, pos, 15, 0).getNewCurrent() != 0) {
ci.cancel();
}
}
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public void arclight$turnOn(BlockState state, ServerLevel worldIn, BlockPos pos, Random random, CallbackInfo ci) {
public void arclight$turnOn(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci) {
if (CraftEventFactory.callRedstoneChange(worldIn, pos, 0, 15).getNewCurrent() != 15) {
ci.cancel();
}

View File

@ -0,0 +1,22 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.DirtPathBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(DirtPathBlock.class)
public class DirtPathBlockMixin {
@Inject(method = "tick", cancellable = true, at = @At("HEAD"))
private void arclight$checkValid(BlockState state, ServerLevel level, BlockPos pos, RandomSource p_221073_, CallbackInfo ci) {
if (!state.canSurvive(level, pos)) {
ci.cancel();
}
}
}

View File

@ -36,7 +36,7 @@ public class DropperBlockMixin {
public void dispenseFrom(ServerLevel worldIn, BlockPos pos) {
BlockSourceImpl proxyblocksource = new BlockSourceImpl(worldIn, pos);
DispenserBlockEntity dispensertileentity = proxyblocksource.getEntity();
int i = dispensertileentity.getRandomSlot();
int i = dispensertileentity.getRandomSlot(worldIn.getRandom());
if (i < 0) {
worldIn.levelEvent(1001, pos, 0);
} else {

View File

@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
@ -27,8 +28,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(FireBlock.class)
public abstract class FireBlockMixin extends BaseFireBlockMixin implements FireBlockBridge {
@ -57,7 +56,7 @@ public abstract class FireBlockMixin extends BaseFireBlockMixin implements FireB
}
@Inject(method = "tryCatchFire", cancellable = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;"))
public void arclight$blockBurn(Level worldIn, BlockPos pos, int chance, Random random, int age, Direction face, CallbackInfo ci) {
public void arclight$blockBurn(Level worldIn, BlockPos pos, int chance, RandomSource random, int age, Direction face, CallbackInfo ci) {
Block theBlock = CraftBlock.at(worldIn, pos);
Block sourceBlock = CraftBlock.at(worldIn, pos.relative(face));
BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock);

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.FungusBlock;
import net.minecraft.world.level.block.state.BlockState;
@ -12,14 +13,12 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(FungusBlock.class)
public class FungusBlockMixin {
@SuppressWarnings("ConstantConditions")
@Inject(method = "performBonemeal", at = @At("HEAD"))
private void arclight$captureTree(ServerLevel worldIn, Random rand, BlockPos pos, BlockState state, CallbackInfo ci) {
private void arclight$captureTree(ServerLevel worldIn, RandomSource rand, BlockPos pos, BlockState state, CallbackInfo ci) {
if ((Object) this == Blocks.WARPED_FUNGUS) {
ArclightCaptures.captureTreeType(TreeType.WARPED_FUNGUS);
} else if ((Object) this == Blocks.CRIMSON_FUNGUS) {

Some files were not shown because too many files have changed in this diff Show More