Update to 1.19.3

This commit is contained in:
IzzelAliz 2022-12-10 15:47:33 +08:00
parent 0550c6cd96
commit 7590e2b5d7
No known key found for this signature in database
GPG Key ID: EE50E123A11D8338
107 changed files with 904 additions and 894 deletions

View File

@ -4,11 +4,12 @@ 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)
| Release | Forge | Status | Build |
|:-------------:|:-------:|:------:|:------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Horn (1.19.x) | 43.2.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.80 | LTS | [![1.18 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-18?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-18) |
| 1.16.x | 36.2.39 | LTS | [![1.16 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-16?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-16) |
| Release | Forge | Status | Build |
|:-------------------:|:-------:|:------:|:------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Great Horn (1.19.3) | 44.0.1 | ACTIVE | [![1.19 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-19?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-19) |
| Horn (1.19-1.19.2) | 43.2.0 | LTS | [![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.80 | LTS | [![1.18 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-18?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-18) |
| 1.16.x | 36.2.39 | LTS | [![1.16 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-16?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-16) |
**Legacy versions**:

View File

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

View File

@ -1,17 +1,12 @@
package io.izzel.arclight.common.bridge.core.entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.player.Player;
import org.bukkit.event.entity.CreatureSpawnEvent;
public interface EntityTypeBridge<T extends Entity> {
T bridge$spawnCreature(ServerLevel worldIn, @Nullable CompoundTag compound, @Nullable Component customName, @Nullable Player playerIn, BlockPos pos, MobSpawnType reason, boolean flag, boolean flag1, CreatureSpawnEvent.SpawnReason spawnReason);
T bridge$spawnCreature(ServerLevel worldIn, BlockPos pos, MobSpawnType mobSpawnType, CreatureSpawnEvent.SpawnReason spawnReason);
}

View File

@ -1,8 +1,11 @@
package io.izzel.arclight.common.bridge.core.network.datasync;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.server.level.ServerPlayer;
public interface EntityDataManagerBridge {
public interface SynchedEntityDataBridge {
<T> void bridge$markDirty(EntityDataAccessor<T> key);
void bridge$refresh(ServerPlayer player);
}

View File

@ -4,7 +4,6 @@ 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;
@ -18,7 +17,7 @@ public interface PlayerListBridge {
CraftServer bridge$getCraftServer();
ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler, ProfilePublicKey profilePublicKey);
ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler);
void bridge$sendMessage(Component[] components);
}

View File

@ -1,17 +0,0 @@
package io.izzel.arclight.common.mixin.bukkit;
import net.minecraft.world.item.CreativeModeTab;
import org.bukkit.craftbukkit.v.inventory.CraftCreativeCategory;
import org.bukkit.inventory.CreativeCategory;
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 java.util.Map;
@Mixin(CraftCreativeCategory.class)
public class CraftCreativeCategoryMixin {
@Shadow @Final @Mutable private static Map<CreativeModeTab, CreativeCategory> NMS_TO_BUKKIT;
}

View File

@ -41,7 +41,7 @@ public interface CraftRecipeMixin {
throw new IllegalArgumentException("Unknown recipe stack instance " + bukkit);
}
stack.dissolve();
stack.getItems();
if (stack.isVanilla() && requireNotEmpty && stack.getItems().length == 0) {
throw new IllegalArgumentException("Recipe requires at least one non-air choice!");
} else {
@ -55,7 +55,7 @@ public interface CraftRecipeMixin {
*/
@Overwrite
static RecipeChoice toBukkit(Ingredient list) {
list.dissolve();
list.getItems();
if (!list.isVanilla()) {
return new ArclightSpecialIngredient(list);
}

View File

@ -50,19 +50,19 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@Mixin(CraftServer.class)
@Mixin(value = CraftServer.class, remap = false)
public abstract class CraftServerMixin implements CraftServerBridge {
// @formatter:off
@Shadow(remap = false) @Final private CraftCommandMap commandMap;
@Shadow(remap = false) @Final private SimplePluginManager pluginManager;
@Shadow(remap = false) @Final private SimpleHelpMap helpMap;
@Shadow(remap = false) protected abstract void enablePlugin(Plugin plugin);
@Shadow(remap = false) protected abstract void loadCustomPermissions();
@Shadow(remap = false) @Final protected DedicatedServer console;
@Shadow(remap = false) @Final @Mutable private String serverName;
@Shadow(remap = false) @Final @Mutable protected DedicatedPlayerList playerList;
@Shadow(remap = false) @Final private Map<String, World> worlds;
@Shadow @Final private CraftCommandMap commandMap;
@Shadow @Final private SimplePluginManager pluginManager;
@Shadow @Final private SimpleHelpMap helpMap;
@Shadow protected abstract void enablePlugin(Plugin plugin);
@Shadow protected abstract void loadCustomPermissions();
@Shadow @Final protected DedicatedServer console;
@Shadow @Final @Mutable private String serverName;
@Shadow @Final @Mutable protected DedicatedPlayerList playerList;
@Shadow @Final private Map<String, World> worlds;
@Shadow public int reloadCount;
@Shadow private YamlConfiguration configuration;
@Shadow protected abstract File getConfigFile();
@ -77,7 +77,7 @@ public abstract class CraftServerMixin implements CraftServerBridge {
@Shadow public abstract void loadPlugins();
@Shadow public abstract void enablePlugins(PluginLoadOrder type);
@Shadow public abstract PluginManager getPluginManager();
@Accessor(value = "logger", remap = false) @Mutable public abstract void setLogger(Logger logger);
@Accessor("logger") @Mutable public abstract void setLogger(Logger logger);
// @formatter:on
@Inject(method = "<init>", at = @At("RETURN"))

View File

@ -16,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
import java.util.function.Predicate;
@Mixin(Registry.SimpleRegistry.class)
@Mixin(value = Registry.SimpleRegistry.class, remap = false)
public class Registry_SimpleRegistryMixin<T extends Enum<T> & Keyed> implements SimpleRegistryBridge {
@Shadow @Final @Mutable private Map<NamespacedKey, T> map;

View File

@ -5,7 +5,6 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
@ -33,7 +32,7 @@ public abstract class FlowingFluidMixin {
// @formatter:on
@Inject(method = "spread", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/material/FlowingFluid;spreadTo(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/Direction;Lnet/minecraft/world/level/material/FluidState;)V"))
public void arclight$flowInto(LevelAccessor worldIn, BlockPos pos, FluidState stateIn, CallbackInfo ci) {
public void arclight$flowInto(Level worldIn, BlockPos pos, FluidState stateIn, CallbackInfo ci) {
if (!DistValidate.isValid(worldIn)) return;
Block source = CraftBlock.at(worldIn, pos);
BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN);

View File

@ -21,8 +21,6 @@ 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.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;
@ -55,7 +53,6 @@ public abstract class ServerLoginNetHandlerMixin {
// @formatter:off
@Shadow private ServerLoginPacketListenerImpl.State state;
@Shadow @Final private MinecraftServer server;
@Shadow @Final private byte[] nonce;
@Shadow @Final public Connection connection;
@Shadow @Final private static AtomicInteger UNIQUE_THREAD_ID;
@Shadow private GameProfile gameProfile;
@ -64,8 +61,7 @@ public abstract class ServerLoginNetHandlerMixin {
@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 ProfilePublicKey.ValidationException { return null; }
@Shadow @Final private byte[] challenge;
// @formatter:on
public void disconnect(final String s) {
@ -83,26 +79,13 @@ public abstract class ServerLoginNetHandlerMixin {
this.loginGameProfile = this.getOfflineProfile(this.loginGameProfile);
}
*/
ProfilePublicKey profilePublicKey = null;
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 (ProfilePublicKey.ValidationException e) {
LOGGER.error("Failed to validate profile key: {}", e.getMessage());
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);
ServerPlayer entity = ((PlayerListBridge) this.server.getPlayerList()).bridge$canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile, (ServerLoginPacketListenerImpl) (Object) this);
if (entity == null) {
// this.disconnect(itextcomponent);
} else {
@ -141,7 +124,6 @@ public abstract class ServerLoginNetHandlerMixin {
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
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;
@ -150,7 +132,7 @@ public abstract class ServerLoginNetHandlerMixin {
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));
this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge));
} else {
class Handler extends Thread {
@ -202,12 +184,7 @@ public abstract class ServerLoginNetHandlerMixin {
final String s;
try {
PrivateKey privatekey = this.server.getKeyPair().getPrivate();
if (this.profilePublicKeyData != null) {
ProfilePublicKey profilepublickey = new ProfilePublicKey(this.profilePublicKeyData);
if (!packetIn.isChallengeSignatureValid(this.nonce, profilepublickey)) {
throw new IllegalStateException("Protocol error");
}
} else if (!packetIn.isNonceValid(this.nonce, privatekey)) {
if (!packetIn.isChallengeValid(this.challenge, privatekey)) {
throw new IllegalStateException("Protocol error");
}

View File

@ -5,6 +5,7 @@ import com.mojang.datafixers.util.Pair;
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;
import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge;
import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge;
import io.izzel.arclight.common.bridge.core.network.play.TimestampedPacket;
import io.izzel.arclight.common.bridge.core.server.MinecraftServerBridge;
@ -25,14 +26,13 @@ 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.FilterMask;
import net.minecraft.network.chat.LastSeenMessages;
import net.minecraft.network.chat.OutgoingPlayerChatMessage;
import net.minecraft.network.chat.OutgoingChatMessage;
import net.minecraft.network.chat.PlayerChatMessage;
import net.minecraft.network.chat.PreviewableCommand;
import net.minecraft.network.chat.SignableCommand;
import net.minecraft.network.chat.SignedMessageChain;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketUtils;
import net.minecraft.network.protocol.game.*;
@ -104,7 +104,6 @@ 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;
@ -146,6 +145,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@ -198,13 +198,13 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
@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_);
@Shadow protected abstract void detectRateSpam();
@Shadow protected abstract Optional<LastSeenMessages> tryHandleChat(String p_251364_, Instant p_248959_, LastSeenMessages.Update p_249613_);
@Shadow protected abstract PlayerChatMessage getSignedMessage(ServerboundChatPacket p_251061_, LastSeenMessages p_250566_) throws SignedMessageChain.DecodeException;
@Shadow protected abstract void handleMessageDecodeFailure(SignedMessageChain.DecodeException p_252068_);
@Shadow protected abstract Map<String, PlayerChatMessage> collectSignedArguments(ServerboundChatCommandPacket p_249441_, SignableCommand<?> p_250039_, LastSeenMessages p_249207_) throws SignedMessageChain.DecodeException;
// @formatter:on
private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6;
@ -638,6 +638,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
this.player.absMoveTo(d0, d1, d2, f, f1);
if (!this.player.noPhysics && !this.player.isSleeping() && (flag1 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew((LevelReader) worldserver, axisalignedbb))) {
this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet(), false); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet.
this.player.doCheckFallDamage(this.player.getY() - d6, packetplayinflying.isOnGround());
} else {
this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch);
CraftPlayer player = this.getCraftPlayer();
@ -790,10 +791,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
@Inject(method = "handleUseItemOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItemOn(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;"))
private void arclight$checkDistance(ServerboundUseItemOnPacket packetIn, CallbackInfo ci) {
this.player.stopUsingItem();
}
// So, what is SPIGOT-4706 exactly?
// @Inject(method = "handleUseItemOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItemOn(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;"))
// private void arclight$checkDistance(ServerboundUseItemOnPacket packetIn, CallbackInfo ci) {
// this.player.stopUsingItem();
// }
private int limitedPackets;
private long lastLimitedPacket = -1;
@ -830,7 +832,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
InteractionHand enumhand = packet.getHand();
ItemStack itemstack = this.player.getItemInHand(enumhand);
this.player.resetLastActionTime();
if (!itemstack.isEmpty()) {
if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) {
float f1 = this.player.getXRot();
float f2 = this.player.getYRot();
double d0 = this.player.getX();
@ -957,51 +959,37 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
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);
var optional = this.tryHandleChat(packet.message(), packet.timeStamp(), packet.lastSeenMessages());
if (optional.isPresent()) {
PlayerChatMessage playerchatmessage;
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
});
try {
playerchatmessage = this.getSignedMessage(packet, optional.get());
} catch (SignedMessageChain.DecodeException e) {
this.handleMessageDecodeFailure(e);
return;
}
CompletableFuture<FilteredText> completablefuture = this.filterTextPacket(playerchatmessage.signedContent());
CompletableFuture<Component> completablefuture1 = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent());
this.chatMessageChain.append((executor) -> {
return CompletableFuture.allOf(completablefuture, completablefuture1).thenAcceptAsync((ovoid) -> {
PlayerChatMessage playerchatmessage1 = playerchatmessage.withUnsignedContent(completablefuture1.join()).filter(completablefuture.join().mask());
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 -> {
if (player == null) {
return 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) {
private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastseenmessages) {
String command = "/" + packet.command();
LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command);
@ -1014,18 +1002,19 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
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;
}
Map<String, PlayerChatMessage> map;
try {
map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastseenmessages) : Collections.emptyMap(); // CraftBukkit
} catch (SignedMessageChain.DecodeException e) {
this.handleMessageDecodeFailure(e);
return;
}
CommandSigningContext commandsigningcontext = new CommandSigningContext.SignedArguments(map);
parseresults = Commands.mapSource(parseresults, (p_242749_) -> {
return p_242749_.withSigningContext(commandsigningcontext);
});
CommandSigningContext.SignedArguments arguments = new CommandSigningContext.SignedArguments(map);
parseresults = Commands.mapSource(parseresults, (stack) -> stack.withSigningContext(arguments));
this.server.getCommands().performCommand(parseresults, command);
}
@ -1043,7 +1032,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
return;
}
ServerGamePacketListenerImpl handler = (ServerGamePacketListenerImpl) (Object) this;
OutgoingPlayerChatMessage outgoing = OutgoingPlayerChatMessage.create(original);
var outgoing = OutgoingChatMessage.create(original);
if (!async && s.startsWith("/")) {
this.handleCommand(s);
} else if (this.player.getChatVisibility() != ChatVisiblity.SYSTEM) {
@ -1054,15 +1043,12 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) {
PlayerChatEvent queueEvent = new PlayerChatEvent(thisPlayer, event.getMessage(), event.getFormat(), event.getRecipients());
queueEvent.setCancelled(event.isCancelled());
class SyncChat extends Waitable {
class SyncChat extends Waitable<Object> {
@Override
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());
@ -1070,7 +1056,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
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
} else if (!org.spigotmc.SpigotConfig.bungee && CraftChatMessage.fromComponent(original.decoratedContent()).equals(message)) { // Spigot
// TODO server.getPlayerList().broadcastChatMessage(original, player, ChatType.bind(ChatType.RAW, player));
return null;
}
@ -1083,9 +1069,6 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
Bukkit.getConsoleSender().sendMessage(message);
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
return null;
}
}
@ -1106,9 +1089,6 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
if (event.isCancelled()) {
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
return;
}
@ -1117,7 +1097,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
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
} else if (!org.spigotmc.SpigotConfig.bungee && CraftChatMessage.fromComponent(original.decoratedContent()).equals(s)) { // Spigot
// TODO server.getPlayerList().broadcastChatMessage(original, player, ChatType.bind(ChatType.RAW, player));
return;
}
@ -1131,10 +1111,6 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
}
}
Bukkit.getConsoleSender().sendMessage(s);
if (outgoing != null) {
outgoing.sendHeadersToRemainingPlayers(server.getPlayerList());
}
}
}
@ -1162,12 +1138,10 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
*/
@Overwrite
private void broadcastChatMessage(PlayerChatMessage playerchatmessage) {
String s = playerchatmessage.signedContent().plain();
String s = playerchatmessage.signedContent();
if (s.isEmpty()) {
LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message");
} else if (getCraftPlayer().isConversing()) {
OutgoingPlayerChatMessage outgoing = OutgoingPlayerChatMessage.create(playerchatmessage);
outgoing.sendHeadersToRemainingPlayers(this.server.getPlayerList());
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
@ -1264,7 +1238,10 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction interaction, PlayerInteractEntityEvent event) { // CraftBukkit
if (!player.canInteractWith(entity, 1.5D))
return; //Forge: If the entity cannot be reached, do nothing. Original check was dist < 6, range is 4.5, so vanilla used padding=1.5
ItemStack itemstack = player.getItemInHand(hand).copy();
var stack = player.getItemInHand(hand);
if (!stack.isItemEnabled(world.enabledFeatures()))
return;
ItemStack itemstack = stack.copy();
// CraftBukkit start
ItemStack itemInHand = player.getItemInHand(hand);
boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob;
@ -1285,7 +1262,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) {
// Refresh the current entity metadata
send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true));
((SynchedEntityDataBridge) entity.getEntityData()).bridge$refresh(player);
if (entity instanceof Allay) {
send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList())));
player.containerMenu.sendAllDataToRemote();
@ -1336,6 +1313,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
public void onAttack() {
if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && (entity != player || player.isSpectator())) {
ItemStack itemInHand = player.getMainHandItem();
if (!itemInHand.isItemEnabled(world.enabledFeatures())) return;
if (player.canHit(entity, 3)) { //Forge: Perform attack range check. Original check was dist < 6, range is 3, so vanilla used padding=3
player.attack(entity);
}

View File

@ -54,7 +54,6 @@ 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,9 +1,11 @@
package io.izzel.arclight.common.mixin.core.network;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.network.datasync.EntityDataManagerBridge;
import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import org.bukkit.craftbukkit.v.entity.CraftPlayer;
@ -14,13 +16,18 @@ 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.List;
@Mixin(SynchedEntityData.class)
public abstract class SynchedEntityDataMixin implements EntityDataManagerBridge {
public abstract class SynchedEntityDataMixin implements SynchedEntityDataBridge {
// @formatter:off
@Shadow protected abstract <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key);
@Shadow private boolean isDirty;
@Shadow @Final private Entity entity;
@Shadow @Nullable public abstract List<SynchedEntityData.DataValue<?>> getNonDefaultValues();
@Shadow public abstract boolean isEmpty();
// @formatter:on
@Inject(method = "set", at = @At("HEAD"))
@ -42,4 +49,18 @@ public abstract class SynchedEntityDataMixin implements EntityDataManagerBridge
public <T> void bridge$markDirty(EntityDataAccessor<T> key) {
this.markDirty(key);
}
public void refresh(ServerPlayer player) {
if (!this.isEmpty()) {
var list = this.getNonDefaultValues();
if (list != null) {
player.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
}
}
}
@Override
public void bridge$refresh(ServerPlayer player) {
refresh(player);
}
}

View File

@ -3,7 +3,7 @@ package io.izzel.arclight.common.mixin.core.network.protocol.game;
import com.mojang.brigadier.arguments.ArgumentType;
import io.netty.buffer.Unpooled;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.registries.ForgeRegistries;
import org.spigotmc.SpigotConfig;
@ -30,7 +30,7 @@ public class ClientboundCommandsPacket_ArgumentNodeStubMixin {
ci.cancel();
buf.writeVarInt(ARCLIGHT_WRAP_INDEX);
//noinspection deprecation
buf.writeVarInt(Registry.COMMAND_ARGUMENT_TYPE.getId(type));
buf.writeVarInt(BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getId(type));
var payload = new FriendlyByteBuf(Unpooled.buffer());
type.serializeToNetwork((T) node, payload);
buf.writeVarInt(payload.readableBytes());

View File

@ -1,8 +1,6 @@
package io.izzel.arclight.common.mixin.core.server;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.DynamicOps;
import io.izzel.arclight.api.ArclightVersion;
import io.izzel.arclight.common.bridge.core.command.ICommandSourceBridge;
import io.izzel.arclight.common.bridge.core.server.MinecraftServerBridge;
@ -22,30 +20,26 @@ import net.minecraft.Util;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.BlockPos;
import net.minecraft.core.LayeredRegistryAccess;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.status.ServerStatus;
import net.minecraft.obfuscate.DontObfuscate;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ReloadableServerResources;
import net.minecraft.server.RegistryLayer;
import net.minecraft.server.ServerFunctionManager;
import net.minecraft.server.Services;
import net.minecraft.server.TickTask;
import net.minecraft.server.WorldLoader;
import net.minecraft.server.WorldStem;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.PackType;
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.PlayerList;
import net.minecraft.util.Unit;
import net.minecraft.util.profiling.ProfilerFiller;
@ -56,7 +50,7 @@ import net.minecraft.world.level.DataPackConfig;
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.WorldOptions;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData;
@ -94,10 +88,7 @@ import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.Proxy;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BooleanSupplier;
@ -149,19 +140,20 @@ 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 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;
@Shadow private boolean debugCommandProfilerDelayStart;
@Shadow @Nullable private MinecraftServer.TimeProfiler debugCommandProfiler;
@Shadow public abstract LayeredRegistryAccess<RegistryLayer> registries();
// @formatter:on
public MinecraftServerMixin(String name) {
super(name);
}
public DataPackConfig datapackconfiguration;
public DynamicOps<Tag> registryreadops;
public WorldLoader.DataLoadContext worldLoader;
private boolean forceTicks;
public CraftServer server;
public OptionSet options;
@ -199,9 +191,8 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
} catch (Exception e) {
e.printStackTrace();
}
this.datapackconfiguration = ArclightCaptures.getDatapackConfig();
this.registryreadops = RegistryOps.create(NbtOps.INSTANCE, worldStem.registryAccess());
this.vanillaCommandDispatcher = worldStem.dataPackResources().getCommands();
this.worldLoader = ArclightCaptures.getDataLoadContext();
}
/**
@ -218,7 +209,6 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
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);
@ -248,6 +238,11 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
currentTick = (int) (System.currentTimeMillis() / 50);
if (this.debugCommandProfilerDelayStart) {
this.debugCommandProfilerDelayStart = false;
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
this.nextTickTime += 50L;
this.startMetricsRecordingTick();
this.profiler.push("tick");
@ -343,7 +338,7 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
@Inject(method = "createLevels", at = @At(value = "NEW", ordinal = 0, target = "net/minecraft/server/level/ServerLevel"))
private void arclight$registerEnv(ChunkProgressListener p_240787_1_, CallbackInfo ci) {
BukkitRegistry.registerEnvironments(this.worldData.worldGenSettings().dimensions());
BukkitRegistry.registerEnvironments(this.registryAccess().registryOrThrow(Registries.LEVEL_STEM));
}
@Redirect(method = "createLevels", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"))
@ -409,8 +404,8 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
}
// bukkit methods
public void initWorld(ServerLevel serverWorld, ServerLevelData worldInfo, WorldData saveData, WorldGenSettings generatorSettings) {
boolean flag = generatorSettings.isDebug();
public void initWorld(ServerLevel serverWorld, ServerLevelData worldInfo, WorldData saveData, WorldOptions worldOptions) {
boolean flag = saveData.isDebugWorld();
if (((WorldBridge) serverWorld).bridge$getGenerator() != null) {
((WorldBridge) serverWorld).bridge$getWorld().getPopulators().addAll(
((WorldBridge) serverWorld).bridge$getGenerator().getDefaultPopulators(
@ -420,7 +415,7 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
worldborder.applySettings(worldInfo.getWorldBorder());
if (!worldInfo.isInitialized()) {
try {
setInitialSpawn(serverWorld, worldInfo, generatorSettings.generateBonusChest(), flag);
setInitialSpawn(serverWorld, worldInfo, worldOptions.generateBonusChest(), flag);
worldInfo.setInitialized(true);
if (flag) {
this.setupDebugLevel(this.worldData);
@ -499,47 +494,13 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<T
}
@Inject(method = "saveAllChunks", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;overworld()Lnet/minecraft/server/level/ServerLevel;"))
private void arclight$skipSave(boolean suppressLog, boolean flush, boolean forced, CallbackInfoReturnable<Boolean> cir, boolean flag) {
cir.setReturnValue(flag);
private void arclight$skipSave(boolean suppressLog, boolean flush, boolean forced, CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(!this.levels.isEmpty());
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public CompletableFuture<Void> reloadResources(Collection<String> p_129862_) {
RegistryAccess.Frozen registryaccess$frozen = this.registryAccess();
CompletableFuture<Void> completablefuture = CompletableFuture.supplyAsync(() -> {
return p_129862_.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList());
}, 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();
}
}).thenApply((p_212904_) -> {
return new MinecraftServer.ReloadableResources(closeableresourcemanager, p_212904_);
});
}).thenAcceptAsync((p_212919_) -> {
this.resources.close();
this.resources = p_212919_;
this.server.syncCommands();
this.packRepository.setSelected(p_129862_);
this.worldData.setDataPackConfig(getSelectedPacks(this.packRepository));
this.resources.managers().updateRegistryTags(this.registryAccess());
this.getPlayerList().saveAll();
this.getPlayerList().reloadResources();
this.functionManager.replaceLibrary(this.resources.managers().getFunctionLibrary());
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()) {
this.managedBlock(completablefuture::isDone);
}
return completablefuture;
@Inject(method = "desc=/V$/", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/repository/PackRepository;setSelected(Ljava/util/Collection;)V"))
private void arclight$syncCommand(CallbackInfo ci) {
this.server.syncCommands();
}
/**

View File

@ -0,0 +1,17 @@
package io.izzel.arclight.common.mixin.core.server;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.server.WorldLoader;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(WorldLoader.class)
public class WorldLoaderMixin {
@ModifyArg(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader$WorldDataSupplier;get(Lnet/minecraft/server/WorldLoader$DataLoadContext;)Lnet/minecraft/server/WorldLoader$DataLoadOutput;"))
private static WorldLoader.DataLoadContext arclight$captureContext(WorldLoader.DataLoadContext context) {
ArclightCaptures.captureDataLoadContext(context);
return context;
}
}

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.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

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.server.commands;
import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.Holder;
import net.minecraft.server.commands.EffectCommands;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.Entity;
@ -18,7 +19,7 @@ import java.util.Collection;
public class EffectCommandMixin {
@Inject(method = "giveEffect", at = @At("HEAD"))
private static void arclight$addReason(CommandSourceStack source, Collection<? extends Entity> targets, MobEffect effect, Integer seconds, int amplifier, boolean showParticles, CallbackInfoReturnable<Integer> cir) {
private static void arclight$addReason(CommandSourceStack p_250553_, Collection<? extends Entity> targets, Holder<MobEffect> p_249495_, Integer p_249652_, int p_251498_, boolean p_249944_, CallbackInfoReturnable<Integer> cir) {
for (Entity entity : targets) {
if (entity instanceof LivingEntity) {
((LivingEntityBridge) entity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.COMMAND);
@ -36,7 +37,7 @@ public class EffectCommandMixin {
}
@Inject(method = "clearEffect", at = @At("HEAD"))
private static void arclight$removeReason(CommandSourceStack source, Collection<? extends Entity> targets, MobEffect effect, CallbackInfoReturnable<Integer> cir) {
private static void arclight$removeReason(CommandSourceStack p_250069_, Collection<? extends Entity> targets, Holder<MobEffect> p_249198_, CallbackInfoReturnable<Integer> cir) {
for (Entity entity : targets) {
if (entity instanceof LivingEntity) {
((LivingEntityBridge) entity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.COMMAND);

View File

@ -2,9 +2,10 @@ package io.izzel.arclight.common.mixin.core.server.commands;
import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.commands.SummonCommand;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.phys.Vec3;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
@ -16,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class SummonCommandMixin {
@Inject(method = "spawnEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;tryAddFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)Z"))
private static void arclight$summonReason(CommandSourceStack source, ResourceLocation type, Vec3 pos, CompoundTag nbt, boolean randomizeProperties, CallbackInfoReturnable<Integer> cir) {
private static void arclight$summonReason(CommandSourceStack source, Holder.Reference<EntityType<?>> p_251948_, Vec3 p_251429_, CompoundTag p_250568_, boolean p_250229_, CallbackInfoReturnable<Integer> cir) {
((ServerWorldBridge) source.getLevel()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.COMMAND);
}
}

View File

@ -4,7 +4,7 @@ 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.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
@ -45,7 +45,7 @@ public abstract class ChunkMapMixin implements ChunkMapBridge {
@Shadow protected abstract void tick();
@Shadow @Mutable public ChunkGenerator generator;
@Shadow @Final public ServerLevel level;
@Shadow private RandomState randomState;
@Shadow @Final @Mutable private RandomState randomState;
@Invoker("tick") public abstract void bridge$tick(BooleanSupplier hasMoreTime);
@Invoker("setViewDistance") public abstract void bridge$setViewDistance(int i);
// @formatter:on
@ -89,9 +89,9 @@ public abstract class ChunkMapMixin implements ChunkMapBridge {
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());
this.randomState = RandomState.create(noisebasedchunkgenerator.generatorSettings().value(), this.level.registryAccess().lookupOrThrow(Registries.NOISE), this.level.getSeed());
} else {
this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), this.level.registryAccess().registryOrThrow(Registry.NOISE_REGISTRY), this.level.getSeed());
this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), this.level.registryAccess().lookupOrThrow(Registries.NOISE), this.level.getSeed());
}
}
}

View File

@ -33,7 +33,7 @@ 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;
@Shadow(remap = false) @Final private Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets;
@Invoker("purgeStaleTickets") public abstract void bridge$tick();
// @formatter:on

View File

@ -49,6 +49,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@ -77,6 +78,7 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
@Shadow private Vec3 ap;
@Shadow private int yHeadRotp;
@Shadow protected abstract void broadcastAndSend(Packet<?> packet);
@Shadow @Nullable private List<SynchedEntityData.DataValue<?>> trackedDataValues;
// @formatter:on
private Set<ServerPlayerConnection> trackedPlayers;
@ -259,8 +261,8 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
Packet<?> packet = this.entity.getAddEntityPacket();
this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0f / 360.0f);
consumer.accept(packet);
if (!this.entity.getEntityData().isEmpty()) {
consumer.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.entity.getEntityData(), true));
if (this.trackedDataValues != null) {
consumer.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.trackedDataValues));
}
boolean flag = this.trackDelta;
if (this.entity instanceof LivingEntity livingEntity) {
@ -310,7 +312,7 @@ public abstract class ServerEntityMixin implements ServerEntityBridge {
}
@Inject(method = "sendDirtyEntityData", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/server/level/ServerEntity;broadcastAndSend(Lnet/minecraft/network/protocol/Packet;)V"))
private void arclight$sendScaledHealth(CallbackInfo ci, SynchedEntityData entitydatamanager, Set<AttributeInstance> set) {
private void arclight$sendScaledHealth(CallbackInfo ci, SynchedEntityData entitydatamanager, List<SynchedEntityData.DataValue<?>> list, Set<AttributeInstance> set) {
if (this.entity instanceof ServerPlayerEntityBridge player) {
player.bridge$getBukkitEntity().injectScaledMaxHealth(set, false);
}

View File

@ -21,8 +21,9 @@ 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.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket;
import net.minecraft.resources.ResourceKey;
@ -148,13 +149,13 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
if (typeKey != null) {
this.typeKey = typeKey;
} else {
var dimensions = shadow$getServer().getWorldData().worldGenSettings().dimensions();
var key = dimensions.getKey(levelStem);
if (key != null) {
this.typeKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, key);
var dimensions = shadow$getServer().registryAccess().registryOrThrow(Registries.LEVEL_STEM);
var key = dimensions.getResourceKey(levelStem);
if (key.isPresent()) {
this.typeKey = key.get();
} else {
ArclightMod.LOGGER.warn("Assign {} to unknown level stem {}", dimension.location(), levelStem);
this.typeKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, dimension.location());
this.typeKey = ResourceKey.create(Registries.LEVEL_STEM, dimension.location());
}
}
if (worldInfo instanceof PrimaryLevelData) {
@ -185,7 +186,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
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());
GenericGameEvent event = new GenericGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.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();
@ -269,7 +270,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
if (this.serverLevelData instanceof PrimaryLevelData worldInfo) {
worldInfo.setWorldBorder(this.getWorldBorder().createSettings());
worldInfo.setCustomBossEvents(this.shadow$getServer().getCustomBossEvents().save());
this.convertable.saveDataTag(this.shadow$getServer().registryHolder, worldInfo, this.shadow$getServer().getPlayerList().getSingleplayerData());
this.convertable.saveDataTag(this.shadow$getServer().registryAccess(), worldInfo, this.shadow$getServer().getPlayerList().getSingleplayerData());
}
}
@ -377,11 +378,10 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
return tryAddFreshEntityWithPassengers(entity, reason);
}
@Inject(method = "explode", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER,
target = "Lnet/minecraft/world/level/Explosion;finalizeExplosion(Z)V"), locals = LocalCapture.CAPTURE_FAILHARD)
public void arclight$doExplosion(Entity entityIn, DamageSource damageSourceIn, @Nullable ExplosionDamageCalculator context, double xIn, double yIn, double zIn,
float explosionRadius, boolean causesFire, Explosion.BlockInteraction modeIn, CallbackInfoReturnable<Explosion> cir,
Explosion explosion) {
@Inject(method = "explode", cancellable = true, at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/level/Explosion;interactsWithBlocks()Z"), locals = LocalCapture.CAPTURE_FAILHARD)
private void arclight$doExplosion(Entity p_256039_, DamageSource p_255778_, ExplosionDamageCalculator p_256002_, double p_256067_, double p_256370_, double p_256153_, float p_256045_, boolean p_255686_, Level.ExplosionInteraction p_255827_,
CallbackInfoReturnable<Explosion> cir, Explosion explosion) {
if (((ExplosionBridge) explosion).bridge$wasCancelled()) {
cir.setReturnValue(explosion);
}

View File

@ -14,7 +14,7 @@ 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.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.LayeredRegistryAccess;
import net.minecraft.core.UUIDUtil;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.Component;
@ -31,6 +31,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.RegistryLayer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@ -48,7 +49,6 @@ 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;
@ -130,7 +130,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
}
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$loadServer(MinecraftServer minecraftServer, RegistryAccess.Frozen p_i231425_2_, PlayerDataStorage p_i231425_3_, int p_i231425_4_, CallbackInfo ci) {
private void arclight$loadServer(MinecraftServer minecraftServer, LayeredRegistryAccess<RegistryLayer> p_251844_, PlayerDataStorage p_203844_, int p_203845_, CallbackInfo ci) {
cserver = ArclightServer.createOrLoad((DedicatedServer) minecraftServer, (PlayerList) (Object) this);
}
@ -209,7 +209,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
}
@Override
public ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler, ProfilePublicKey profilePublicKey) {
public ServerPlayer bridge$canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile, ServerLoginPacketListenerImpl handler) {
UUID uuid = UUIDUtil.getOrCreatePlayerUUID(gameProfile);
List<ServerPlayer> list = Lists.newArrayList();
for (ServerPlayer entityplayer : this.players) {
@ -221,7 +221,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
this.save(entityplayer);
entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login"));
}
ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, profilePublicKey);
ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile);
Player player = ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity();
String hostname = handler == null ? "" : ((NetworkManagerBridge) handler.connection).bridge$getHostname();
@ -332,7 +332,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.dimensionTypeId(), serverWorld.dimension(), BiomeManager.obfuscateSeed(serverWorld.getSeed()), playerIn.gameMode.getGameModeForPlayer(), playerIn.gameMode.getPreviousGameModeForPlayer(), serverWorld.isDebug(), serverWorld.isFlat(), flag, playerIn.getLastDeathLocation()));
playerIn.connection.send(new ClientboundRespawnPacket(serverWorld.dimensionTypeId(), serverWorld.dimension(), BiomeManager.obfuscateSeed(serverWorld.getSeed()), playerIn.gameMode.getGameModeForPlayer(), playerIn.gameMode.getPreviousGameModeForPlayer(), serverWorld.isDebug(), serverWorld.isFlat(), (byte) (flag ? 1 : 0), 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);
@ -446,7 +446,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
ServerLevel serverWorld = ((CraftWorld) location.getWorld()).getHandle();
ServerPlayer serverplayerentity = new ServerPlayer(this.server, serverWorld, playerIn.getGameProfile(), playerIn.getProfilePublicKey());
ServerPlayer serverplayerentity = new ServerPlayer(this.server, serverWorld, playerIn.getGameProfile());
// Forward to new player instance
((InternalEntityBridge) playerIn).internal$getBukkitEntity().setHandle(serverplayerentity);
@ -478,7 +478,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
}
LevelData iworldinfo = serverplayerentity.level.getLevelData();
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 ClientboundRespawnPacket(serverplayerentity.level.dimensionTypeId(), serverplayerentity.level.dimension(), BiomeManager.obfuscateSeed(serverplayerentity.getLevel().getSeed()), serverplayerentity.gameMode.getGameModeForPlayer(), serverplayerentity.gameMode.getPreviousGameModeForPlayer(), serverplayerentity.getLevel().isDebug(), serverplayerentity.getLevel().isFlat(), (byte) (conqueredEnd ? 1 : 0), 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);

View File

@ -212,12 +212,12 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
}
}
@Inject(method = "destroyBlock", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/common/ForgeHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I"))
@Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraftforge/common/ForgeHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I"))
public void arclight$beforePrimaryEventFired(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
ArclightCaptures.captureNextBlockBreakEventAsPrimaryEvent();
}
@Inject(method = "destroyBlock", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraftforge/common/ForgeHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I"))
@Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Lnet/minecraftforge/common/ForgeHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I"))
public void arclight$handleSecondaryBlockBreakEvents(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
ArclightCaptures.BlockBreakEventContext breakEventContext = ArclightCaptures.popSecondaryBlockBreakEvent();
while (breakEventContext != null) {
@ -284,7 +284,9 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana
BlockState blockstate = worldIn.getBlockState(blockpos);
InteractionResult resultType = InteractionResult.PASS;
boolean cancelledBlock = false;
if (this.gameModeForPlayer == GameType.SPECTATOR) {
if (!blockstate.getBlock().isEnabled(worldIn.enabledFeatures())) {
return InteractionResult.FAIL;
} else if (this.gameModeForPlayer == GameType.SPECTATOR) {
MenuProvider provider = blockstate.getMenuProvider(worldIn, blockpos);
cancelledBlock = !(provider instanceof MenuProvider);
}

View File

@ -79,10 +79,10 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@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();
@Shadow public abstract boolean interactsWithBlocks();
@Shadow @Nullable public abstract LivingEntity getIndirectSourceEntity();
// @formatter:on
@Inject(method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)V",
at = @At("RETURN"))
public void arclight$adjustSize(Level worldIn, Entity exploderIn, double xIn, double yIn, double zIn, float sizeIn, boolean causesFireIn, Explosion.BlockInteraction modeIn, CallbackInfo ci) {
@ -236,7 +236,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
this.level.playLocalSound(this.x, this.y, this.z, SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 4.0F, (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F, false);
}
boolean flag = this.blockInteraction != Explosion.BlockInteraction.NONE;
boolean flag = this.interactsWithBlocks();
if (spawnParticles) {
if (!(this.radius < 2.0F) && flag) {
this.level.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
@ -247,7 +247,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
if (flag) {
ObjectArrayList<Pair<ItemStack, BlockPos>> objectarraylist = new ObjectArrayList<>();
boolean flag2 = this.getSourceMob() instanceof Player;
boolean flag2 = this.getIndirectSourceEntity() instanceof Player;
Util.shuffle(this.toBlow, this.level.random);
float yield = this.callBlockExplodeEvent();
@ -266,7 +266,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
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).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) {
if (this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY || yield < 1.0F) {
lootcontext$builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / yield);
}

View File

@ -1,22 +1,15 @@
package io.izzel.arclight.common.mixin.core.world.damagesource;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import io.izzel.arclight.common.bridge.core.util.IndirectEntityDamageSourceBridge;
import net.minecraft.world.damagesource.IndirectEntityDamageSource;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(IndirectEntityDamageSource.class)
public class IndirectEntityDamageSourceMixin extends DamageSourceMixin implements IndirectEntityDamageSourceBridge {
// @formatter:off
@Shadow @Final private Entity owner;
// @formatter:on
public Entity getProximateDamageSource() {
Entity trueSource = super.getEntity();
return trueSource == null ? this.owner : trueSource;
return getEntity();
}
@Override

View File

@ -3,7 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.entity;
import com.google.common.collect.Lists;
import io.izzel.arclight.common.bridge.core.entity.AreaEffectCloudEntityBridge;
import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.network.syncher.EntityDataAccessor;
@ -208,11 +208,11 @@ public abstract class AreaEffectCloudEntityMixin extends EntityMixin implements
}
public String getPotionType() {
return Registry.POTION.getKey(this.potion).toString();
return BuiltInRegistries.POTION.getKey(this.potion).toString();
}
public void setPotionType(final String string) {
this.setPotion(Registry.POTION.get(new ResourceLocation(string)));
this.setPotion(BuiltInRegistries.POTION.get(new ResourceLocation(string)));
}
@Override

View File

@ -8,7 +8,7 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.network.datasync.EntityDataManagerBridge;
import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge;
import io.izzel.arclight.common.bridge.core.world.TeleporterBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
@ -789,7 +789,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
}
if (event.isCancelled() && this.getAirSupply() != -1) {
ci.cancel();
((EntityDataManagerBridge) this.getEntityData()).bridge$markDirty(DATA_AIR_SUPPLY_ID);
((SynchedEntityDataBridge) this.getEntityData()).bridge$markDirty(DATA_AIR_SUPPLY_ID);
return;
}
this.entityData.set(DATA_AIR_SUPPLY_ID, event.getAmount());
@ -967,7 +967,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
}
ArclightCaptures.captureCraftPortalEvent(event);
return PortalShape.createPortalInfo(worldFinal, result, direction$axis, vector3d, this.getDimensions(this.getPose()), this.getDeltaMovement(), this.getYRot(), this.getXRot());
return PortalShape.createPortalInfo(worldFinal, result, direction$axis, vector3d, (Entity) (Object) this, this.getDeltaMovement(), this.getYRot(), this.getXRot());
}).orElse(null);
}
} else {

View File

@ -4,12 +4,12 @@ import io.izzel.arclight.common.bridge.core.entity.EntityTypeBridge;
import io.izzel.arclight.common.bridge.core.world.IWorldWriterBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -20,46 +20,51 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import javax.annotation.Nullable;
import java.util.function.Consumer;
@Mixin(EntityType.class)
public abstract class EntityTypeMixin<T extends Entity> implements EntityTypeBridge<T> {
// @formatter:off
@Shadow @Nullable public abstract T create(ServerLevel worldIn, @Nullable CompoundTag compound, @Nullable Component customName, @Nullable Player playerIn, BlockPos pos, MobSpawnType reason, boolean p_220349_7_, boolean p_220349_8_);
@Shadow @Nullable public abstract T create(ServerLevel p_262637_, @org.jetbrains.annotations.Nullable CompoundTag p_262687_, @org.jetbrains.annotations.Nullable Consumer<T> p_262629_, BlockPos p_262595_, MobSpawnType p_262666_, boolean p_262685_, boolean p_262588_);
// @formatter:on
@Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/network/chat/Component;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private void arclight$spawnReason(ServerLevel worldIn, CompoundTag compound, Component customName, Player playerIn, BlockPos pos, MobSpawnType reason, boolean p_220342_7_, boolean p_220342_8_, CallbackInfoReturnable<T> cir) {
@Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;",
at = @At(value = "HEAD"))
private void arclight$spawnReason(ServerLevel worldIn, ItemStack p_20594_, Player p_20595_, BlockPos p_20596_, MobSpawnType p_20597_, boolean p_20598_, boolean p_20599_, CallbackInfoReturnable<T> cir) {
CreatureSpawnEvent.SpawnReason spawnReason = ((IWorldWriterBridge) worldIn).bridge$getAddEntityReason();
if (spawnReason == null) {
((IWorldWriterBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.SPAWNER_EGG);
}
}
@Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/network/chat/Component;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;",
@Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Ljava/util/function/Consumer;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;",
cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN"),
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")))
private void arclight$returnIfSuccess(ServerLevel worldIn, CompoundTag compound, Component customName, Player playerIn, BlockPos pos, MobSpawnType reason, boolean p_220342_7_, boolean p_220342_8_, CallbackInfoReturnable<T> cir, T t) {
private void arclight$returnIfSuccess(ServerLevel p_262704_, CompoundTag p_262603_, Consumer<T> p_262621_, BlockPos p_262672_, MobSpawnType p_262644_, boolean p_262690_, boolean p_262590_, CallbackInfoReturnable<T> cir, T t) {
if (t != null) {
cir.setReturnValue(t.isRemoved() ? null : t);
}
}
public T spawn(ServerLevel worldIn, @Nullable CompoundTag compound, @Nullable Component customName, @Nullable Player playerIn, BlockPos pos, MobSpawnType reason, boolean p_220342_7_, boolean p_220342_8_, CreatureSpawnEvent.SpawnReason spawnReason) {
T t = this.create(worldIn, compound, customName, playerIn, pos, reason, p_220342_7_, p_220342_8_);
public T spawn(ServerLevel p_262634_, BlockPos p_262707_, MobSpawnType p_262597_, CreatureSpawnEvent.SpawnReason spawnReason) {
return this.spawn(p_262634_, null, null, p_262707_, p_262597_, false, false, spawnReason);
}
public T spawn(ServerLevel p_262704_, @Nullable CompoundTag p_262603_, @Nullable Consumer<T> p_262621_, BlockPos p_262672_, MobSpawnType p_262644_, boolean p_262690_, boolean p_262590_, CreatureSpawnEvent.SpawnReason spawnReason) {
T t = this.create(p_262704_, p_262603_, p_262621_, p_262672_, p_262644_, p_262690_, p_262590_);
if (t != null) {
if (t instanceof net.minecraft.world.entity.Mob && net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn((net.minecraft.world.entity.Mob) t, worldIn, pos.getX(), pos.getY(), pos.getZ(), null, reason))
if (t instanceof net.minecraft.world.entity.Mob && net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn((net.minecraft.world.entity.Mob) t, p_262704_, p_262672_.getX(), p_262672_.getY(), p_262672_.getZ(), null, p_262644_))
return null;
((IWorldWriterBridge) worldIn).bridge$pushAddEntityReason(spawnReason);
worldIn.addFreshEntityWithPassengers(t);
((IWorldWriterBridge) p_262704_).bridge$pushAddEntityReason(spawnReason);
p_262704_.addFreshEntityWithPassengers(t);
return t.isRemoved() ? null : t;
}
return null;
}
@Override
public T bridge$spawnCreature(ServerLevel worldIn, @Nullable CompoundTag compound, @Nullable Component customName, @Nullable Player playerIn, BlockPos pos, MobSpawnType reason, boolean flag, boolean flag1, CreatureSpawnEvent.SpawnReason spawnReason) {
return spawn(worldIn, compound, customName, playerIn, pos, reason, flag, flag1, spawnReason);
public T bridge$spawnCreature(ServerLevel worldIn, BlockPos pos, MobSpawnType mobSpawnType, CreatureSpawnEvent.SpawnReason spawnReason) {
return spawn(worldIn, pos, mobSpawnType, spawnReason);
}
}

View File

@ -523,15 +523,9 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
this.noActionTime = 0;
float f = amount;
if (false && (source == DamageSource.ANVIL || source == DamageSource.FALLING_BLOCK) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
this.getItemBySlot(EquipmentSlot.HEAD).hurtAndBreak((int) (amount * 4.0F + this.random.nextFloat() * amount * 2.0F), (LivingEntity) (Object) this, (p_213341_0_) -> {
p_213341_0_.broadcastBreakEvent(EquipmentSlot.HEAD);
});
amount *= 0.75F;
}
boolean flag = f > 0.0F && this.isDamageSourceBlocked(source); // Copied from below
float f1 = 0.0F;
// ShieldBlockEvent implemented in damageEntity0
if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) {
this.hurtCurrentlyUsedShield(amount);
@ -623,7 +617,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
this.markHurt();
}
if (entity1 != null) {
if (entity1 != null && !source.isExplosion()) {
double d1 = entity1.getX() - this.getX();
double d0;
@ -638,7 +632,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
}
if (this.getHealth() <= 0.0F) {
if (this.isDeadOrDying()) {
if (!this.checkTotemDeathProtection(source)) {
SoundEvent soundevent = this.getDeathSound();
if (flag1 && soundevent != null) {
@ -687,7 +681,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
float originalDamage = f;
Function<Double, Double> hardHat = f12 -> {
if ((damagesource == DamageSource.ANVIL || damagesource == DamageSource.FALLING_BLOCK) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
if (damagesource.isDamageHelmet() && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
return -(f12 - (f12 * 0.75F));
}
return -0.0;
@ -953,7 +947,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
@Inject(method = "createWitherRose", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private void arclight$witherRoseDrop(LivingEntity livingEntity, CallbackInfo ci, boolean flag, ItemEntity itemEntity) {
private void arclight$witherRoseDrop(LivingEntity livingEntity, CallbackInfo ci, boolean flag, ItemEntity
itemEntity) {
org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) (((EntityBridge) itemEntity).bridge$getBukkitEntity()));
CraftEventFactory.callEvent(event);
if (event.isCancelled()) {
@ -1023,7 +1018,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
@Eject(method = "completeUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;finishUsingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/item/ItemStack;"))
private ItemStack arclight$itemConsume(ItemStack itemStack, Level worldIn, LivingEntity entityLiving, CallbackInfo ci) {
private ItemStack arclight$itemConsume(ItemStack itemStack, Level worldIn, LivingEntity
entityLiving, CallbackInfo ci) {
if (this instanceof ServerPlayerEntityBridge) {
final org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(itemStack);
final PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, CraftEquipmentSlot.getHand(this.getUsedItemHand()));
@ -1041,7 +1037,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
@Eject(method = "randomTeleport", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;teleportTo(DDD)V"))
private void arclight$entityTeleport(LivingEntity entity, double x, double y, double z, CallbackInfoReturnable<Boolean> cir) {
private void arclight$entityTeleport(LivingEntity entity, double x, double y, double z, CallbackInfoReturnable<
Boolean> cir) {
EntityTeleportEvent event = new EntityTeleportEvent(getBukkitEntity(), new Location(((WorldBridge) this.level).bridge$getWorld(), this.getX(), this.getY(), this.getZ()),
new Location(((WorldBridge) this.level).bridge$getWorld(), x, y, z));
Bukkit.getPluginManager().callEvent(event);
@ -1054,7 +1051,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
@Redirect(method = "dropAllDeathLoot", at = @At(value = "INVOKE", ordinal = 0, remap = false, target = "Lnet/minecraft/world/entity/LivingEntity;captureDrops(Ljava/util/Collection;)Ljava/util/Collection;"))
private Collection<ItemEntity> arclight$captureIfNeed(LivingEntity livingEntity, Collection<ItemEntity> value) {
private Collection<ItemEntity> arclight$captureIfNeed(LivingEntity
livingEntity, Collection<ItemEntity> value) {
Collection<ItemEntity> drops = livingEntity.captureDrops();
// todo this instanceof ArmorStandEntity
return drops == null ? livingEntity.captureDrops(value) : drops;
@ -1071,7 +1069,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
@Inject(method = "addEatEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z"))
public void arclight$foodEffectCause(ItemStack p_213349_1_, Level p_213349_2_, LivingEntity livingEntity, CallbackInfo ci) {
public void arclight$foodEffectCause(ItemStack p_213349_1_, Level p_213349_2_, LivingEntity
livingEntity, CallbackInfo ci) {
((LivingEntityBridge) livingEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.FOOD);
}
@ -1134,7 +1133,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
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 (!flag && !ItemStack.isSame(oldItem, newItem) && !this.firstTick) {
if (slot.getType() == EquipmentSlot.Type.ARMOR && !silent) {
this.playEquipSound(newItem);
}

View File

@ -44,8 +44,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import javax.annotation.Nullable;
import static net.minecraft.world.entity.LivingEntity.getEquipmentSlotForItem;
@Mixin(Mob.class)
public abstract class MobMixin extends LivingEntityMixin implements MobEntityBridge {
@ -69,6 +67,7 @@ public abstract class MobMixin extends LivingEntityMixin implements MobEntityBri
@Shadow protected abstract void setItemSlotAndDropWhenKilled(EquipmentSlot p_233657_1_, ItemStack p_233657_2_);
@Shadow @Nullable public abstract <T extends Mob> T convertTo(EntityType<T> p_233656_1_, boolean p_233656_2_);
@Shadow @Nullable protected abstract SoundEvent getAmbientSound();
@Shadow protected abstract EquipmentSlot getEquipmentSlotForItemStack(ItemStack p_256113_);
// @formatter:on
public boolean aware;
@ -221,10 +220,10 @@ public abstract class MobMixin extends LivingEntityMixin implements MobEntityBri
* @reason
*/
@Overwrite
public boolean equipItemIfPossible(ItemStack stack) {
public ItemStack equipItemIfPossible(ItemStack stack) {
ItemEntity itemEntity = arclight$item;
arclight$item = null;
EquipmentSlot equipmentslottype = getEquipmentSlotForItem(stack);
EquipmentSlot equipmentslottype = this.getEquipmentSlotForItemStack(stack);
ItemStack itemstack = this.getItemBySlot(equipmentslottype);
boolean flag = this.canReplaceCurrentItem(stack, itemstack);
boolean canPickup = flag && this.canHoldItem(stack);
@ -239,10 +238,16 @@ public abstract class MobMixin extends LivingEntityMixin implements MobEntityBri
forceDrops = false;
}
this.setItemSlotAndDropWhenKilled(equipmentslottype, stack);
return true;
if (equipmentslottype.isArmor() && stack.getCount() > 1) {
ItemStack itemstack1 = stack.copyWithCount(1);
this.setItemSlotAndDropWhenKilled(equipmentslottype, itemstack1);
return itemstack1;
} else {
this.setItemSlotAndDropWhenKilled(equipmentslottype, stack);
return stack;
}
} else {
return false;
return ItemStack.EMPTY;
}
}

View File

@ -1,51 +1,24 @@
package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.Registry;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.ai.behavior.AssignProfessionFromJobSite;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerData;
import net.minecraft.world.entity.npc.VillagerProfession;
import org.bukkit.craftbukkit.v.entity.CraftVillager;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.VillagerCareerChangeEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import java.util.Optional;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(AssignProfessionFromJobSite.class)
public class AssignProfessionFromJobSiteMixin {
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void start(ServerLevel worldIn, Villager entityIn, long gameTimeIn) {
GlobalPos globalpos = entityIn.getBrain().getMemory(MemoryModuleType.POTENTIAL_JOB_SITE).get();
entityIn.getBrain().eraseMemory(MemoryModuleType.POTENTIAL_JOB_SITE);
entityIn.getBrain().setMemory(MemoryModuleType.JOB_SITE, globalpos);
worldIn.broadcastEntityEvent(entityIn, (byte) 14);
if (entityIn.getVillagerData().getProfession() == VillagerProfession.NONE) {
MinecraftServer minecraftserver = worldIn.getServer();
Optional.ofNullable(minecraftserver.getLevel(globalpos.dimension())).flatMap((world) -> {
return world.getPoiManager().getType(globalpos.pos());
}).flatMap((poiType) -> {
return Registry.VILLAGER_PROFESSION.stream().filter((profession) -> {
return profession.heldJobSite().test(poiType);
}).findFirst();
}).ifPresent((profession) -> {
VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityIn, CraftVillager.nmsToBukkitProfession(profession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED);
if (!event.isCancelled()) {
VillagerData newData = entityIn.getVillagerData().setProfession(CraftVillager.bukkitToNmsProfession(event.getProfession()));
entityIn.setVillagerData(newData);
entityIn.refreshBrain(worldIn);
}
});
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;setVillagerData(Lnet/minecraft/world/entity/npc/VillagerData;)V"))
private static void arclight$jobChange(Villager instance, VillagerData villagerData) {
VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(instance, CraftVillager.nmsToBukkitProfession(villagerData.getProfession()), VillagerCareerChangeEvent.ChangeReason.EMPLOYED);
if (!event.isCancelled()) {
VillagerData newData = villagerData.setProfession(CraftVillager.bukkitToNmsProfession(event.getProfession()));
instance.setVillagerData(newData);
}
}
}

View File

@ -1,45 +1,61 @@
package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.entity.AgeableMob;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.behavior.BabyFollowAdult;
import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.ai.behavior.EntityTracker;
import net.minecraft.world.entity.ai.behavior.OneShot;
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.WalkTarget;
import org.bukkit.craftbukkit.v.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityTargetEvent;
import org.spongepowered.asm.mixin.Final;
import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.function.Function;
@Mixin(BabyFollowAdult.class)
public abstract class BabyFollowAdultMixin<E extends AgeableMob> {
// @formatter:off
@Shadow protected abstract AgeableMob getNearestAdult(E p_147430_);
@Shadow @Final private Function<LivingEntity, Float> speedModifier;
@Shadow @Final private UniformInt followRange;
// @formatter:on
public abstract class BabyFollowAdultMixin {
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void start(ServerLevel p_147426_, E entity, long p_147428_) {
var event = CraftEventFactory.callEntityTargetLivingEvent(entity, this.getNearestAdult(entity), EntityTargetEvent.TargetReason.FOLLOW_LEADER);
if (event.isCancelled()) {
return;
}
if (event.getTarget() != null) {
BehaviorUtils.setWalkAndLookTargetMemories(entity, ((CraftLivingEntity) event.getTarget()).getHandle(), this.speedModifier.apply(entity), this.followRange.getMinValue() - 1);
} else {
entity.getBrain().eraseMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT);
}
public static OneShot<AgeableMob> create(UniformInt p_259321_, Function<LivingEntity, Float> p_259190_) {
return BehaviorBuilder.create((p_258331_) -> {
return p_258331_.group(p_258331_.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), p_258331_.registered(MemoryModuleType.LOOK_TARGET), p_258331_.absent(MemoryModuleType.WALK_TARGET)).apply(p_258331_, (p_258317_, p_258318_, p_258319_) -> {
return (p_258326_, p_258327_, p_258328_) -> {
if (!p_258327_.isBaby()) {
return false;
} else {
LivingEntity ageablemob = p_258331_.get(p_258317_);
if (p_258327_.closerThan(ageablemob, (double) (p_259321_.getMaxValue() + 1)) && !p_258327_.closerThan(ageablemob, (double) p_259321_.getMinValue())) {
// CraftBukkit start
EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(p_258327_, ageablemob, EntityTargetEvent.TargetReason.FOLLOW_LEADER);
if (event.isCancelled()) {
return false;
}
if (event.getTarget() == null) {
p_258317_.erase();
return true;
}
ageablemob = ((CraftLivingEntity) event.getTarget()).getHandle();
// CraftBukkit end
WalkTarget walktarget = new WalkTarget(new EntityTracker(ageablemob, false), p_259190_.apply(p_258327_), p_259321_.getMinValue() - 1);
p_258318_.set(new EntityTracker(ageablemob, true));
p_258319_.set(walktarget);
return true;
} else {
return false;
}
}
};
});
});
}
}

View File

@ -1,51 +1,62 @@
package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import com.mojang.datafixers.kinds.K1;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
import net.minecraft.world.entity.ai.behavior.EntityTracker;
import net.minecraft.world.entity.ai.behavior.GoToWantedItem;
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.animal.allay.Allay;
import net.minecraft.world.entity.ai.memory.WalkTarget;
import net.minecraft.world.entity.item.ItemEntity;
import org.bukkit.craftbukkit.v.entity.CraftEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityTargetEvent;
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 org.spongepowered.asm.mixin.Overwrite;
import java.util.Optional;
import java.util.function.Predicate;
@Mixin(GoToWantedItem.class)
public abstract class GoToWantedItemMixin<E extends LivingEntity> {
// @formatter:off
@Shadow protected abstract ItemEntity getClosestLovedItem(E p_23156_);
@Shadow @Final private float speedModifier;
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public static <E extends LivingEntity> BehaviorControl<E> create(Predicate<E> p_259490_, float p_260346_, boolean p_259637_, int p_259054_) {
return BehaviorBuilder.create((p_258371_) -> {
BehaviorBuilder<E, ? extends MemoryAccessor<? extends K1, WalkTarget>> behaviorbuilder = p_259637_ ? p_258371_.registered(MemoryModuleType.WALK_TARGET) : p_258371_.absent(MemoryModuleType.WALK_TARGET);
return p_258371_.group(p_258371_.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder, p_258371_.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), p_258371_.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS)).apply(p_258371_, (p_258387_, p_258388_, p_258389_, p_258390_) -> {
return (p_258380_, p_258381_, p_258382_) -> {
ItemEntity itementity = p_258371_.get(p_258389_);
if (p_258371_.tryGet(p_258390_).isEmpty() && p_259490_.test(p_258381_) && itementity.closerThan(p_258381_, (double) p_259054_) && p_258381_.level.getWorldBorder().isWithinBounds(itementity.blockPosition())) {
// CraftBukkit start
if (p_258381_ instanceof net.minecraft.world.entity.animal.allay.Allay) {
var event = CraftEventFactory.callEntityTargetEvent(p_258381_, itementity, EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
@Inject(method = "start", cancellable = true, at = @At("HEAD"))
private void arclight$entityTarget(ServerLevel level, E entity, long p_23154_, CallbackInfo ci) {
if (entity instanceof Allay) {
Entity target = this.getClosestLovedItem(entity);
var event = CraftEventFactory.callEntityTargetEvent(entity, target, EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
if (event.isCancelled()) {
return false;
}
if (!(event.getTarget() instanceof ItemEntity)) {
p_258389_.erase();
}
if (event.isCancelled()) {
ci.cancel();
}
itementity = (ItemEntity) ((CraftEntity) event.getTarget()).getHandle();
}
// CraftBukkit end
target = (event.getTarget() == null) ? null : ((CraftEntity) event.getTarget()).getHandle();
if (target instanceof ItemEntity item) {
entity.getBrain().setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.of(item));
BehaviorUtils.setWalkAndLookTargetMemories(entity, target, this.speedModifier, 0);
} else {
entity.getBrain().eraseMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM);
}
ci.cancel();
}
WalkTarget walktarget = new WalkTarget(new EntityTracker(itementity, false), p_260346_, 0);
p_258387_.set(new EntityTracker(itementity, true));
p_258388_.set(walktarget);
return true;
} else {
return false;
}
};
});
});
}
}

View File

@ -1,75 +1,31 @@
package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.behavior.InteractWithDoor;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.Node;
import net.minecraft.world.level.pathfinder.Path;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.event.entity.EntityInteractEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(InteractWithDoor.class)
public abstract class InteractWithDoorMixin {
// @formatter:off
@Shadow @Nullable private Node lastCheckedNode;
@Shadow protected abstract void rememberDoorToClose(ServerLevel p_242301_1_, LivingEntity p_242301_2_, BlockPos p_242301_3_);
@Shadow public static void closeDoorsThatIHaveOpenedOrPassedThrough(ServerLevel p_242294_0_, LivingEntity p_242294_1_, @org.jetbrains.annotations.Nullable Node p_242294_2_, @org.jetbrains.annotations.Nullable Node p_242294_3_) { }
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void start(ServerLevel worldIn, LivingEntity entityIn, long gameTimeIn) {
Path path = entityIn.getBrain().getMemory(MemoryModuleType.PATH).get();
this.lastCheckedNode = path.getNextNode();
Node pathpoint = path.getPreviousNode();
Node pathpoint1 = path.getNextNode();
BlockPos blockpos = pathpoint.asBlockPos();
BlockState blockstate = worldIn.getBlockState(blockpos);
if (blockstate.is(BlockTags.WOODEN_DOORS)) {
DoorBlock doorblock = (DoorBlock) blockstate.getBlock();
if (!doorblock.isOpen(blockstate)) {
EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(((EntityBridge) entityIn).bridge$getBukkitEntity(), CraftBlock.at(entityIn.level, blockpos));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
doorblock.setOpen(entityIn, worldIn, blockstate, blockpos, true);
}
this.rememberDoorToClose(worldIn, entityIn, blockpos);
@Eject(method = "desc=/B$/", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/DoorBlock;setOpen(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Z)V"))
private static void arclight$openDoor1(DoorBlock instance, Entity entity, Level p_153167_, BlockState p_153168_, BlockPos pos, boolean p_153170_, CallbackInfoReturnable<Boolean> cir) {
var event = new EntityInteractEvent(((EntityBridge) entity).bridge$getBukkitEntity(), CraftBlock.at(entity.getLevel(), pos));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
cir.setReturnValue(false);
return;
}
BlockPos blockpos1 = pathpoint1.asBlockPos();
BlockState blockstate1 = worldIn.getBlockState(blockpos1);
if (blockstate1.is(BlockTags.WOODEN_DOORS)) {
DoorBlock doorblock1 = (DoorBlock) blockstate1.getBlock();
if (!doorblock1.isOpen(blockstate1)) {
EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(((EntityBridge) entityIn).bridge$getBukkitEntity(), CraftBlock.at(entityIn.level, blockpos));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
doorblock1.setOpen(entityIn, worldIn, blockstate1, blockpos1, true);
this.rememberDoorToClose(worldIn, entityIn, blockpos1);
}
}
closeDoorsThatIHaveOpenedOrPassedThrough(worldIn, entityIn, pathpoint, pathpoint1);
instance.setOpen(entity, p_153167_, p_153168_, pos, p_153170_);
}
}

View File

@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ResetProfession.class)
public class ResetProfessionMixin {
@Redirect(method = "start(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;setVillagerData(Lnet/minecraft/world/entity/npc/VillagerData;)V"))
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;setVillagerData(Lnet/minecraft/world/entity/npc/VillagerData;)V"))
private void arclight$careerChangeHook(Villager villagerEntity, VillagerData villagerData) {
VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(villagerEntity,
CraftVillager.nmsToBukkitProfession(VillagerProfession.NONE),

View File

@ -3,7 +3,9 @@ package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
import net.minecraft.world.entity.ai.behavior.StartAttacking;
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.event.entity.living.LivingChangeTargetEvent;
@ -13,28 +15,56 @@ import org.bukkit.event.entity.EntityTargetEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
@Mixin(StartAttacking.class)
public class StartAttackingMixin<E extends Mob> {
public class StartAttackingMixin {
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
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;
}
livingEntity = ((event.getTarget() != null) ? ((CraftLivingEntity) event.getTarget()).getHandle() : null);
var changeTargetEvent = ForgeHooks.onLivingChangeTarget(mob, livingEntity, LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET);
if (changeTargetEvent.isCanceled()) {
return;
}
livingEntity = changeTargetEvent.getNewTarget();
mob.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, livingEntity);
mob.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
// noinspection removal
ForgeHooks.onLivingSetAttackTarget(mob, livingEntity, LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET); // TODO: Remove in 1.20
public static <E extends Mob> BehaviorControl<E> create(Predicate<E> p_259618_, Function<E, Optional<? extends LivingEntity>> p_259435_) {
return BehaviorBuilder.create((p_258782_) -> {
return p_258782_.group(p_258782_.absent(MemoryModuleType.ATTACK_TARGET), p_258782_.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(p_258782_, (p_258778_, p_258779_) -> {
return (p_258773_, p_258774_, p_258775_) -> {
if (!p_259618_.test(p_258774_)) {
return false;
} else {
Optional<? extends LivingEntity> optional = p_259435_.apply(p_258774_);
if (optional.isEmpty()) {
return false;
} else {
LivingEntity livingentity = optional.get();
if (!p_258774_.canAttack(livingentity)) {
return false;
} else {
LivingChangeTargetEvent changeTargetEvent = ForgeHooks.onLivingChangeTarget(p_258774_, livingentity, LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET);
if (changeTargetEvent.isCanceled())
return false;
// CraftBukkit start
EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(p_258774_, livingentity, (livingentity instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY);
if (event.isCancelled()) {
return false;
}
if (event.getTarget() == null) {
p_258778_.erase();
return true;
}
livingentity = ((CraftLivingEntity) event.getTarget()).getHandle();
// CraftBukkit end
p_258778_.set(changeTargetEvent.getNewTarget());
p_258779_.erase();
ForgeHooks.onLivingSetAttackTarget(p_258774_, changeTargetEvent.getNewTarget(), LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET); // TODO: Remove in 1.20
return true;
}
}
}
};
});
});
}
}

View File

@ -2,30 +2,59 @@ package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
import net.minecraft.world.entity.ai.behavior.StopAttackingIfTargetInvalid;
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import org.bukkit.craftbukkit.v.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityTargetEvent;
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 org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
@Mixin(StopAttackingIfTargetInvalid.class)
public class StopAttackingIfTargetInvalidMixin<E extends Mob> {
public abstract class StopAttackingIfTargetInvalidMixin {
@Inject(method = "clearAttackTarget", cancellable = true, at = @At("HEAD"))
private void arclight$attackEvent(E mob, CallbackInfo ci) {
LivingEntity old = mob.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null);
EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(mob, old, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET);
if (event.isCancelled()) {
ci.cancel();
return;
}
if (event.getTarget() != null) {
mob.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity)event.getTarget()).getHandle());
ci.cancel();
}
// @formatter:off
@Shadow private static boolean isTiredOfTryingToReachTarget(LivingEntity p_259416_, Optional<Long> p_259377_) { return false; }
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public static <E extends Mob> BehaviorControl<E> create(Predicate<LivingEntity> p_260357_, BiConsumer<E, LivingEntity> p_259568_, boolean p_260319_) {
return BehaviorBuilder.create((p_258801_) -> {
return p_258801_.group(p_258801_.present(MemoryModuleType.ATTACK_TARGET), p_258801_.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(p_258801_, (p_258787_, p_258788_) -> {
return (p_258795_, p_258796_, p_258797_) -> {
LivingEntity livingentity = p_258801_.get(p_258787_);
if (p_258796_.canAttack(livingentity) && (!p_260319_ || !isTiredOfTryingToReachTarget(p_258796_, p_258801_.tryGet(p_258788_))) && livingentity.isAlive() && livingentity.level == p_258796_.level && !p_260357_.test(livingentity)) {
return true;
} else {
// CraftBukkit start
LivingEntity old = p_258796_.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null);
EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(p_258796_, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET);
if (event.isCancelled()) {
return false;
}
if (event.getTarget() == null) {
p_258787_.erase();
return true;
}
livingentity = ((CraftLivingEntity) event.getTarget()).getHandle();
// CraftBukkit end
p_259568_.accept(p_258796_, livingentity);
p_258787_.erase();
return true;
}
};
});
});
}
}

View File

@ -1,8 +1,8 @@
package io.izzel.arclight.common.mixin.core.world.entity.animal;
import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge;
import net.minecraft.advancements.CriteriaTriggers;
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;
import net.minecraft.world.InteractionResult;
@ -42,7 +42,7 @@ public interface BucketableMixin {
if (event.isCancelled()) {
player.containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
((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
((SynchedEntityDataBridge) livingEntity.getEntityData()).bridge$refresh((ServerPlayer) player); // Need to send data such as the display name to client
return Optional.of(InteractionResult.FAIL);
}
entity.playSound(entity.getPickupSound(), 1.0F, 1.0F);

View File

@ -0,0 +1,30 @@
package io.izzel.arclight.common.mixin.core.world.entity.animal;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.animal.Cat;
import net.minecraft.world.level.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Item;
import org.bukkit.event.entity.EntityDropItemEvent;
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.Redirect;
@Mixin(targets = "net.minecraft.world.entity.animal.Cat$CatRelaxOnOwnerGoal")
public class Cat_CatRelaxOnOwnerGoalMixin {
@Shadow @Final private Cat cat;
@Redirect(method = "giveMorningGift", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private boolean arclight$dropItem(Level instance, Entity entity) {
var event = new EntityDropItemEvent(((EntityBridge) this.cat).bridge$getBukkitEntity(), (Item) ((EntityBridge) entity).bridge$getBukkitEntity());
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
return instance.addFreshEntity(entity);
}
return false;
}
}

View File

@ -5,6 +5,7 @@ import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import net.minecraft.world.level.Level;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
@ -28,20 +29,20 @@ public abstract class EnderCrystalMixin extends EntityMixin {
@Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/enderdragon/EndCrystal;remove(Lnet/minecraft/world/entity/Entity$RemovalReason;)V"))
private void arclight$entityDamage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
if (CraftEventFactory.handleNonLivingEntityDamageEvent((EndCrystal) (Object)this, source, amount)) {
if (CraftEventFactory.handleNonLivingEntityDamageEvent((EndCrystal) (Object) this, source, amount)) {
cir.setReturnValue(false);
}
}
@Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$blockPrime(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, Explosion.BlockInteraction modeIn) {
ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), explosionRadius, false);
@Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$blockPrime(Level world, Entity entityIn, DamageSource damageSource, ExplosionDamageCalculator calculator, double xIn, double yIn, double zIn, float explosionRadius, boolean fire, Level.ExplosionInteraction interaction) {
ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), explosionRadius, fire);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
this.unsetRemoved();
return null;
} else {
return world.explode(entityIn, xIn, yIn, zIn, event.getRadius(), event.getFire(), modeIn);
return world.explode(entityIn, damageSource, calculator, xIn, yIn, zIn, event.getRadius(), event.getFire(), interaction);
}
}
}

View File

@ -8,7 +8,7 @@ import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.event.ForgeEventFactory;
@ -51,11 +51,10 @@ public abstract class WitherBossMixin extends PathfinderMobMixin {
int k1 = this.getInvulnerableTicks() - 1;
this.bossEvent.setProgress(1.0F - (float) k1 / 220.0F);
if (k1 <= 0) {
Explosion.BlockInteraction explosion$blockinteraction = ForgeEventFactory.getMobGriefingEvent(this.level, (WitherBoss) (Object) this) ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.NONE;
ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
this.level.explode((WitherBoss) (Object) this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), explosion$blockinteraction);
this.level.explode((WitherBoss) (Object) this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
}
if (!this.isSilent()) {
this.level.globalLevelEvent(1023, this.blockPosition(), 0);

View File

@ -4,7 +4,7 @@ import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.entity.player.PlayerInventoryBridge;
import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.core.network.datasync.EntityDataManagerBridge;
import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin;
import net.minecraft.network.syncher.EntityDataAccessor;
@ -127,7 +127,7 @@ public abstract class ItemEntityMixin extends EntityMixin {
@Inject(method = "setItem", at = @At("RETURN"))
private void arclight$markDirty(ItemStack stack, CallbackInfo ci) {
((EntityDataManagerBridge) this.getEntityData()).bridge$markDirty(DATA_ITEM);
((SynchedEntityDataBridge) this.getEntityData()).bridge$markDirty(DATA_ITEM);
}
@Redirect(method = "merge(Lnet/minecraft/world/entity/item/ItemEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;setItem(Lnet/minecraft/world/item/ItemStack;)V"))

View File

@ -6,7 +6,6 @@ import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.item.PrimedTnt;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Explosive;
@ -83,7 +82,7 @@ public abstract class PrimedTntMixin extends EntityMixin {
ExplosionPrimeEvent event = new ExplosionPrimeEvent((Explosive) this.getBukkitEntity());
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
this.level.explode((PrimedTnt) (Object) this, this.getX(), this.getY(0.0625), this.getZ(), event.getRadius(), event.getFire(), Explosion.BlockInteraction.BREAK);
this.level.explode((PrimedTnt) (Object) this, this.getX(), this.getY(0.0625), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.TNT);
}
}
}

View File

@ -9,8 +9,7 @@ import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.AreaEffectCloud;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.level.Explosion;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraft.world.level.Level;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.CreatureSpawnEvent;
@ -35,6 +34,7 @@ public abstract class CreeperMixin extends PathfinderMobMixin implements Creeper
@Shadow public int explosionRadius;
@Shadow protected abstract void spawnLingeringCloud();
@Shadow private int swell;
@Shadow public abstract boolean isPowered();
// @formatter:on
@Inject(method = "thunderHit", cancellable = true, at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/monster/Creeper;entityData:Lnet/minecraft/network/syncher/SynchedEntityData;"))
@ -51,13 +51,12 @@ public abstract class CreeperMixin extends PathfinderMobMixin implements Creeper
@Overwrite
public void explodeCreeper() {
if (!this.level.isClientSide) {
Explosion.BlockInteraction explosion_effect = ForgeEventFactory.getMobGriefingEvent(this.level, (Creeper) (Object) this) ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.NONE;
final float f = this.entityData.get(DATA_IS_POWERED) ? 2.0f : 1.0f;
final float f = this.isPowered() ? 2.0f : 1.0f;
final ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), this.explosionRadius * f, false);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
this.dead = true;
this.level.explode((Creeper) (Object) this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), explosion_effect);
this.level.explode((Creeper) (Object) this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
this.discard();
this.spawnLingeringCloud();
} else {

View File

@ -55,6 +55,7 @@ public abstract class SlimeMixin extends MobMixin {
float f1 = ((float) (l % 2) - 0.5F) * f;
float f2 = ((float) (l / 2) - 0.5F) * f;
net.minecraft.world.entity.monster.Slime slimeentity = this.getType().create(this.level);
if (slimeentity == null) continue;
if (this.isPersistenceRequired()) {
slimeentity.setPersistenceRequired();
}

View File

@ -91,7 +91,7 @@ public abstract class ZombieMixin extends PathfinderMobMixin {
if (zombieVillager != null) {
zombieVillager.finalizeSpawn(level, level.getCurrentDifficultyAt(zombieVillager.blockPosition()), MobSpawnType.CONVERSION, new net.minecraft.world.entity.monster.Zombie.ZombieGroupData(false, true), null);
zombieVillager.setVillagerData(villager.getVillagerData());
zombieVillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE).getValue());
zombieVillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE));
zombieVillager.setTradeOffers(villager.getOffers().createTag());
zombieVillager.setVillagerXp(villager.getVillagerXp());
net.minecraftforge.event.ForgeEventFactory.onLivingConvert(villager, zombieVillager);

View File

@ -67,7 +67,7 @@ public abstract class PiglinAiMixin {
eat(piglinEntity);
} else {
((MobEntityBridge) piglinEntity).bridge$captureItemDrop(itemEntity);
boolean flag = piglinEntity.equipItemIfPossible(itemstack);
boolean flag = !piglinEntity.equipItemIfPossible(itemstack).equals(ItemStack.EMPTY);
if (!flag) {
putInInventory(piglinEntity, itemstack);
}

View File

@ -2,7 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster.piglin;
import io.izzel.arclight.common.bridge.core.entity.monster.piglin.PiglinBridge;
import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
@ -41,17 +41,17 @@ public abstract class PiglinMixin extends PathfinderMobMixin implements PiglinBr
@Inject(method = "addAdditionalSaveData", at = @At("RETURN"))
private void arclight$writeAdditional(CompoundTag compound, CallbackInfo ci) {
ListTag barterList = new ListTag();
allowedBarterItems.stream().map(Registry.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add);
allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add);
compound.put("Bukkit.BarterList", barterList);
ListTag interestList = new ListTag();
interestItems.stream().map(Registry.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add);
interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add);
compound.put("Bukkit.InterestList", interestList);
}
@Inject(method = "readAdditionalSaveData", at = @At("RETURN"))
private void arclight$readAdditional(CompoundTag compound, CallbackInfo ci) {
this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(Registry.ITEM::get).collect(Collectors.toCollection(HashSet::new));
this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(Registry.ITEM::get).collect(Collectors.toCollection(HashSet::new));
this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new));
this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new));
}
@Redirect(method = "holdInOffHand", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/item/ItemStack;isPiglinCurrency()Z"))

View File

@ -39,19 +39,16 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobType;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.boss.EnderDragonPart;
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;
import net.minecraft.world.inventory.PlayerEnderChestContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Scoreboard;
import net.minecraftforge.common.ForgeHooks;
@ -139,7 +136,7 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
public int oldLevel;
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(Level p_219727_, BlockPos p_219728_, float p_219729_, GameProfile p_219730_, ProfilePublicKey p_219731_, CallbackInfo ci) {
private void arclight$init(CallbackInfo ci) {
oldLevel = -1;
((FoodStatsBridge) this.foodData).bridge$setEntityHuman((net.minecraft.world.entity.player.Player) (Object) this);
((IInventoryBridge) this.enderChestInventory).setOwner(this.getBukkitEntity());

View File

@ -493,7 +493,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
}
ServerLevel[] exitWorld = new ServerLevel[]{server};
LevelData iworldinfo = server.getLevelData();
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 ClientboundRespawnPacket(server.dimensionTypeId(), server.dimension(), BiomeManager.obfuscateSeed(server.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), server.isDebug(), server.isFlat(), (byte) 3, this.getLastDeathLocation()));
this.connection.send(new ClientboundChangeDifficultyPacket(iworldinfo.getDifficulty(), iworldinfo.isDifficultyLocked()));
PlayerList playerlist = this.server.getPlayerList();
playerlist.sendPlayerPermissionLevel((ServerPlayer) (Object) this);
@ -527,7 +527,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].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 ClientboundRespawnPacket(exitWorld[0].dimensionTypeId(), exitWorld[0].dimension(), BiomeManager.obfuscateSeed(exitWorld[0].getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), exitWorld[0].isDebug(), exitWorld[0].isFlat(), (byte) 3, this.getLastDeathLocation()));
this.connection.send(new ClientboundChangeDifficultyPacket(newWorldInfo.getDifficulty(), newWorldInfo.isDifficultyLocked()));
}
@ -787,7 +787,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
this.clientViewDistance = packetIn.viewDistance();
}
@Inject(method = "setCamera", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;teleportTo(DDD)V"))
@Inject(method = "setCamera", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;teleport(DDDFF)V"))
private void arclight$spectatorReason(Entity entityToSpectate, CallbackInfo ci) {
this.bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause.SPECTATE);
}

View File

@ -2,7 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile;
import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.core.entity.projectile.ArrowEntityBridge;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.effect.MobEffectInstance;
@ -45,11 +45,11 @@ public abstract class ArrowEntityMixin extends AbstractArrowMixin implements Arr
}
public String getPotionType() {
return Registry.POTION.getKey(this.potion).toString();
return BuiltInRegistries.POTION.getKey(this.potion).toString();
}
public void setPotionType(final String string) {
this.potion = Registry.POTION.get(new ResourceLocation(string));
this.potion = BuiltInRegistries.POTION.get(new ResourceLocation(string));
this.getEntityData().set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects)));
}

View File

@ -29,15 +29,15 @@ public abstract class LargeFireballMixin extends AbstractHurtingProjectileMixin
this.isIncendiary = level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
}
@Redirect(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$explodePrime(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, boolean causesFire, Explosion.BlockInteraction modeIn) {
@Redirect(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$explodePrime(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, boolean causesFire, Level.ExplosionInteraction interaction) {
ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
event.setRadius(explosionRadius);
event.setFire(causesFire);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
return this.level.explode((LargeFireball) (Object) this, xIn, yIn, zIn, event.getRadius(), event.getFire(), modeIn);
return this.level.explode((LargeFireball) (Object) this, xIn, yIn, zIn, event.getRadius(), event.getFire(), interaction);
} else {
return null;
}

View File

@ -47,11 +47,13 @@ public abstract class ThrownEggMixin extends ThrowableProjectileMixin {
if (hatching) {
for (int i = 0; i < b0; ++i) {
Entity entity = ((WorldBridge) this.level).bridge$getWorld().createEntity(new Location(((WorldBridge) this.level).bridge$getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0f), hatchingType.getEntityClass());
if (((EntityBridge) entity).bridge$getBukkitEntity() instanceof Ageable) {
((Ageable) ((EntityBridge) entity).bridge$getBukkitEntity()).setBaby();
if (entity != null) {
if (((EntityBridge) entity).bridge$getBukkitEntity() instanceof Ageable) {
((Ageable) ((EntityBridge) entity).bridge$getBukkitEntity()).setBaby();
}
((WorldBridge) this.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.EGG);
this.level.addFreshEntity(entity);
}
((WorldBridge) this.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.EGG);
this.level.addFreshEntity(entity);
}
}
this.level.broadcastEntityEvent((ThrownEgg) (Object) this, (byte) 3);

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
import net.minecraft.world.phys.HitResult;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -16,4 +17,14 @@ public abstract class ThrownEnderpearlMixin extends ThrowableProjectileMixin {
private void arclight$spawnEndermite(HitResult result, CallbackInfo ci) {
((WorldBridge) this.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.ENDER_PEARL);
}
@Inject(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private void arclight$entityDamage(CallbackInfo ci) {
CraftEventFactory.entityDamage = (ThrownEnderpearl) (Object) this;
}
@Inject(method = "onHit", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private void arclight$entityDamageReset(CallbackInfo ci) {
CraftEventFactory.entityDamage = null;
}
}

View File

@ -29,12 +29,12 @@ public abstract class WitherSkullMixin extends AbstractHurtingProjectileMixin {
((LivingEntityBridge) result.getEntity()).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ATTACK);
}
@Redirect(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$explode(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, boolean causesFire, Explosion.BlockInteraction modeIn) {
@Redirect(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$explode(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, boolean causesFire, Level.ExplosionInteraction interaction) {
ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), explosionRadius, causesFire);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
return this.level.explode((WitherSkull) (Object) this, xIn, yIn, zIn, event.getRadius(), event.getFire(), modeIn);
return this.level.explode((WitherSkull) (Object) this, xIn, yIn, zIn, event.getRadius(), event.getFire(), interaction);
}
return null;
}

View File

@ -1,9 +1,11 @@
package io.izzel.arclight.common.mixin.core.world.entity.vehicle;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.vehicle.MinecartTNT;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import net.minecraft.world.level.Level;
import org.bukkit.Bukkit;
import org.bukkit.event.entity.ExplosionPrimeEvent;
@ -17,9 +19,9 @@ public abstract class MinecartTNTMixin extends AbstractMinecartMixin {
@Shadow private int fuse;
@Eject(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFLnet/minecraft/world/level/Explosion$BlockInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$explode(Level level, Entity entity, double x, double y, double z, float radius, Explosion.BlockInteraction interaction, CallbackInfo ci) {
var event = new ExplosionPrimeEvent(this.getBukkitEntity(), radius, false);
@Eject(method = "explode(Lnet/minecraft/world/damagesource/DamageSource;D)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;"))
private Explosion arclight$explode(Level level, Entity entity, DamageSource source, ExplosionDamageCalculator calculator, double x, double y, double z, float radius, boolean fire, Level.ExplosionInteraction interaction, CallbackInfo ci) {
var event = new ExplosionPrimeEvent(this.getBukkitEntity(), radius, fire);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
this.fuse = -1;

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.inventory;
import io.izzel.arclight.common.bridge.core.inventory.container.LecternContainerBridge;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.LecternMenu;
import net.minecraft.world.inventory.MenuType;
@ -11,12 +12,12 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(MenuType.class)
public class ContainerTypeMixin<T extends AbstractContainerMenu> {
public class ContainerTypeMixin {
@Inject(method = "register", cancellable = true, at = @At("HEAD"))
private static <T extends AbstractContainerMenu> void arclight$replaceLectern(String key, MenuType.MenuSupplier<T> factory, CallbackInfoReturnable<MenuType<T>> cir) {
if (key.equals("lectern")) {
cir.setReturnValue(Registry.register(Registry.MENU, key, new MenuType<>((i, inv) -> {
cir.setReturnValue(Registry.register(BuiltInRegistries.MENU, key, new MenuType<>((i, inv) -> {
LecternMenu container = new LecternMenu(i);
((LecternContainerBridge) container).bridge$setPlayerInventory(inv);
return (T) container;

View File

@ -63,7 +63,7 @@ public abstract class CraftingMenuMixin extends AbstractContainerMenuMixin imple
return optional.isPresent();
}
@ModifyVariable(method = "slotChangedCraftingGrid", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V"))
@ModifyVariable(method = "slotChangedCraftingGrid", ordinal = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V"))
private static ItemStack arclight$preCraft(ItemStack stack, AbstractContainerMenu container, Level level, Player player, CraftingContainer craftingContainer, ResultContainer resultContainer) {
return CraftEventFactory.callPreCraftEvent(craftingContainer, resultContainer, stack, ((ContainerBridge) container).bridge$getBukkitView(), arclight$isRepair);
}

View File

@ -6,7 +6,7 @@ import io.izzel.arclight.common.bridge.core.inventory.container.PosContainerBrid
import io.izzel.arclight.common.bridge.core.util.IWorldPosCallableBridge;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
@ -112,7 +112,7 @@ public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMix
List<EnchantmentInstance> list = this.getEnchantmentList(itemstack, j1, this.costs[j1]);
if (list != null && !list.isEmpty()) {
EnchantmentInstance enchantmentdata = list.get(this.random.nextInt(list.size()));
this.enchantClue[j1] = Registry.ENCHANTMENT.getId(enchantmentdata.enchantment);
this.enchantClue[j1] = BuiltInRegistries.ENCHANTMENT.getId(enchantmentdata.enchantment);
this.levelClue[j1] = enchantmentdata.level;
}
}
@ -122,7 +122,7 @@ public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMix
CraftItemStack item = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3];
for (int j = 0; j < 3; ++j) {
org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(ForgeRegistries.ENCHANTMENTS.getKey(Registry.ENCHANTMENT.byId(this.enchantClue[j])))) : null;
org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(ForgeRegistries.ENCHANTMENTS.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null;
offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null;
}
@ -143,7 +143,7 @@ public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMix
EnchantmentOffer offer = event.getOffers()[j];
if (offer != null) {
this.costs[j] = offer.getCost();
this.enchantClue[j] = Registry.ENCHANTMENT.getId(ForgeRegistries.ENCHANTMENTS.getValue(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey())));
this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(ForgeRegistries.ENCHANTMENTS.getValue(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey())));
this.levelClue[j] = offer.getEnchantmentLevel();
} else {
this.costs[j] = 0;

View File

@ -77,7 +77,7 @@ public abstract class BoatItemMixin extends Item {
}
Boat boatentity = this.getBoat(worldIn, result);
boatentity.setType(this.type);
boatentity.setVariant(this.type);
boatentity.setYRot(playerIn.getYRot());
if (!worldIn.noCollision(boatentity, boatentity.getBoundingBox().inflate(-0.1D))) {
return new InteractionResultHolder<>(InteractionResult.FAIL, itemstack);

View File

@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.BlastingRecipe;
import net.minecraft.world.item.crafting.CookingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeType;
import org.bukkit.craftbukkit.v.inventory.CraftBlastingRecipe;
@ -17,8 +18,8 @@ import org.spongepowered.asm.mixin.Mixin;
@Mixin(BlastingRecipe.class)
public abstract class BlastingRecipeMixin extends AbstractCookingRecipe implements IRecipeBridge {
public BlastingRecipeMixin(RecipeType<?> typeIn, ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn) {
super(typeIn, idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn);
public BlastingRecipeMixin(RecipeType<?> p_250197_, ResourceLocation p_249379_, String p_249518_, CookingBookCategory p_250891_, Ingredient p_251354_, ItemStack p_252185_, float p_252165_, int p_250256_) {
super(p_250197_, p_249379_, p_249518_, p_250891_, p_251354_, p_252185_, p_252165_, p_250256_);
}
@Override
@ -26,6 +27,7 @@ public abstract class BlastingRecipeMixin extends AbstractCookingRecipe implemen
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftBlastingRecipe recipe = new CraftBlastingRecipe(CraftNamespacedKey.fromMinecraft(this.getId()), result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
recipe.setGroup(this.group);
recipe.setCategory(CraftRecipe.getCategory(this.category()));
return recipe;
}
}

View File

@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.CampfireCookingRecipe;
import net.minecraft.world.item.crafting.CookingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeType;
import org.bukkit.craftbukkit.v.inventory.CraftCampfireRecipe;
@ -17,8 +18,8 @@ import org.spongepowered.asm.mixin.Mixin;
@Mixin(CampfireCookingRecipe.class)
public abstract class CampfireCookingRecipeMixin extends AbstractCookingRecipe implements IRecipeBridge {
public CampfireCookingRecipeMixin(RecipeType<?> typeIn, ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn) {
super(typeIn, idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn);
public CampfireCookingRecipeMixin(RecipeType<?> p_250197_, ResourceLocation p_249379_, String p_249518_, CookingBookCategory p_250891_, Ingredient p_251354_, ItemStack p_252185_, float p_252165_, int p_250256_) {
super(p_250197_, p_249379_, p_249518_, p_250891_, p_251354_, p_252185_, p_252165_, p_250256_);
}
@Override
@ -26,6 +27,7 @@ public abstract class CampfireCookingRecipeMixin extends AbstractCookingRecipe i
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftCampfireRecipe recipe = new CraftCampfireRecipe(CraftNamespacedKey.fromMinecraft(this.getId()), result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
recipe.setGroup(this.group);
recipe.setCategory(CraftRecipe.getCategory(this.category()));
return recipe;
}
}

View File

@ -1,20 +1,20 @@
package io.izzel.arclight.common.mixin.core.world.item.crafting;
import io.izzel.arclight.common.bridge.core.item.crafting.IngredientBridge;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
@Mixin(Ingredient.class)
public abstract class IngredientMixin implements IngredientBridge {
// @formatter:off
@Shadow public abstract void dissolve();
@Shadow public ItemStack[] itemStacks;
@Shadow public abstract boolean isEmpty();
@Shadow public abstract ItemStack[] getItems();
// @formatter:on
public boolean exact;
@ -24,28 +24,28 @@ public abstract class IngredientMixin implements IngredientBridge {
* @reason
*/
@Overwrite
public boolean test(@Nullable ItemStack stack) {
if (stack == null) {
public boolean test(@Nullable ItemStack itemstack) {
if (itemstack == null) {
return false;
} else if (this.isEmpty()) {
return itemstack.isEmpty();
} else {
this.dissolve();
if (this.itemStacks.length == 0) {
return stack.isEmpty();
} else {
for (ItemStack itemstack : this.itemStacks) {
if (exact) {
if (itemstack.getItem() == stack.getItem() && ItemStack.isSame(itemstack, stack)) {
return true;
}
continue;
}
if (itemstack.getItem() == stack.getItem()) {
ItemStack[] items = this.getItems();
for (ItemStack stack : items) {
// CraftBukkit start
if (exact) {
if (stack.getItem() == itemstack.getItem() && ItemStack.tagMatches(itemstack, stack)) {
return true;
}
continue;
}
// CraftBukkit end
if (stack.is(itemstack.getItem())) {
return true;
}
return false;
}
return false;
}
}

View File

@ -8,7 +8,7 @@ import com.google.gson.JsonParseException;
import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge;
import io.izzel.arclight.common.bridge.core.item.crafting.RecipeManagerBridge;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.GsonHelper;
@ -53,7 +53,7 @@ public abstract class RecipeManagerMixin implements RecipeManagerBridge {
this.hasErrors = false;
Map<RecipeType<?>, Object2ObjectLinkedOpenHashMap<ResourceLocation, Recipe<?>>> map = Maps.newHashMap();
for (RecipeType<?> type : Registry.RECIPE_TYPE) {
for (RecipeType<?> type : BuiltInRegistries.RECIPE_TYPE) {
map.put(type, new Object2ObjectLinkedOpenHashMap<>());
}
@ -139,7 +139,7 @@ public abstract class RecipeManagerMixin implements RecipeManagerBridge {
public void clearRecipes() {
this.recipes = new HashMap<>();
for (RecipeType<?> type : Registry.RECIPE_TYPE) {
for (RecipeType<?> type : BuiltInRegistries.RECIPE_TYPE) {
this.recipes.put(type, new Object2ObjectLinkedOpenHashMap<>());
}
this.byName = new HashMap<>();

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.core.item.crafting.IRecipeBridge;
import io.izzel.arclight.common.mod.util.ArclightSpecialRecipe;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.ShapedRecipe;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
@ -24,6 +25,7 @@ public abstract class ShapedRecipeMixin implements IRecipeBridge {
@Shadow @Final NonNullList<Ingredient> recipeItems;
@Shadow public abstract int getHeight();
@Shadow public abstract int getWidth();
@Shadow public abstract CraftingBookCategory category();
// @formatter:on
@Override
@ -34,6 +36,7 @@ public abstract class ShapedRecipeMixin implements IRecipeBridge {
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftShapedRecipe recipe = new CraftShapedRecipe(result, (ShapedRecipe) (Object) this);
recipe.setGroup(this.group);
recipe.setCategory(CraftRecipe.getCategory(this.category()));
switch (this.getHeight()) {
case 1:

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world.item.crafting;
import io.izzel.arclight.common.bridge.core.item.crafting.IRecipeBridge;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.ShapelessRecipe;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
@ -14,12 +15,13 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ShapelessRecipe.class)
public class ShapelessRecipeMixin implements IRecipeBridge {
public abstract class ShapelessRecipeMixin implements IRecipeBridge {
// @formatter:off
@Shadow @Final ItemStack result;
@Shadow @Final String group;
@Shadow @Final NonNullList<Ingredient> ingredients;
@Shadow public abstract CraftingBookCategory category();
// @formatter:off
@Override
@ -27,6 +29,7 @@ public class ShapelessRecipeMixin implements IRecipeBridge {
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftShapelessRecipe recipe = new CraftShapelessRecipe(result, (ShapelessRecipe)(Object) this);
recipe.setGroup(this.group);
recipe.setCategory(CraftRecipe.getCategory(this.category()));
for (Ingredient list : this.ingredients) {
recipe.addIngredient(CraftRecipe.toBukkit(list));
}

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.core.item.crafting.IRecipeBridge;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.CookingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.SmeltingRecipe;
@ -15,10 +16,10 @@ import org.bukkit.inventory.Recipe;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(SmeltingRecipe.class)
public abstract class FurnaceRecipeMixin extends AbstractCookingRecipe implements IRecipeBridge {
public abstract class SmeltingRecipeMixin extends AbstractCookingRecipe implements IRecipeBridge {
public FurnaceRecipeMixin(RecipeType<?> typeIn, ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn) {
super(typeIn, idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn);
public SmeltingRecipeMixin(RecipeType<?> p_250197_, ResourceLocation p_249379_, String p_249518_, CookingBookCategory p_250891_, Ingredient p_251354_, ItemStack p_252185_, float p_252165_, int p_250256_) {
super(p_250197_, p_249379_, p_249518_, p_250891_, p_251354_, p_252185_, p_252165_, p_250256_);
}
@Override
@ -27,6 +28,7 @@ public abstract class FurnaceRecipeMixin extends AbstractCookingRecipe implement
CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(CraftNamespacedKey.fromMinecraft(this.id), result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
recipe.setGroup(this.group);
recipe.setCategory(CraftRecipe.getCategory(this.category()));
return recipe;
}

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.core.item.crafting.IRecipeBridge;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.CookingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.SmokingRecipe;
@ -17,8 +18,8 @@ import org.spongepowered.asm.mixin.Mixin;
@Mixin(SmokingRecipe.class)
public abstract class SmokingRecipeMixin extends AbstractCookingRecipe implements IRecipeBridge {
public SmokingRecipeMixin(RecipeType<?> typeIn, ResourceLocation idIn, String groupIn, Ingredient ingredientIn, ItemStack resultIn, float experienceIn, int cookTimeIn) {
super(typeIn, idIn, groupIn, ingredientIn, resultIn, experienceIn, cookTimeIn);
public SmokingRecipeMixin(RecipeType<?> p_250197_, ResourceLocation p_249379_, String p_249518_, CookingBookCategory p_250891_, Ingredient p_251354_, ItemStack p_252185_, float p_252165_, int p_250256_) {
super(p_250197_, p_249379_, p_249518_, p_250891_, p_251354_, p_252185_, p_252165_, p_250256_);
}
@Override
@ -26,6 +27,7 @@ public abstract class SmokingRecipeMixin extends AbstractCookingRecipe implement
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftSmokingRecipe recipe = new CraftSmokingRecipe(CraftNamespacedKey.fromMinecraft(this.getId()), result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime);
recipe.setGroup(this.group);
recipe.setCategory(CraftRecipe.getCategory(this.category()));
return recipe;
}
}

View File

@ -11,7 +11,7 @@ import io.izzel.arclight.common.mod.util.ArclightCaptures;
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
@ -204,7 +204,7 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter {
}
var generator = serverWorld.getChunkSource().getGenerator();
if (biomeProvider != null) {
BiomeSource biomeSource = new CustomWorldChunkManager(worldInfo, biomeProvider, serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY));
BiomeSource biomeSource = new CustomWorldChunkManager(worldInfo, biomeProvider, serverWorld.registryAccess().registryOrThrow(Registries.BIOME));
((ChunkGeneratorBridge) generator).bridge$setBiomeSource(biomeSource);
}
CustomChunkGenerator gen = new CustomChunkGenerator(serverWorld, generator, this.generator);

View File

@ -3,7 +3,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.BambooStalkBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BambooLeaves;
@ -18,8 +18,8 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BambooBlock.class)
public abstract class BambooBlockMixin extends BlockMixin {
@Mixin(BambooStalkBlock.class)
public abstract class BambooStalkBlockMixin extends BlockMixin {
@Shadow @Final public static EnumProperty<BambooLeaves> LEAVES;
@Shadow @Final public static IntegerProperty AGE;

View File

@ -6,7 +6,6 @@ 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;
@ -14,6 +13,7 @@ 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 net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@ -74,7 +74,8 @@ public abstract class BedBlockMixin {
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);
Vec3 vec3d = pos.getCenter();
level.explode(null, DamageSource.badRespawnPointExplosion(vec3d), null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
} else if (p_49477_.getMessage() != null) {
p_49518_.displayClientMessage(p_49477_.getMessage(), true);
}

View File

@ -2,11 +2,9 @@ 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.entity.projectile.AbstractArrow;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.ButtonBlock;
import net.minecraft.world.level.block.state.BlockState;
@ -26,8 +24,6 @@ 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.util.List;
@Mixin(ButtonBlock.class)
public class ButtonBlockMixin {
@ -38,25 +34,14 @@ public class ButtonBlockMixin {
@Inject(method = "checkPressed", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;getValue(Lnet/minecraft/world/level/block/state/properties/Property;)Ljava/lang/Comparable;"))
public void arclight$entityInteract(BlockState state, Level worldIn, BlockPos pos, CallbackInfo ci,
List<? extends Entity> list, boolean flag) {
AbstractArrow abstractarrow, boolean flag) {
boolean flag1 = state.getValue(ButtonBlock.POWERED);
if (flag1 != flag && flag) {
Block block = CraftBlock.at(worldIn, pos);
boolean allowed = false;
EntityInteractEvent event = new EntityInteractEvent(((EntityBridge) abstractarrow).bridge$getBukkitEntity(), block);
Bukkit.getPluginManager().callEvent(event);
for (Object object : list) {
if (object != null) {
EntityInteractEvent event = new EntityInteractEvent(((EntityBridge) object).bridge$getBukkitEntity(), block);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
allowed = true;
break;
}
}
}
if (!allowed) {
if (event.isCancelled()) {
ci.cancel();
}
}
@ -65,7 +50,7 @@ public class ButtonBlockMixin {
@Inject(method = "checkPressed", 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"))
public void arclight$blockRedstone3(BlockState state, Level worldIn, BlockPos pos, CallbackInfo ci,
List<? extends Entity> list, boolean flag, boolean flag1) {
AbstractArrow abstractarrow, boolean flag, boolean flag1) {
Block block = CraftBlock.at(worldIn, pos);
int old = (flag1) ? 15 : 0;
int current = (!flag1) ? 15 : 0;
@ -94,16 +79,4 @@ 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, RandomSource rand, CallbackInfo ci) {
Block block = CraftBlock.at(worldIn, pos);
BlockRedstoneEvent event = new BlockRedstoneEvent(block, 15, 0);
Bukkit.getPluginManager().callEvent(event);
if (event.getNewCurrent() > 0) {
ci.cancel();
}
}
}

View File

@ -1,15 +1,10 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
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.Block;
import net.minecraft.world.level.block.CarvedPumpkinBlock;
import net.minecraft.world.level.block.LevelEvent;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
import org.bukkit.event.entity.CreatureSpawnEvent;
import net.minecraft.world.level.block.state.pattern.BlockPattern;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -19,47 +14,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(CarvedPumpkinBlock.class)
public class CarvedPumpkinBlockMixin {
private transient BlockStateListPopulator arclight$populator;
private transient boolean arclight$success = false;
@Redirect(method = "trySpawnGolem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
public boolean arclight$storeUpdate1(Level world, BlockPos pos, BlockState newState, int flags) {
if (arclight$populator == null) {
arclight$populator = new BlockStateListPopulator(world);
}
return arclight$populator.setBlock(pos, newState, flags);
@Redirect(method = "spawnGolemInWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/CarvedPumpkinBlock;clearPatternBlocks(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch;)V"))
private static void arclight$clearLater(Level level, BlockPattern.BlockPatternMatch match) {
}
@Redirect(method = "trySpawnGolem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;levelEvent(ILnet/minecraft/core/BlockPos;I)V"))
public void arclight$storeUpdate2(Level world, int type, BlockPos pos, int data) {
// do nothing
}
@Inject(method = "trySpawnGolem", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
public void arclight$returnIfFail(Level world, BlockPos blockPos, CallbackInfo ci) {
if (arclight$success) {
if (arclight$populator != null) {
for (BlockPos pos : arclight$populator.getBlocks()) {
world.levelEvent(LevelEvent.PARTICLES_DESTROY_BLOCK, pos, Block.getId(world.getBlockState(pos)));
}
arclight$populator.updateList();
}
} else {
@Inject(method = "spawnGolemInWorld", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private static void arclight$clearPattern(Level p_249110_, BlockPattern.BlockPatternMatch p_251293_, Entity entity, BlockPos p_251189_, CallbackInfo ci) {
if (!entity.isAddedToWorld()) {
ci.cancel();
} else {
CarvedPumpkinBlock.clearPatternBlocks(p_249110_, p_251293_);
}
arclight$populator = null;
arclight$success = false;
}
@Redirect(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
public boolean arclight$spawnSnow(Level world, Entity entityIn) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN);
return arclight$success = world.addFreshEntity(entityIn);
}
@Redirect(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
public boolean arclight$spawnIron(Level world, Entity entityIn) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM);
return arclight$success = world.addFreshEntity(entityIn);
}
}

View File

@ -2,6 +2,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.DoorBlock;
@ -12,6 +13,7 @@ import net.minecraft.world.level.block.state.properties.EnumProperty;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.event.block.BlockRedstoneEvent;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@ -24,7 +26,7 @@ public abstract class DoorBlockMixin {
@Shadow @Final public static EnumProperty<DoubleBlockHalf> HALF;
@Shadow @Final public static BooleanProperty POWERED;
@Shadow @Final public static BooleanProperty OPEN;
@Shadow protected abstract void playSound(Level worldIn, BlockPos pos, boolean isOpening);
@Shadow protected abstract void playSound(@Nullable Entity p_251616_, Level p_249656_, BlockPos p_249439_, boolean p_251628_);
// @formatter:on
/**
@ -49,7 +51,7 @@ public abstract class DoorBlockMixin {
boolean flag = event.getNewCurrent() > 0;
if (flag != state.getValue(OPEN)) {
this.playSound(worldIn, pos, flag);
this.playSound(null, worldIn, pos, flag);
}
worldIn.setBlock(pos, state.setValue(POWERED, flag).setValue(OPEN, flag), 2);

View File

@ -36,7 +36,7 @@ public class DragonEggBlockMixin {
private transient BlockPos arclight$toBlock;
@ModifyVariable(method = "teleport", index = 6, name = "blockpos", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 2))
@ModifyVariable(method = "teleport", ordinal = 1, name = "blockpos", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 2))
public BlockPos arclight$setPos(BlockPos pos) {
return arclight$toBlock;
}

View File

@ -4,13 +4,10 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.entity.EntityTypeBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.NetherPortalBlock;
import net.minecraft.world.level.block.state.BlockState;
@ -27,9 +24,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(NetherPortalBlock.class)
public class NetherPortalBlockMixin {
@Redirect(method = "randomTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/network/chat/Component;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;"))
public Entity arclight$spawn(EntityType<?> entityType, ServerLevel worldIn, CompoundTag compound, Component customName, Player playerIn, BlockPos pos, MobSpawnType reason, boolean flag, boolean flag1) {
return ((EntityTypeBridge<?>) entityType).bridge$spawnCreature(worldIn, compound, customName, playerIn, pos, reason, flag, flag1, CreatureSpawnEvent.SpawnReason.NETHER_PORTAL);
@Redirect(method = "randomTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;)Lnet/minecraft/world/entity/Entity;"))
public Entity arclight$spawn(EntityType<?> instance, ServerLevel p_262634_, BlockPos p_262707_, MobSpawnType p_262597_) {
return ((EntityTypeBridge<?>) instance).bridge$spawnCreature(p_262634_, p_262707_, p_262597_, CreatureSpawnEvent.SpawnReason.NETHER_PORTAL);
}
@Inject(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handleInsidePortal(Lnet/minecraft/core/BlockPos;)V"))

View File

@ -8,45 +8,16 @@ import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.block.NotePlayEvent;
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.CallbackInfo;
@Mixin(NoteBlock.class)
public abstract class NoteBlockMixin {
// @formatter:off
@Shadow protected abstract void playNote(Entity entity, Level worldIn, BlockPos pos);
// @formatter:on
@Redirect(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/NoteBlock;playNote(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V"))
public void arclight$callNote2(NoteBlock noteBlock, Entity entity, Level worldIn, BlockPos pos, BlockState blockState) {
this.playNote(entity, worldIn, pos, blockState);
}
@Redirect(method = "neighborChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/NoteBlock;playNote(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V"))
public void arclight$callNote1(NoteBlock noteBlock, Entity entity, Level worldIn, BlockPos pos, BlockState blockState) {
this.playNote(entity, worldIn, pos, blockState);
}
@Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/NoteBlock;playNote(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V"))
public void arclight$callNote3(NoteBlock noteBlock, Entity entity, Level worldIn, BlockPos pos, BlockState blockState) {
this.playNote(entity, worldIn, pos, blockState);
}
private transient BlockState arclight$state;
private void playNote(Entity entity, Level worldIn, BlockPos pos, BlockState state) {
arclight$state = state;
this.playNote(entity, worldIn, pos);
arclight$state = null;
}
@Inject(method = "playNote", cancellable = true, require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;blockEvent(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;II)V"))
private void arclight$notePlay(Entity entity, Level worldIn, BlockPos pos, CallbackInfo ci) {
NotePlayEvent event = CraftEventFactory.callNotePlayEvent(worldIn, pos, arclight$state.getValue(NoteBlock.INSTRUMENT), arclight$state.getValue(NoteBlock.NOTE));
private void arclight$notePlay(Entity entity, BlockState state, Level worldIn, BlockPos pos, CallbackInfo ci) {
NotePlayEvent event = CraftEventFactory.callNotePlayEvent(worldIn, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
if (event.isCancelled()) {
ci.cancel();
}

View File

@ -9,7 +9,7 @@ import net.minecraft.BlockUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
@ -49,7 +49,7 @@ public abstract class PortalShapeMixin implements PortalSizeBridge {
@Shadow private int height;
@Shadow @Final private Direction rightDir;
@Shadow @Final private int width;
@Shadow public static PortalInfo createPortalInfo(ServerLevel world, BlockUtil.FoundRectangle result, Direction.Axis axis, Vec3 offsetVector, EntityDimensions size, Vec3 motion, float rotationYaw, float rotationPitch) { return null; }
@Shadow public static PortalInfo createPortalInfo(ServerLevel p_259301_, BlockUtil.FoundRectangle p_259931_, Direction.Axis p_259901_, Vec3 p_259630_, Entity p_259166_, Vec3 p_260043_, float p_259853_, float p_259667_) { return null; }
// @formatter:on
List<BlockState> blocks = new ArrayList<>();
@ -101,8 +101,8 @@ public abstract class PortalShapeMixin implements PortalSizeBridge {
return portalInfo;
}
private static PortalInfo createPortalInfo(ServerLevel world, BlockUtil.FoundRectangle result, Direction.Axis axis, Vec3 offsetVector, EntityDimensions size, Vec3 motion, float rotationYaw, float rotationPitch, CraftPortalEvent event) {
private static PortalInfo createPortalInfo(ServerLevel world, BlockUtil.FoundRectangle result, Direction.Axis axis, Vec3 offsetVector, Entity entity, Vec3 motion, float rotationYaw, float rotationPitch, CraftPortalEvent event) {
ArclightCaptures.captureCraftPortalEvent(event);
return createPortalInfo(world, result, axis, offsetVector, size, motion, rotationYaw, rotationPitch);
return createPortalInfo(world, result, axis, offsetVector, entity, motion, rotationYaw, rotationPitch);
}
}

View File

@ -3,58 +3,41 @@ package io.izzel.arclight.common.mixin.core.world.level.block;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.LevelEvent;
import net.minecraft.world.level.block.CarvedPumpkinBlock;
import net.minecraft.world.level.block.WitherSkullBlock;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
import net.minecraft.world.level.block.state.pattern.BlockPattern;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(WitherSkullBlock.class)
public class WitherSkullBlockMixin {
private static transient BlockStateListPopulator arclight$populator;
private static transient boolean arclight$success = false;
@Redirect(method = "checkSpawn", 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 static boolean arclight$storeUpdate1(Level world, BlockPos pos, BlockState newState, int flags) {
if (arclight$populator == null) {
arclight$populator = new BlockStateListPopulator(world);
}
return arclight$populator.setBlock(pos, newState, flags);
@Redirect(method = "checkSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/CarvedPumpkinBlock;clearPatternBlocks(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch;)V"))
private static void arclight$clearLater(Level p_249604_, BlockPattern.BlockPatternMatch p_251190_) {
}
@Redirect(method = "checkSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;levelEvent(ILnet/minecraft/core/BlockPos;I)V"))
private static void arclight$storeUpdate2(Level world, int type, BlockPos pos, int data) {
// do nothing
}
@Inject(method = "checkSpawn", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private static void arclight$returnIfFail(Level worldIn, BlockPos blockPos, SkullBlockEntity tileEntity, CallbackInfo ci) {
if (arclight$success) {
if (arclight$populator != null) {
for (BlockPos pos : arclight$populator.getBlocks()) {
worldIn.levelEvent(LevelEvent.PARTICLES_DESTROY_BLOCK, pos, Block.getId(worldIn.getBlockState(pos)));
}
arclight$populator.updateList();
}
} else {
@Inject(method = "checkSpawn", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;makeInvulnerable()V"))
private static void arclight$addEntity(Level level, BlockPos pos, SkullBlockEntity p_58258_, CallbackInfo ci,
BlockState state, boolean flag, BlockPattern.BlockPatternMatch patternMatch, WitherBoss witherBoss) {
((WorldBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER);
if (!level.addFreshEntity(witherBoss)) {
ci.cancel();
} else {
CarvedPumpkinBlock.clearPatternBlocks(level, patternMatch);
}
arclight$populator = null;
arclight$success = false;
}
@Redirect(method = "checkSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private static boolean arclight$spawnWither(Level world, Entity entityIn) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER);
return arclight$success = world.addFreshEntity(entityIn);
private static boolean arclight$muteSpawn(Level instance, Entity entity) {
return true;
}
}

View File

@ -21,7 +21,7 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(CampfireBlockEntity.class)
public abstract class CampfireTileEntityMixin extends BlockEntityMixin {
public abstract class CampfireBlockEntityMixin extends BlockEntityMixin {
@Shadow @Final private RecipeManager.CachedCheck<Container, CampfireCookingRecipe> quickCheck;
@ -40,9 +40,11 @@ public abstract class CampfireTileEntityMixin extends BlockEntityMixin {
entity.cookingProgress[i]++;
if (entity.cookingProgress[i] >= entity.cookingTime[i]) {
Container container = new SimpleContainer(itemstack);
ItemStack itemstack1 = ((CampfireTileEntityMixin) (Object) entity).quickCheck.getRecipeFor(container, level).map((p_155305_) -> {
ItemStack itemstack1 = ((CampfireBlockEntityMixin) (Object) entity).quickCheck.getRecipeFor(container, level).map((p_155305_) -> {
return p_155305_.assemble(container);
}).orElse(itemstack);
if (!itemstack1.isItemEnabled(level.enabledFeatures())) continue;
CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);

View File

@ -0,0 +1,68 @@
package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import io.izzel.arclight.common.mod.util.DistValidate;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.ChiseledBookShelfBlockEntity;
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.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList;
import java.util.List;
@Mixin(ChiseledBookShelfBlockEntity.class)
public abstract class ChiseledBookShelfBlockEntityMixin extends BlockEntityMixin implements IInventoryBridge, Container {
@Shadow @Final private NonNullList<ItemStack> items;
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = 1;
@Override
public List<ItemStack> getContents() {
return this.items;
}
@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 void setOwner(InventoryHolder owner) {
}
@Override
public void setMaxStackSize(int size) {
maxStack = size;
}
@Override
public int getMaxStackSize() {
return maxStack;
}
@Override
public Location getLocation() {
if (!DistValidate.isValid(level)) return null;
return new org.bukkit.Location(((WorldBridge) level).bridge$getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ());
}
}

View File

@ -0,0 +1,49 @@
package io.izzel.arclight.common.mixin.core.world.level.gameevent;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import io.izzel.arclight.common.bridge.core.world.WorldBridge;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.GameEventDispatcher;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
import org.bukkit.event.world.GenericGameEvent;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Objects;
@Mixin(GameEventDispatcher.class)
public class GameEventDispatcherMixin {
@Shadow @Final private ServerLevel level;
private transient int arclight$newRadius;
@Inject(method = "post", cancellable = true, at = @At("HEAD"))
private void arclight$gameEvent(GameEvent gameEvent, Vec3 vec3, GameEvent.Context context, CallbackInfo ci) {
var entity = context.sourceEntity();
var i = gameEvent.getNotificationRadius();
GenericGameEvent event = new GenericGameEvent(Objects.requireNonNull(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(gameEvent)))),
new Location(((WorldBridge) this.level).bridge$getWorld(), vec3.x(), vec3.y(), vec3.z()), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), i, !Bukkit.isPrimaryThread());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
ci.cancel();
} else {
arclight$newRadius = event.getRadius();
}
}
@Redirect(method = "post", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/gameevent/GameEvent;getNotificationRadius()I"))
private int arclight$applyRadius(GameEvent instance) {
return arclight$newRadius;
}
}

View File

@ -2,12 +2,13 @@ package io.izzel.arclight.common.mixin.core.world.level.gameevent.vibrations;
import io.izzel.arclight.common.bridge.core.entity.EntityBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.PositionSource;
import net.minecraft.world.level.gameevent.vibrations.VibrationInfo;
import net.minecraft.world.level.gameevent.vibrations.VibrationListener;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
@ -26,11 +27,11 @@ import java.util.Optional;
public abstract class VibrationListenerMixin {
// @formatter:off
@Shadow @Nullable protected VibrationListener.ReceivingEvent receivingEvent;
@Shadow @Final protected VibrationListener.VibrationListenerConfig config;
@Shadow @Final protected PositionSource listenerSource;
@Shadow private static boolean isOccluded(Level p_223776_, Vec3 p_223777_, Vec3 p_223778_) { return false; }
@Shadow protected abstract void scheduleSignal(ServerLevel p_223770_, GameEvent p_223771_, GameEvent.Context p_223772_, Vec3 p_223773_, Vec3 p_223774_);
@Shadow @Nullable protected VibrationInfo currentVibration;
@Shadow public abstract void scheduleVibration(ServerLevel p_250210_, GameEvent p_251063_, GameEvent.Context p_249354_, Vec3 p_250310_, Vec3 p_249553_);
// @formatter:on
/**
@ -38,34 +39,33 @@ public abstract class VibrationListenerMixin {
* @reason
*/
@Overwrite
public boolean handleGameEvent(ServerLevel level, GameEvent.Message p_223768_) {
if (this.receivingEvent != null) {
public boolean handleGameEvent(ServerLevel worldserver, GameEvent gameevent, GameEvent.Context gameevent_a, Vec3 vec3d) {
if (this.currentVibration != null) {
return false;
} else if (!this.config.isValidVibration(gameevent, gameevent_a)) {
return false;
} else {
GameEvent gameevent = p_223768_.gameEvent();
GameEvent.Context gameevent$context = p_223768_.context();
if (!this.config.isValidVibration(gameevent, gameevent$context)) {
Optional<Vec3> optional = this.listenerSource.getPosition(worldserver);
if (optional.isEmpty()) {
return false;
} else {
Optional<Vec3> optional = this.listenerSource.getPosition(level);
if (optional.isEmpty()) {
Vec3 vec3d1 = optional.get();
// CraftBukkit start
boolean defaultCancel = !this.config.shouldListen(worldserver, (VibrationListener) (Object) this, new BlockPos(vec3d), gameevent, gameevent_a);
Entity entity = gameevent_a.sourceEntity();
BlockReceiveGameEvent event = new BlockReceiveGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(gameevent))), CraftBlock.at(worldserver, new BlockPos(vec3d1)), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity());
event.setCancelled(defaultCancel);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
// CraftBukkit end
return false;
} else if (isOccluded(worldserver, vec3d, vec3d1)) {
return false;
} else {
Vec3 vec3 = p_223768_.source();
Vec3 vec31 = optional.get();
boolean cancelled = !this.config.shouldListen(level, (VibrationListener) (Object) this, new BlockPos(vec3), gameevent, gameevent$context);
Entity entity = gameevent$context.sourceEntity();
var event = new BlockReceiveGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(gameevent))), CraftBlock.at(level, new BlockPos(vec31)), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity());
event.setCancelled(cancelled);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return false;
} else if (isOccluded(level, vec3, vec31)) {
return false;
} else {
this.scheduleSignal(level, gameevent, gameevent$context, vec3, vec31);
return true;
}
this.scheduleVibration(worldserver, gameevent, gameevent_a, vec3d, vec3d1);
return true;
}
}
}

View File

@ -1,6 +1,8 @@
package io.izzel.arclight.common.mixin.core.world.level.levelgen.structure.templatesystem;
import net.minecraft.core.HolderGetter;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataTypeRegistry;
@ -24,7 +26,7 @@ public class StructureTemplateMixin {
}
@Inject(method = "load", at = @At("RETURN"))
private void arclight$loadPdc(CompoundTag tag, CallbackInfo ci) {
private void arclight$loadPdc(HolderGetter<Block> reg, CompoundTag tag, CallbackInfo ci) {
var base = tag.get("BukkitValues");
if (base instanceof CompoundTag compoundTag) {
this.persistentDataContainer.putAll(compoundTag);

View File

@ -5,7 +5,7 @@ import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@ -47,9 +47,9 @@ public interface NeighborUpdaterMixin {
CrashReportCategory crashreportcategory = crashreport.addCategory("Block being updated");
crashreportcategory.setDetail("Source block type", () -> {
try {
return String.format(Locale.ROOT, "ID #%s (%s // %s)", Registry.BLOCK.getKey(block), block.getDescriptionId(), block.getClass().getCanonicalName());
return String.format(Locale.ROOT, "ID #%s (%s // %s)", BuiltInRegistries.BLOCK.getKey(block), block.getDescriptionId(), block.getClass().getCanonicalName());
} catch (Throwable throwable1) {
return "ID #" + Registry.BLOCK.getKey(block);
return "ID #" + BuiltInRegistries.BLOCK.getKey(block);
}
});
CrashReportCategory.populateBlockDetails(crashreportcategory, level, pos, state);

View File

@ -7,6 +7,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.Entity;
@ -24,6 +25,7 @@ import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.ForgeEventFactory;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@ -40,15 +42,15 @@ public abstract class BaseSpawnerMixin {
@Shadow public SimpleWeightedRandomList<SpawnData> spawnPotentials;
@Shadow public int spawnDelay;
@Shadow public int spawnCount;
@Shadow public SpawnData nextSpawnData;
@Shadow public int spawnRange;
@Shadow public int maxNearbyEntities;
@Shadow protected abstract boolean isNearPlayer(Level p_151344_, BlockPos p_151345_);
@Shadow protected abstract void delay(Level p_151351_, BlockPos p_151352_);
@Shadow protected abstract SpawnData getOrCreateNextSpawnData(@Nullable Level p_254503_, RandomSource p_253892_, BlockPos p_254487_);
// @formatter:on
@Inject(method = "setEntityId", at = @At("RETURN"))
public void arclight$clearMobs(EntityType<?> type, CallbackInfo ci) {
public void arclight$clearMobs(CallbackInfo ci) {
this.spawnPotentials = SimpleWeightedRandomList.empty();
}
@ -67,9 +69,11 @@ public abstract class BaseSpawnerMixin {
--this.spawnDelay;
} else {
boolean flag = false;
RandomSource randomsource = level.getRandom();
SpawnData spawnData = this.getOrCreateNextSpawnData(level, randomsource, pos);
for (int i = 0; i < this.spawnCount; ++i) {
CompoundTag compoundtag = this.nextSpawnData.getEntityToSpawn();
CompoundTag compoundtag = spawnData.getEntityToSpawn();
Optional<EntityType<?>> optional = EntityType.by(compoundtag);
if (optional.isEmpty()) {
this.delay(level, pos);
@ -83,12 +87,12 @@ public abstract class BaseSpawnerMixin {
double d2 = j >= 3 ? listtag.getDouble(2) : (double) pos.getZ() + (level.random.nextDouble() - level.random.nextDouble()) * (double) this.spawnRange + 0.5D;
if (level.noCollision(optional.get().getAABB(d0, d1, d2))) {
BlockPos blockpos = new BlockPos(d0, d1, d2);
if (this.nextSpawnData.getCustomSpawnRules().isPresent()) {
if (spawnData.getCustomSpawnRules().isPresent()) {
if (!optional.get().getCategory().isFriendly() && level.getDifficulty() == Difficulty.PEACEFUL) {
continue;
}
SpawnData.CustomSpawnRules spawndata$customspawnrules = this.nextSpawnData.getCustomSpawnRules().get();
SpawnData.CustomSpawnRules spawndata$customspawnrules = spawnData.getCustomSpawnRules().get();
if (!spawndata$customspawnrules.blockLightLimit().isValueInRange(level.getBrightness(LightLayer.BLOCK, blockpos)) || !spawndata$customspawnrules.skyLightLimit().isValueInRange(level.getBrightness(LightLayer.SKY, blockpos))) {
continue;
}
@ -116,12 +120,12 @@ public abstract class BaseSpawnerMixin {
var res = ForgeEventFactory.canEntitySpawn(mob, level, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this, MobSpawnType.SPAWNER);
if (res == net.minecraftforge.eventbus.api.Event.Result.DENY) continue;
if (res == net.minecraftforge.eventbus.api.Event.Result.DEFAULT) {
if (this.nextSpawnData.getCustomSpawnRules().isEmpty() && !mob.checkSpawnRules(level, MobSpawnType.SPAWNER) || !mob.checkSpawnObstruction(level)) {
if (spawnData.getCustomSpawnRules().isEmpty() && !mob.checkSpawnRules(level, MobSpawnType.SPAWNER) || !mob.checkSpawnObstruction(level)) {
continue;
}
}
if (this.nextSpawnData.getEntityToSpawn().size() == 1 && this.nextSpawnData.getEntityToSpawn().contains("id", 8)) {
if (spawnData.getEntityToSpawn().size() == 1 && spawnData.getEntityToSpawn().contains("id", 8)) {
if (!ForgeEventFactory.doSpecialSpawn(mob, (LevelAccessor) level, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this, MobSpawnType.SPAWNER))
((Mob) entity).finalizeSpawn(level, level.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, null, null);
}

View File

@ -14,12 +14,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(WanderingTraderSpawner.class)
public class WanderingTraderSpawnerMixin {
@Inject(method = "spawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/network/chat/Component;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;"))
@Inject(method = "spawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;)Lnet/minecraft/world/entity/Entity;"))
public void arclight$spawnReason1(ServerLevel serverWorld, CallbackInfoReturnable<Boolean> cir) {
((WorldBridge) serverWorld).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.NATURAL);
}
@Inject(method = "tryToSpawnLlamaFor", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/network/chat/Component;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;"))
@Inject(method = "tryToSpawnLlamaFor", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;)Lnet/minecraft/world/entity/Entity;"))
public void arclight$spawnReason2(ServerLevel serverWorld, WanderingTrader p_242373_2_, int p_242373_3_, CallbackInfo ci) {
((WorldBridge) serverWorld).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.NATURAL);
}

View File

@ -28,7 +28,7 @@ public abstract class PrimaryLevelDataMixin implements WorldInfoBridge {
@Shadow private boolean thundering;
@Shadow private boolean raining;
@Shadow public abstract boolean isDifficultyLocked();
@Shadow private LevelSettings settings;
@Shadow public LevelSettings settings;
@Shadow @Final private Lifecycle worldGenSettingsLifecycle;
// @formatter:on

View File

@ -1,24 +0,0 @@
package io.izzel.arclight.common.mixin.optimization.general;
import net.minecraft.resources.ResourceKey;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Mixin(ResourceKey.class)
public class ResourceKeyMixin_Optimize {
@Redirect(method = "<clinit>", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Collections;synchronizedMap(Ljava/util/Map;)Ljava/util/Map;"))
private static <K, V> Map<K, V> arclight$useHashMap(Map<K, V> m) {
return new ConcurrentHashMap<>();
}
@Redirect(method = "create(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/resources/ResourceKey;",
at = @At(value = "INVOKE", remap = false, target = "Ljava/lang/String;intern()Ljava/lang/String;"))
private static String arclight$dropIntern(String instance) {
return instance;
}
}

View File

@ -19,6 +19,8 @@ import io.izzel.arclight.i18n.ArclightConfig;
import io.izzel.arclight.i18n.conf.EntityPropertySpec;
import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.dedicated.DedicatedServer;
@ -29,10 +31,10 @@ import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.Potions;
import net.minecraft.world.item.crafting.CookingBookCategory;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.dimension.LevelStem;
@ -48,7 +50,7 @@ import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v.CraftCrashReport;
import org.bukkit.craftbukkit.v.CraftStatistic;
import org.bukkit.craftbukkit.v.inventory.CraftCreativeCategory;
import org.bukkit.craftbukkit.v.inventory.CraftRecipe;
import org.bukkit.craftbukkit.v.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.v.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
@ -59,7 +61,6 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.SpawnCategory;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.CreativeCategory;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
@ -67,12 +68,10 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@SuppressWarnings({"ConstantConditions", "deprecation"})
public class BukkitRegistry {
@ -108,9 +107,9 @@ public class BukkitRegistry {
loadBiomes(console);
loadArts();
loadStats();
loadCreativeTab();
loadSpawnCategory();
loadEndDragonPhase();
loadCookingBookCategory();
try {
for (var field : org.bukkit.Registry.class.getFields()) {
if (Modifier.isStatic(field.getModifiers()) && field.get(null) instanceof org.bukkit.Registry.SimpleRegistry<?> registry) {
@ -121,6 +120,22 @@ public class BukkitRegistry {
}
}
private static void loadCookingBookCategory() {
var id = CookingBookCategory.values().length;
var newTypes = new ArrayList<org.bukkit.inventory.recipe.CookingBookCategory>();
for (CookingBookCategory category : CookingBookCategory.values()) {
try {
CraftRecipe.getCategory(category);
} catch (Exception e) {
var name = category.name();
var bukkit = EnumHelper.makeEnum(org.bukkit.inventory.recipe.CookingBookCategory.class, name, id++, List.of(), List.of());
newTypes.add(bukkit);
ArclightMod.LOGGER.debug("Registered {} as cooking category {}", name, bukkit);
}
}
EnumHelper.addEnums(org.bukkit.inventory.recipe.CookingBookCategory.class, newTypes);
}
private static void loadEndDragonPhase() {
var max = EnderDragonPhase.getCount();
var newTypes = new ArrayList<EnderDragon.Phase>();
@ -149,30 +164,6 @@ public class BukkitRegistry {
EnumHelper.addEnums(SpawnCategory.class, newTypes);
}
private static void loadCreativeTab() {
var id = new AtomicInteger(CreativeCategory.values().length);
var newTypes = new ArrayList<CreativeCategory>();
var tabs = CreativeModeTab.TABS;
var map = new HashMap<CreativeModeTab, CreativeCategory>(Unsafe.getStatic(CraftCreativeCategory.class, "NMS_TO_BUKKIT"));
for (var tab : tabs) {
map.computeIfAbsent(tab, k -> {
var name = "MOD_" + k.getId();
var newTab = EnumHelper.makeEnum(CreativeCategory.class, name, id.getAndIncrement(), List.of(), List.of());
newTypes.add(newTab);
ArclightMod.LOGGER.debug("Registered {} as creative tab {}", k, newTab);
return newTab;
});
}
EnumHelper.addEnums(CreativeCategory.class, newTypes);
try {
var field = CraftCreativeCategory.class.getDeclaredField("NMS_TO_BUKKIT");
field.setAccessible(true);
field.set(null, map);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void loadStats() {
int i = Statistic.values().length;
List<Statistic> newTypes = new ArrayList<>();
@ -185,11 +176,11 @@ public class BukkitRegistry {
if (statistic == null) {
String standardName = ResourceLocationUtil.standardize(location);
Statistic.Type type;
if (statType.getRegistry() == Registry.ENTITY_TYPE) {
if (statType.getRegistry() == BuiltInRegistries.ENTITY_TYPE) {
type = Statistic.Type.ENTITY;
} else if (statType.getRegistry() == Registry.BLOCK) {
} else if (statType.getRegistry() == BuiltInRegistries.BLOCK) {
type = Statistic.Type.BLOCK;
} else if (statType.getRegistry() == Registry.ITEM) {
} else if (statType.getRegistry() == BuiltInRegistries.ITEM) {
type = Statistic.Type.ITEM;
} else {
type = Statistic.Type.UNTYPED;
@ -202,7 +193,7 @@ public class BukkitRegistry {
i++;
}
}
for (ResourceLocation location : Registry.CUSTOM_STAT) {
for (ResourceLocation location : BuiltInRegistries.CUSTOM_STAT) {
Statistic statistic = STATS.get(location);
if (statistic == null) {
String standardName = ResourceLocationUtil.standardize(location);
@ -246,7 +237,7 @@ public class BukkitRegistry {
List<Biome> newTypes = new ArrayList<>();
Field key = Arrays.stream(Biome.class.getDeclaredFields()).filter(it -> it.getName().equals("key")).findAny().orElse(null);
long keyOffset = Unsafe.objectFieldOffset(key);
var registry = console.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
var registry = console.registryAccess().registryOrThrow(Registries.BIOME);
for (net.minecraft.world.level.biome.Biome biome : registry) {
var location = registry.getKey(biome);
String name = ResourceLocationUtil.standardize(location);

View File

@ -3,13 +3,13 @@ package io.izzel.arclight.common.mod.util;
import io.izzel.arclight.common.mod.ArclightConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.WorldLoader;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.DataPackConfig;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.bukkit.TreeType;
import org.bukkit.block.BlockState;
@ -19,6 +19,7 @@ import org.bukkit.event.entity.EntityPotionEffectEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Stack;
public class ArclightCaptures {
@ -252,17 +253,17 @@ public class ArclightCaptures {
}
}
private static transient DataPackConfig datapackCodec;
private static transient WorldLoader.DataLoadContext dataLoadContext;
public static void captureDatapackConfig(DataPackConfig codec) {
datapackCodec = codec;
public static void captureDataLoadContext(WorldLoader.DataLoadContext context) {
dataLoadContext = context;
}
public static DataPackConfig getDatapackConfig() {
public static WorldLoader.DataLoadContext getDataLoadContext() {
try {
return datapackCodec;
return Objects.requireNonNull(dataLoadContext, "dataLoadContext");
} finally {
datapackCodec = null;
dataLoadContext = null;
}
}

View File

@ -23,7 +23,7 @@ public class ArclightPingEvent extends ServerListPingEvent {
private final Object[] players;
public ArclightPingEvent(Connection networkManager, MinecraftServer server) {
super(((NetworkManagerBridge) networkManager).bridge$getHostname(), ((InetSocketAddress) networkManager.getRemoteAddress()).getAddress(), server.getMotd(), server.previewsChat(), server.getPlayerList().getMaxPlayers());
super(((NetworkManagerBridge) networkManager).bridge$getHostname(), ((InetSocketAddress) networkManager.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers());
this.icon = ((CraftServer) Bukkit.getServer()).getServerIcon();
this.players = server.getPlayerList().players.toArray();
}

View File

@ -10,7 +10,7 @@ import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.storage.DerivedLevelData;
import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
@ -23,9 +23,9 @@ public class DelegateWorldInfo extends PrimaryLevelData {
private final DerivedLevelData derivedWorldInfo;
public DelegateWorldInfo(LevelSettings worldSettings, WorldGenSettings generatorSettings, Lifecycle lifecycle, DerivedLevelData derivedWorldInfo) {
super(worldSettings, generatorSettings, lifecycle);
this.derivedWorldInfo = derivedWorldInfo;
public DelegateWorldInfo(LevelSettings p_251081_, WorldOptions p_251666_, SpecialWorldProperty p_252268_, Lifecycle p_251714_, DerivedLevelData derivedLevelData) {
super(p_251081_, p_251666_, p_252268_, p_251714_);
this.derivedWorldInfo = derivedLevelData;
}
@Override
@ -234,7 +234,7 @@ public class DelegateWorldInfo extends PrimaryLevelData {
}
public static DelegateWorldInfo wrap(DerivedLevelData worldInfo) {
return new DelegateWorldInfo(worldSettings(worldInfo), generatorSettings(worldInfo), lifecycle(worldInfo), worldInfo);
return new DelegateWorldInfo(worldSettings(worldInfo), generatorSettings(worldInfo), specialWorldProperty(worldInfo), lifecycle(worldInfo), worldInfo);
}
private static LevelSettings worldSettings(ServerLevelData worldInfo) {
@ -245,14 +245,25 @@ public class DelegateWorldInfo extends PrimaryLevelData {
}
}
private static WorldGenSettings generatorSettings(ServerLevelData worldInfo) {
private static WorldOptions generatorSettings(ServerLevelData worldInfo) {
if (worldInfo instanceof PrimaryLevelData) {
return ((PrimaryLevelData) worldInfo).worldGenSettings();
return ((PrimaryLevelData) worldInfo).worldGenOptions();
} else {
return generatorSettings(((DerivedWorldInfoBridge) worldInfo).bridge$getDelegate());
}
}
private static SpecialWorldProperty specialWorldProperty(ServerLevelData serverLevelData) {
if (serverLevelData instanceof PrimaryLevelData) {
return ((PrimaryLevelData) serverLevelData).isFlatWorld() ?
SpecialWorldProperty.FLAT : (
((PrimaryLevelData) serverLevelData).isDebugWorld() ? SpecialWorldProperty.DEBUG : SpecialWorldProperty.NONE
);
} else {
return specialWorldProperty(((DerivedWorldInfoBridge) serverLevelData).bridge$getDelegate());
}
}
private static Lifecycle lifecycle(ServerLevelData worldInfo) {
if (worldInfo instanceof PrimaryLevelData) {
return ((WorldInfoBridge) worldInfo).bridge$getLifecycle();

View File

@ -1,3 +1,5 @@
# Arclight 1.19.3
public net.minecraft.server.MinecraftServer$TimeProfiler <init>(JI)V # TimeProfiler
# Arclight 1.18.2
public-f net.minecraft.server.ReloadableServerResources f_206847_ # commands
public net.minecraft.world.level.chunk.ChunkGenerator f_212255_
@ -538,3 +540,21 @@ public net.minecraft.world.entity.animal.allay.Allay m_239811_()V # resetDuplica
public net.minecraft.world.entity.animal.allay.Allay m_218324_()Z # canDuplicate
public net.minecraft.world.entity.projectile.FireworkRocketEntity f_37022_ # life
public net.minecraft.world.entity.projectile.FireworkRocketEntity f_37024_ # attachedToEntity
# Bukkit 1.19.3
public net.minecraft.server.MinecraftServer$ReloadableResources
public net.minecraft.server.dedicated.DedicatedServerProperties$WorldDimensionData
public net.minecraft.server.level.ServerLevel m_261178_(Lnet/minecraft/world/level/entity/EntityTypeTest;Ljava/util/function/Predicate;Ljava/util/List;I)V
public net.minecraft.server.Main m_195488_(Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lnet/minecraft/core/Registry;)V
public net.minecraft.server.WorldLoader m_245736_(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/server/RegistryLayer;Ljava/util/List;)Lnet/minecraft/core/LayeredRegistryAccess;
public net.minecraft.util.datafix.fixes.BlockStateData m_14942_(ILjava/lang/String;[Ljava/lang/String;)V
public net.minecraft.world.entity.animal.TropicalFish m_30042_()I
public net.minecraft.world.entity.animal.TropicalFish m_30056_(I)V
public net.minecraft.world.entity.decoration.ItemFrame f_31757_
public net.minecraft.world.entity.decoration.ItemFrame f_31758_
public net.minecraft.world.entity.projectile.FireworkRocketEntity f_37024_
public net.minecraft.world.entity.projectile.FireworkRocketEntity f_37022_
public net.minecraft.world.item.context.UseOnContext <init>(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)V
public net.minecraft.world.level.block.entity.ChiseledBookShelfBlockEntity f_262317_
public net.minecraft.world.level.chunk.ChunkGenerator f_223021_
public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData f_256718_
public-f net.minecraft.world.level.saveddata.maps.MapItemSavedData f_256789_

View File

@ -1,5 +1,5 @@
modLoader="javafml"
loaderVersion="[24,]"
loaderVersion="[44,]"
license="GNU GENERAL PUBLIC LICENSE Version 3"
[[mods]]

View File

@ -16,7 +16,6 @@
"CraftBlockMixin",
"CraftBlockStateMixin",
"CraftConsoleCommandSenderMixin",
"CraftCreativeCategoryMixin",
"CraftEntityMixin",
"CraftEventFactoryMixin",
"CraftHumanEntityMixin",

View File

@ -52,7 +52,7 @@
"server.PlayerAdvancementsMixin",
"server.ServerFunctionManagerMixin",
"server.ServerScoreboardMixin",
"server.WorldLoader_PackConfigMixin",
"server.WorldLoaderMixin",
"server.commands.EffectCommandMixin",
"server.commands.GameRuleCommandMixin",
"server.commands.ReloadCommandMixin",
@ -133,6 +133,7 @@
"world.entity.animal.Bee_HurtByOtherGoalMixin",
"world.entity.animal.BeeMixin",
"world.entity.animal.BucketableMixin",
"world.entity.animal.Cat_CatRelaxOnOwnerGoalMixin",
"world.entity.animal.ChickenMixin",
"world.entity.animal.CowMixin",
"world.entity.animal.DolphinEntity_SwimWithPlayerGoalMixin",
@ -312,7 +313,7 @@
"world.item.crafting.BlastingRecipeMixin",
"world.item.crafting.CampfireCookingRecipeMixin",
"world.item.crafting.CustomRecipeMixin",
"world.item.crafting.FurnaceRecipeMixin",
"world.item.crafting.SmeltingRecipeMixin",
"world.item.crafting.IngredientMixin",
"world.item.crafting.RecipeManagerMixin",
"world.item.crafting.RecipeMixin",
@ -325,8 +326,8 @@
"world.item.enchantment.DamageEnchantmentMixin",
"world.item.enchantment.FrostWalkerEnchantmentMixin",
"world.level.LevelMixin",
"world.level.block.BambooBlockMixin",
"world.level.block.BambooSaplingBlockMixin",
"world.level.block.BambooStalkBlockMixin",
"world.level.block.BaseFireBlockMixin",
"world.level.block.BasePressurePlateBlockMixin",
"world.level.block.BedBlockMixin",
@ -434,8 +435,9 @@
"world.level.block.entity.BeehiveBlockEntityMixin",
"world.level.block.entity.BlockEntityMixin",
"world.level.block.entity.BrewingStandBlockEntityMixin",
"world.level.block.entity.CampfireTileEntityMixin",
"world.level.block.entity.CampfireBlockEntityMixin",
"world.level.block.entity.ChestBlockEntityMixin",
"world.level.block.entity.ChiseledBookShelfBlockEntityMixin",
"world.level.block.entity.CommandBlockLogicMixin",
"world.level.block.entity.CommandBlockTileEntity1Mixin",
"world.level.block.entity.ConduitBlockEntityMixin",
@ -461,6 +463,7 @@
"world.level.chunk.storage.ChunkSerializerMixin",
"world.level.chunk.storage.RegionFileCacheMixin",
"world.level.entity.PersistentEntitySectionManagerMixin",
"world.level.gameevent.GameEventDispatcherMixin",
"world.level.gameevent.vibrations.VibrationListenerMixin",
"world.level.levelgen.structure.templatesystem.StructureTemplateMixin",
"world.level.portal.PortalForcerMixin",

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