1.17: mixins are done

This commit is contained in:
IzzelAliz 2021-07-26 14:44:22 +08:00
parent f83cf94337
commit bc714cafb3
124 changed files with 1434 additions and 1648 deletions

View File

@ -50,7 +50,7 @@ dependencies {
implementation "org.spigotmc:spigot-api:$minecraftVersion-R0.1-SNAPSHOT@jar" implementation "org.spigotmc:spigot-api:$minecraftVersion-R0.1-SNAPSHOT@jar"
implementation 'org.jetbrains:annotations:19.0.0' implementation 'org.jetbrains:annotations:19.0.0'
implementation 'org.spongepowered:mixin:0.8.2' implementation 'org.spongepowered:mixin:0.8.3'
annotationProcessor 'org.spongepowered:mixin:0.8.2:processor' annotationProcessor 'org.spongepowered:mixin:0.8.2:processor'
implementation 'com.github.ArclightTeam:mixin-tools:1.0.0' implementation 'com.github.ArclightTeam:mixin-tools:1.0.0'

View File

@ -1,13 +1,16 @@
package io.izzel.arclight.common.bridge.tileentity; package io.izzel.arclight.common.bridge.tileentity;
import java.util.List; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3; import java.util.List;
public interface AbstractFurnaceTileEntityBridge { public interface AbstractFurnaceTileEntityBridge {
List<Recipe<?>> bridge$dropExp(Level world, Vec3 pos, Player entity, ItemStack itemStack, int amount); List<Recipe<?>> bridge$dropExp(ServerPlayer entity, ItemStack itemStack, int amount);
int bridge$getBurnDuration(ItemStack stack);
boolean bridge$isLit();
} }

View File

@ -7,4 +7,6 @@ public interface ChunkHolderBridge {
int bridge$getOldTicketLevel(); int bridge$getOldTicketLevel();
LevelChunk bridge$getFullChunk(); LevelChunk bridge$getFullChunk();
LevelChunk bridge$getFullChunkUnchecked();
} }

View File

@ -1,12 +1,13 @@
package io.izzel.arclight.common.bridge.world.server; package io.izzel.arclight.common.bridge.world.server;
import io.izzel.arclight.common.mod.util.ArclightCallbackExecutor; import io.izzel.arclight.common.mod.util.ArclightCallbackExecutor;
import java.util.function.BooleanSupplier;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
public interface ChunkManagerBridge { import java.util.function.BooleanSupplier;
public interface ChunkMapBridge {
void bridge$tick(BooleanSupplier hasMoreTime); void bridge$tick(BooleanSupplier hasMoreTime);

View File

@ -27,9 +27,4 @@ public interface ServerWorldBridge extends WorldBridge {
boolean bridge$addAllEntitiesSafely(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason); boolean bridge$addAllEntitiesSafely(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason);
LevelStorageSource.LevelStorageAccess bridge$getConvertable(); LevelStorageSource.LevelStorageAccess bridge$getConvertable();
interface Hack {
BlockEntity getTileEntity(BlockPos blockPos);
}
} }

View File

@ -1,8 +1,15 @@
package io.izzel.arclight.common.bridge.world.storage; package io.izzel.arclight.common.bridge.world.storage;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import org.bukkit.craftbukkit.v.map.CraftMapView; import org.bukkit.craftbukkit.v.map.CraftMapView;
import java.util.List;
public interface MapDataBridge { public interface MapDataBridge {
CraftMapView bridge$getMapView(); CraftMapView bridge$getMapView();
void bridge$setId(String id);
List<MapItemSavedData.HoldingPlayer> bridge$getCarriedBy();
} }

View File

@ -60,11 +60,10 @@ public abstract class CraftItemStackMixin implements CraftItemStackBridge {
if (stack == (Object) this) { if (stack == (Object) this) {
return true; return true;
} }
if (!(stack instanceof CraftItemStack)) { if (!(stack instanceof CraftItemStack that)) {
return stack.getClass() == org.bukkit.inventory.ItemStack.class && stack.isSimilar((org.bukkit.inventory.ItemStack) (Object) this); return stack.getClass() == org.bukkit.inventory.ItemStack.class && stack.isSimilar((org.bukkit.inventory.ItemStack) (Object) this);
} }
CraftItemStack that = (CraftItemStack) stack;
if (handle == ((CraftItemStackBridge) (Object) that).bridge$getHandle()) { if (handle == ((CraftItemStackBridge) (Object) that).bridge$getHandle()) {
return true; return true;
} }

View File

@ -5,7 +5,6 @@ import com.mojang.brigadier.StringReader;
import io.izzel.arclight.common.bridge.bukkit.CraftServerBridge; import io.izzel.arclight.common.bridge.bukkit.CraftServerBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.server.ArclightServer;
import jline.console.ConsoleReader;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.dedicated.DedicatedPlayerList; import net.minecraft.server.dedicated.DedicatedPlayerList;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
@ -37,7 +36,6 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -72,19 +70,6 @@ public abstract class CraftServerMixin implements CraftServerBridge {
return "Arclight"; return "Arclight";
} }
/**
* @author IzzelAliz
* @reason
*/
@Overwrite(remap = false)
public ConsoleReader getReader() {
try {
return new ConsoleReader();
} catch (IOException e) {
return null;
}
}
@Override @Override
public void bridge$setPlayerList(PlayerList playerList) { public void bridge$setPlayerList(PlayerList playerList) {
this.playerList = (DedicatedPlayerList) playerList; this.playerList = (DedicatedPlayerList) playerList;

View File

@ -1,7 +1,8 @@
package io.izzel.arclight.common.mixin.core.util.text; package io.izzel.arclight.common.mixin.core.network.chat;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import io.izzel.arclight.common.bridge.util.text.ITextComponentBridge; import io.izzel.arclight.common.bridge.util.text.ITextComponentBridge;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -10,10 +11,9 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
import net.minecraft.network.chat.Component;
@Mixin(Component.class) @Mixin(Component.class)
public interface ITextComponentMixin extends ITextComponentBridge, Iterable<Component> { public interface ComponentMixin extends ITextComponentBridge, Iterable<Component> {
// @formatter:off // @formatter:off
@Shadow List<Component> getSiblings(); @Shadow List<Component> getSiblings();

View File

@ -1,15 +1,15 @@
package io.izzel.arclight.common.mixin.core.util.text; package io.izzel.arclight.common.mixin.core.network.chat;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.HoverEvent;
import net.minecraft.network.chat.Style; import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor; import net.minecraft.network.chat.TextColor;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
@Mixin(Style.class) @Mixin(Style.class)
public class StyleMixin { public class StyleMixin {

View File

@ -1,5 +1,7 @@
package io.izzel.arclight.common.mixin.core.util.text; package io.izzel.arclight.common.mixin.core.network.chat;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextColor;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Mutable;
@ -9,11 +11,9 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextColor;
@Mixin(TextColor.class) @Mixin(TextColor.class)
public class ColorMixin { public class TextColorMixin {
// @formatter:off // @formatter:off
@Shadow @Final @Mutable @Nullable public String name; @Shadow @Final @Mutable @Nullable public String name;

View File

@ -1,6 +1,9 @@
package io.izzel.arclight.common.mixin.core.network.protocol.game; package io.izzel.arclight.common.mixin.core.network.protocol.game;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.minecraft.network.protocol.game.ServerGamePacketListener;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -9,13 +12,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import net.minecraft.network.protocol.game.ServerGamePacketListener;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
@Mixin(ServerboundChatPacket.class) @Mixin(ServerboundChatPacket.class)
public class CChatMessagePacketMixin { public class CChatMessagePacketMixin {
@Shadow private String message; @Shadow @Final private String message;
private static final ExecutorService executors = Executors.newCachedThreadPool( private static final ExecutorService executors = Executors.newCachedThreadPool(
new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build() new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()

View File

@ -1,13 +1,15 @@
package io.izzel.arclight.common.mixin.core.network.protocol.game; package io.izzel.arclight.common.mixin.core.network.protocol.game;
import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; import net.minecraft.network.protocol.game.ServerboundContainerClosePacket;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@Mixin(ServerboundContainerClosePacket.class) @Mixin(ServerboundContainerClosePacket.class)
public class CCloseWindowPacketMixin { public class CCloseWindowPacketMixin {
@Shadow private int containerId; @Shadow @Final @Mutable private int containerId;
public void arclight$constructor() { public void arclight$constructor() {
throw new RuntimeException(); throw new RuntimeException();

View File

@ -1,16 +1,16 @@
package io.izzel.arclight.common.mixin.core.util; package io.izzel.arclight.common.mixin.core.server;
import io.izzel.arclight.api.Unsafe;
import net.minecraft.server.Bootstrap;
import org.bukkit.craftbukkit.v.util.CraftLegacy; import org.bukkit.craftbukkit.v.util.CraftLegacy;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import io.izzel.arclight.api.Unsafe;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import net.minecraft.server.Bootstrap;
@Mixin(Bootstrap.class) @Mixin(Bootstrap.class)
public class BootstrapMixin { public class BootstrapMixin {

View File

@ -1,10 +1,18 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.world.chunk.ChunkBridge; import io.izzel.arclight.common.bridge.world.chunk.ChunkBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkHolderBridge; import io.izzel.arclight.common.bridge.world.server.ChunkHolderBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkManagerBridge; import io.izzel.arclight.common.bridge.world.server.ChunkMapBridge;
import io.izzel.arclight.common.mod.ArclightMod; import io.izzel.arclight.common.mod.ArclightMod;
import it.unimi.dsi.fastutil.shorts.ShortSet;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -16,12 +24,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import net.minecraft.server.level.ChunkHolder; import java.util.concurrent.Executor;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
@Mixin(ChunkHolder.class) @Mixin(ChunkHolder.class)
public abstract class ChunkHolderMixin implements ChunkHolderBridge { public abstract class ChunkHolderMixin implements ChunkHolderBridge {
@ -29,7 +32,8 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
// @formatter:off // @formatter:off
@Shadow public int oldTicketLevel; @Shadow public int oldTicketLevel;
@Shadow public abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getFutureIfPresentUnchecked(ChunkStatus p_219301_1_); @Shadow public abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getFutureIfPresentUnchecked(ChunkStatus p_219301_1_);
@Shadow @Final private ChunkPos pos; @Shadow @Final ChunkPos pos;
@Shadow @Final private ShortSet[] changedBlocksPerSection;
@Override @Accessor("oldTicketLevel") public abstract int bridge$getOldTicketLevel(); @Override @Accessor("oldTicketLevel") public abstract int bridge$getOldTicketLevel();
// @formatter:on // @formatter:on
@ -37,9 +41,13 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
if (!ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { if (!ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
return null; // note: using oldTicketLevel for isLoaded checks return null; // note: using oldTicketLevel for isLoaded checks
} }
return this.getFullChunkUnchecked();
}
public LevelChunk getFullChunkUnchecked() {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL);
Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = statusFuture.getNow(null); Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = statusFuture.getNow(null);
return either == null ? null : (LevelChunk) either.left().orElse(null); return (either == null) ? null : (LevelChunk) either.left().orElse(null);
} }
@Override @Override
@ -47,16 +55,27 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
return this.getFullChunk(); return this.getFullChunk();
} }
@Override
public LevelChunk bridge$getFullChunkUnchecked() {
return this.getFullChunkUnchecked();
}
@Inject(method = "blockChanged", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/server/level/ChunkHolder;changedBlocksPerSection:[Lit/unimi/dsi/fastutil/shorts/ShortSet;"))
private void arclight$outOfBound(BlockPos pos, CallbackInfo ci, int i) {
if (i < 0 || i >= this.changedBlocksPerSection.length) return;
}
@Inject(method = "updateFutures", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 0), @Inject(method = "updateFutures", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 0),
locals = LocalCapture.CAPTURE_FAILHARD) locals = LocalCapture.CAPTURE_FAILHARD)
public void arclight$onChunkUnload(ChunkMap chunkManager, CallbackInfo ci, ChunkStatus chunkStatus, public void arclight$onChunkUnload(ChunkMap chunkManager, Executor executor, CallbackInfo ci, ChunkStatus chunkStatus,
ChunkStatus chunkStatus1, boolean flag, boolean flag1, ChunkStatus chunkStatus1, boolean flag, boolean flag1,
ChunkHolder.FullChunkStatus locationType, ChunkHolder.FullChunkStatus locationType1) { ChunkHolder.FullChunkStatus locationType, ChunkHolder.FullChunkStatus locationType1) {
if (locationType.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !locationType1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { if (locationType.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !locationType1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
LevelChunk chunk = (LevelChunk) either.left().orElse(null); LevelChunk chunk = (LevelChunk) either.left().orElse(null);
if (chunk != null) { if (chunk != null) {
((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().execute(() -> { ((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().execute(() -> {
chunk.setUnsaved(true); chunk.setUnsaved(true);
((ChunkBridge) chunk).bridge$unloadCallback(); ((ChunkBridge) chunk).bridge$unloadCallback();
}); });
@ -68,19 +87,19 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
}); });
// Run callback right away if the future was already done // Run callback right away if the future was already done
((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().run(); ((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().run();
} }
} }
@Inject(method = "updateFutures", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) @Inject(method = "updateFutures", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD)
public void arclight$onChunkLoad(ChunkMap chunkManager, CallbackInfo ci, ChunkStatus chunkStatus, public void arclight$onChunkLoad(ChunkMap chunkManager, Executor executor, CallbackInfo ci, ChunkStatus chunkStatus,
ChunkStatus chunkStatus1, boolean flag, boolean flag1, ChunkStatus chunkStatus1, boolean flag, boolean flag1,
ChunkHolder.FullChunkStatus locationType, ChunkHolder.FullChunkStatus locationType1) { ChunkHolder.FullChunkStatus locationType, ChunkHolder.FullChunkStatus locationType1) {
if (!locationType.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && locationType1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { if (!locationType.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && locationType1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
LevelChunk chunk = (LevelChunk) either.left().orElse(null); LevelChunk chunk = (LevelChunk) either.left().orElse(null);
if (chunk != null) { if (chunk != null) {
((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().execute( ((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().execute(
((ChunkBridge) chunk)::bridge$loadCallback ((ChunkBridge) chunk)::bridge$loadCallback
); );
} }
@ -90,7 +109,7 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
return null; return null;
}); });
((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().run(); ((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().run();
} }
} }
} }

View File

@ -1,8 +1,15 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkManagerBridge; import io.izzel.arclight.common.bridge.world.server.ChunkMapBridge;
import io.izzel.arclight.common.mod.util.ArclightCallbackExecutor; import io.izzel.arclight.common.mod.util.ArclightCallbackExecutor;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Mutable;
@ -12,17 +19,10 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
@Mixin(ChunkMap.class) @Mixin(ChunkMap.class)
public abstract class ChunkManagerMixin implements ChunkManagerBridge { public abstract class ChunkMapMixin implements ChunkMapBridge {
// @formatter:off // @formatter:off
@Shadow @Nullable protected abstract ChunkHolder getUpdatingChunkIfPresent(long chunkPosIn); @Shadow @Nullable protected abstract ChunkHolder getUpdatingChunkIfPresent(long chunkPosIn);

View File

@ -1,6 +1,10 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import io.izzel.arclight.common.bridge.world.TrackedEntityBridge; import io.izzel.arclight.common.bridge.world.TrackedEntityBridge;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -9,16 +13,12 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Set; import java.util.Set;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
@Mixin(ChunkMap.TrackedEntity.class) @Mixin(ChunkMap.TrackedEntity.class)
public abstract class ChunkManager_EntityTrackerMixin { public abstract class ChunkMap_TrackedEntityMixin {
// @formatter:off // @formatter:off
@Shadow @Final private ServerEntity serverEntity; @Shadow @Final ServerEntity serverEntity;
@Shadow @Final public Set<ServerPlayer> seenBy; @Shadow @Final public Set<ServerPlayer> seenBy;
// @formatter:on // @formatter:on

View File

@ -1,21 +1,10 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkHolderBridge; import io.izzel.arclight.common.bridge.world.server.ChunkHolderBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkManagerBridge; import io.izzel.arclight.common.bridge.world.server.ChunkMapBridge;
import io.izzel.arclight.common.bridge.world.server.ServerChunkProviderBridge; import io.izzel.arclight.common.bridge.world.server.ServerChunkProviderBridge;
import io.izzel.arclight.common.bridge.world.server.TicketManagerBridge; import io.izzel.arclight.common.bridge.world.server.TicketManagerBridge;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.DistanceManager;
@ -27,21 +16,32 @@ import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelData;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.util.function.Consumer; import java.util.function.Consumer;
@Mixin(ServerChunkCache.class) @Mixin(ServerChunkCache.class)
public abstract class ServerChunkProviderMixin implements ServerChunkProviderBridge { public abstract class ServerChunkCacheMixin implements ServerChunkProviderBridge {
// @formatter:off // @formatter:off
@Shadow public abstract void save(boolean flush); @Shadow public abstract void save(boolean flush);
@Shadow @Final private ThreadedLevelLightEngine lightEngine; @Shadow @Final ThreadedLevelLightEngine lightEngine;
@Shadow @Final public ChunkMap chunkMap; @Shadow @Final public ChunkMap chunkMap;
@Shadow @Final public ServerLevel level; @Shadow @Final public ServerLevel level;
@Shadow @Final private DistanceManager distanceManager; @Shadow @Final private DistanceManager distanceManager;
@Shadow protected abstract void clearCache(); @Shadow protected abstract void clearCache();
@Shadow @Nullable protected abstract ChunkHolder getVisibleChunkIfPresent(long chunkPosIn); @Shadow @Nullable protected abstract ChunkHolder getVisibleChunkIfPresent(long chunkPosIn);
@Shadow protected abstract boolean runDistanceManagerUpdates(); @Shadow abstract boolean runDistanceManagerUpdates();
@Shadow protected abstract boolean chunkAbsent(@Nullable ChunkHolder chunkHolderIn, int p_217224_2_); @Shadow protected abstract boolean chunkAbsent(@Nullable ChunkHolder chunkHolderIn, int p_217224_2_);
@Shadow public boolean spawnEnemies; @Shadow public boolean spawnEnemies;
@Shadow public boolean spawnFriendlies; @Shadow public boolean spawnFriendlies;
@ -52,10 +52,18 @@ public abstract class ServerChunkProviderMixin implements ServerChunkProviderBri
// @formatter:on // @formatter:on
public boolean isChunkLoaded(final int chunkX, final int chunkZ) { public boolean isChunkLoaded(final int chunkX, final int chunkZ) {
final ChunkHolder chunk = ((ChunkManagerBridge) this.chunkMap).bridge$chunkHolderAt(ChunkPos.asLong(chunkX, chunkZ)); ChunkHolder chunk = ((ChunkMapBridge) this.chunkMap).bridge$chunkHolderAt(ChunkPos.asLong(chunkX, chunkZ));
return chunk != null && ((ChunkHolderBridge) chunk).bridge$getFullChunk() != null; return chunk != null && ((ChunkHolderBridge) chunk).bridge$getFullChunk() != null;
} }
public LevelChunk getChunkUnchecked(int chunkX, int chunkZ) {
ChunkHolder chunk = ((ChunkMapBridge) this.chunkMap).bridge$chunkHolderAt(ChunkPos.asLong(chunkX, chunkZ));
if (chunk == null) {
return null;
}
return ((ChunkHolderBridge) chunk).bridge$getFullChunkUnchecked();
}
@Override @Override
public boolean bridge$isChunkLoaded(int x, int z) { public boolean bridge$isChunkLoaded(int x, int z) {
return isChunkLoaded(x, z); return isChunkLoaded(x, z);
@ -64,12 +72,12 @@ public abstract class ServerChunkProviderMixin implements ServerChunkProviderBri
@Override @Override
public void bridge$setChunkGenerator(ChunkGenerator chunkGenerator) { public void bridge$setChunkGenerator(ChunkGenerator chunkGenerator) {
this.generator = chunkGenerator; this.generator = chunkGenerator;
((ChunkManagerBridge) this.chunkMap).bridge$setChunkGenerator(chunkGenerator); ((ChunkMapBridge) this.chunkMap).bridge$setChunkGenerator(chunkGenerator);
} }
@Override @Override
public void bridge$setViewDistance(int viewDistance) { public void bridge$setViewDistance(int viewDistance) {
((ChunkManagerBridge) this.chunkMap).bridge$setViewDistance(viewDistance); ((ChunkMapBridge) this.chunkMap).bridge$setViewDistance(viewDistance);
} }
@ModifyVariable(method = "getChunkFutureMainThread", index = 4, at = @At("HEAD")) @ModifyVariable(method = "getChunkFutureMainThread", index = 4, at = @At("HEAD"))
@ -113,7 +121,7 @@ public abstract class ServerChunkProviderMixin implements ServerChunkProviderBri
((TicketManagerBridge) this.distanceManager).bridge$tick(); ((TicketManagerBridge) this.distanceManager).bridge$tick();
this.bridge$tickDistanceManager(); this.bridge$tickDistanceManager();
this.level.getProfiler().popPush("unload"); this.level.getProfiler().popPush("unload");
((ChunkManagerBridge) this.chunkMap).bridge$tick(() -> true); ((ChunkMapBridge) this.chunkMap).bridge$tick(() -> true);
this.level.getProfiler().pop(); this.level.getProfiler().pop();
this.clearCache(); this.clearCache();
} }

View File

@ -1,7 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import io.izzel.arclight.common.bridge.server.MinecraftServerBridge; import io.izzel.arclight.common.bridge.server.MinecraftServerBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkManagerBridge; import io.izzel.arclight.common.bridge.world.server.ChunkMapBridge;
import io.izzel.arclight.common.bridge.world.server.ServerChunkProviderBridge; import io.izzel.arclight.common.bridge.world.server.ServerChunkProviderBridge;
import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.server.ArclightServer;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
@ -12,13 +12,13 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@Mixin(targets = "net.minecraft.server.level.ServerChunkCache$MainThreadExecutor") @Mixin(targets = "net.minecraft.server.level.ServerChunkCache$MainThreadExecutor")
public abstract class ServerChunkProvider_ChunkExecutorMixin extends BlockableEventLoop<Runnable> { public abstract class ServerChunkCache_MainThreadExecutorMixin extends BlockableEventLoop<Runnable> {
// @formatter:off // @formatter:off
@Shadow(aliases = {"this$0", "field_213181_a"}, remap = false) @Final private ServerChunkCache outer; @Shadow(aliases = {"this$0", "f_8491_"}, remap = false) @Final private ServerChunkCache outer;
// @formatter:on // @formatter:on
protected ServerChunkProvider_ChunkExecutorMixin(String nameIn) { protected ServerChunkCache_MainThreadExecutorMixin(String nameIn) {
super(nameIn); super(nameIn);
} }
@ -27,7 +27,7 @@ public abstract class ServerChunkProvider_ChunkExecutorMixin extends BlockableEv
* @reason * @reason
*/ */
@Overwrite @Overwrite
protected boolean pollTask() { public boolean pollTask() {
try { try {
if (((ServerChunkProviderBridge) outer).bridge$tickDistanceManager()) { if (((ServerChunkProviderBridge) outer).bridge$tickDistanceManager()) {
return true; return true;
@ -36,7 +36,7 @@ public abstract class ServerChunkProvider_ChunkExecutorMixin extends BlockableEv
return super.pollTask(); return super.pollTask();
} }
} finally { } finally {
((ChunkManagerBridge) outer.chunkMap).bridge$getCallbackExecutor().run(); ((ChunkMapBridge) outer.chunkMap).bridge$getCallbackExecutor().run();
((MinecraftServerBridge) ArclightServer.getMinecraftServer()).bridge$drainQueuedTasks(); ((MinecraftServerBridge) ArclightServer.getMinecraftServer()).bridge$drainQueuedTasks();
} }
} }

View File

@ -1,28 +1,9 @@
package io.izzel.arclight.common.mixin.core.world; package io.izzel.arclight.common.mixin.core.server.level;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.TrackedEntityBridge; import io.izzel.arclight.common.bridge.world.TrackedEntityBridge;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.bukkit.util.Vector;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundAddMobPacket; import net.minecraft.network.protocol.game.ClientboundAddMobPacket;
import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket; import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
@ -52,9 +33,28 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.MapItem; import net.minecraft.world.item.MapItem;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.bukkit.util.Vector;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@Mixin(ServerEntity.class) @Mixin(ServerEntity.class)
public abstract class TrackedEntityMixin implements TrackedEntityBridge { public abstract class ServerEntityMixin implements TrackedEntityBridge {
// @formatter:off // @formatter:off
@Shadow @Final private Entity entity; @Shadow @Final private Entity entity;
@ -111,16 +111,17 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
this.lastPassengers = list; this.lastPassengers = list;
this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity));
} }
if (this.entity instanceof ItemFrame) { if (this.entity instanceof ItemFrame itemFrame) {
ItemFrame itemframeentity = (ItemFrame) this.entity; ItemStack itemstack = itemFrame.getItem();
ItemStack itemstack = itemframeentity.getItem(); if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) {
MapItemSavedData mapdata = MapItem.getOrCreateSavedData(itemstack, this.level); MapItemSavedData mapdata = MapItem.getSavedData(itemstack, this.level);
if (this.tickCount % 10 == 0 && mapdata != null && itemstack.getItem() instanceof MapItem) { if (mapdata != null) {
for (ServerPlayer serverplayerentity : this.trackedPlayers) { for (ServerPlayer serverplayerentity : this.trackedPlayers) {
mapdata.tickCarriedBy(serverplayerentity, itemstack); mapdata.tickCarriedBy(serverplayerentity, itemstack);
Packet<?> ipacket = ((MapItem) itemstack.getItem()).getUpdatePacket(itemstack, this.level, serverplayerentity); Packet<?> ipacket = ((MapItem) itemstack.getItem()).getUpdatePacket(itemstack, this.level, serverplayerentity);
if (ipacket != null) { if (ipacket != null) {
serverplayerentity.connection.send(ipacket); serverplayerentity.connection.send(ipacket);
}
} }
} }
} }
@ -128,8 +129,8 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
} }
if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) { if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) {
if (this.entity.isPassenger()) { if (this.entity.isPassenger()) {
int i1 = Mth.floor(this.entity.yRot * 256.0F / 360.0F); int i1 = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F);
int l1 = Mth.floor(this.entity.xRot * 256.0F / 360.0F); int l1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F);
boolean flag2 = Math.abs(i1 - this.yRotp) >= 1 || Math.abs(l1 - this.xRotp) >= 1; boolean flag2 = Math.abs(i1 - this.yRotp) >= 1 || Math.abs(l1 - this.xRotp) >= 1;
if (flag2) { if (flag2) {
this.broadcast.accept(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) i1, (byte) l1, this.entity.isOnGround())); this.broadcast.accept(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) i1, (byte) l1, this.entity.isOnGround()));
@ -141,8 +142,8 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
this.wasRiding = true; this.wasRiding = true;
} else { } else {
++this.teleportDelay; ++this.teleportDelay;
int l = Mth.floor(this.entity.yRot * 256.0F / 360.0F); int l = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F);
int k1 = Mth.floor(this.entity.xRot * 256.0F / 360.0F); int k1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F);
Vec3 vector3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); Vec3 vector3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp));
boolean flag3 = vector3d.lengthSqr() >= (double) 7.6293945E-6F; boolean flag3 = vector3d.lengthSqr() >= (double) 7.6293945E-6F;
Packet<?> ipacket1 = null; Packet<?> ipacket1 = null;
@ -239,7 +240,7 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
ServerPlayer player = arclight$player; ServerPlayer player = arclight$player;
arclight$player = null; arclight$player = null;
Mob entityinsentient; Mob entityinsentient;
if (this.entity.removed) { if (this.entity.isRemoved()) {
return; return;
} }
Packet<?> packet = this.entity.getAddEntityPacket(); Packet<?> packet = this.entity.getAddEntityPacket();
@ -249,15 +250,15 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
consumer.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.entity.getEntityData(), true)); consumer.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.entity.getEntityData(), true));
} }
boolean flag = this.trackDelta; boolean flag = this.trackDelta;
if (this.entity instanceof LivingEntity) { if (this.entity instanceof LivingEntity livingEntity) {
Collection<AttributeInstance> collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes(); Collection<AttributeInstance> collection = livingEntity.getAttributes().getSyncableAttributes();
if (this.entity.getId() == player.getId()) { if (this.entity.getId() == player.getId()) {
((ServerPlayerEntityBridge) this.entity).bridge$getBukkitEntity().injectScaledMaxHealth(collection, false); ((ServerPlayerEntityBridge) this.entity).bridge$getBukkitEntity().injectScaledMaxHealth(collection, false);
} }
if (!collection.isEmpty()) { if (!collection.isEmpty()) {
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection)); consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection));
} }
if (((LivingEntity) this.entity).isFallFlying()) { if (livingEntity.isFallFlying()) {
flag = true; flag = true;
} }
} }
@ -278,11 +279,11 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
} }
this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0f / 360.0f); this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0f / 360.0f);
consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) this.yHeadRotp)); consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) this.yHeadRotp));
if (this.entity instanceof LivingEntity) { if (this.entity instanceof LivingEntity livingEntity) {
LivingEntity entityliving = (LivingEntity) this.entity; for (MobEffectInstance mobeffect : livingEntity.getActiveEffects()) {
for (MobEffectInstance mobeffect : entityliving.getActiveEffects()) {
consumer.accept(new ClientboundUpdateMobEffectPacket(this.entity.getId(), mobeffect)); consumer.accept(new ClientboundUpdateMobEffectPacket(this.entity.getId(), mobeffect));
} }
livingEntity.detectEquipmentUpdates();
} }
if (!this.entity.getPassengers().isEmpty()) { if (!this.entity.getPassengers().isEmpty()) {
consumer.accept(new ClientboundSetPassengersPacket(this.entity)); consumer.accept(new ClientboundSetPassengersPacket(this.entity));
@ -297,8 +298,8 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
@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")) @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, Set<AttributeInstance> set) {
if (this.entity instanceof ServerPlayer) { if (this.entity instanceof ServerPlayerEntityBridge player) {
((ServerPlayerEntityBridge) this.entity).bridge$getBukkitEntity().injectScaledMaxHealth(set, false); player.bridge$getBukkitEntity().injectScaledMaxHealth(set, false);
} }
} }
} }

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge;
@ -11,18 +11,16 @@ import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge; import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge; import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
import io.izzel.arclight.common.bridge.world.storage.WorldInfoBridge; import io.izzel.arclight.common.bridge.world.storage.WorldInfoBridge;
import io.izzel.arclight.common.mixin.core.world.WorldMixin; import io.izzel.arclight.common.mixin.core.world.level.LevelMixin;
import io.izzel.arclight.common.mod.server.world.WorldSymlink; import io.izzel.arclight.common.mod.server.world.WorldSymlink;
import io.izzel.arclight.common.mod.util.ArclightCaptures; import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.izzel.arclight.common.mod.util.DelegateWorldInfo; import io.izzel.arclight.common.mod.util.DelegateWorldInfo;
import io.izzel.arclight.i18n.ArclightConfig; import io.izzel.arclight.i18n.ArclightConfig;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -33,8 +31,6 @@ import net.minecraft.world.Container;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.CustomSpawner;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.ExplosionDamageCalculator;
@ -45,6 +41,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.storage.DerivedLevelData; import net.minecraft.world.level.storage.DerivedLevelData;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
@ -67,8 +64,6 @@ import org.bukkit.event.world.TimeSkipEvent;
import org.bukkit.event.world.WorldSaveEvent; import org.bukkit.event.world.WorldSaveEvent;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -84,11 +79,9 @@ import javax.annotation.Nullable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Level;
@Mixin(ServerLevel.class) @Mixin(ServerLevel.class)
@Implements(@Interface(iface = ServerWorldBridge.Hack.class, prefix = "hack$")) public abstract class ServerLevelMixin extends LevelMixin implements ServerWorldBridge {
public abstract class ServerWorldMixin extends WorldMixin implements ServerWorldBridge {
// @formatter:off // @formatter:off
@Shadow public abstract boolean addFreshEntity(Entity entityIn); @Shadow public abstract boolean addFreshEntity(Entity entityIn);
@ -97,18 +90,17 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
@Shadow protected abstract boolean sendParticles(ServerPlayer player, boolean longDistance, double posX, double posY, double posZ, Packet<?> packet); @Shadow protected abstract boolean sendParticles(ServerPlayer player, boolean longDistance, double posX, double posY, double posZ, Packet<?> packet);
@Shadow @Nonnull public abstract MinecraftServer shadow$getServer(); @Shadow @Nonnull public abstract MinecraftServer shadow$getServer();
@Shadow @Final private List<ServerPlayer> players; @Shadow @Final private List<ServerPlayer> players;
@Shadow @Final public Int2ObjectMap<Entity> entitiesById;
@Shadow public abstract ServerChunkCache getChunkSource(); @Shadow public abstract ServerChunkCache getChunkSource();
@Shadow private boolean allPlayersSleeping;
@Shadow protected abstract void wakeUpAllPlayers(); @Shadow protected abstract void wakeUpAllPlayers();
@Shadow @Final private ServerChunkCache chunkSource; @Shadow @Final private ServerChunkCache chunkSource;
@Shadow protected abstract boolean isUUIDUsed(Entity entityIn);
@Shadow @Final public static BlockPos END_SPAWN_POINT; @Shadow @Final public static BlockPos END_SPAWN_POINT;
@Shadow @Final public ServerLevelData serverLevelData; @Shadow @Final public ServerLevelData serverLevelData;
@Shadow @Final private PersistentEntitySectionManager<Entity> entityManager;
// @formatter:on // @formatter:on
@SuppressWarnings({"FieldCanBeLocal", "unused"}) @SuppressWarnings({"FieldCanBeLocal", "unused"})
public PrimaryLevelData $$worldDataServer; public PrimaryLevelData $$worldDataServer;
private int tickPosition;
public LevelStorageSource.LevelStorageAccess convertable; public LevelStorageSource.LevelStorageAccess convertable;
public UUID uuid; public UUID uuid;
@ -131,7 +123,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
private void arclight$init(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData worldInfo, ResourceKey<net.minecraft.world.level.Level> dimension, DimensionType dimensionType, ChunkProgressListener statusListener, ChunkGenerator chunkGenerator, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking, CallbackInfo ci) { private void arclight$init(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData worldInfo, ResourceKey<net.minecraft.world.level.Level> dimension, DimensionType dimensionType, ChunkProgressListener statusListener, ChunkGenerator chunkGenerator, boolean isDebug, long seed, List<CustomSpawner> specialSpawners, boolean shouldBeTicking, CallbackInfo ci) {
this.pvpMode = minecraftServer.isPvpAllowed(); this.pvpMode = minecraftServer.isPvpAllowed();
this.convertable = levelSave; this.convertable = levelSave;
this.uuid = WorldUUID.getUUID(levelSave.getDimensionPath(this.getDimensionKey())); this.uuid = WorldUUID.getUUID(levelSave.getDimensionPath(this.dimension()));
if (worldInfo instanceof PrimaryLevelData) { if (worldInfo instanceof PrimaryLevelData) {
this.$$worldDataServer = (PrimaryLevelData) worldInfo; this.$$worldDataServer = (PrimaryLevelData) worldInfo;
} else if (worldInfo instanceof DerivedLevelData) { } else if (worldInfo instanceof DerivedLevelData) {
@ -139,7 +131,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
this.$$worldDataServer = DelegateWorldInfo.wrap(((DerivedLevelData) worldInfo)); this.$$worldDataServer = DelegateWorldInfo.wrap(((DerivedLevelData) worldInfo));
((DerivedWorldInfoBridge) worldInfo).bridge$setDimType(this.getTypeKey()); ((DerivedWorldInfoBridge) worldInfo).bridge$setDimType(this.getTypeKey());
if (ArclightConfig.spec().getCompat().isSymlinkWorld()) { if (ArclightConfig.spec().getCompat().isSymlinkWorld()) {
WorldSymlink.create((DerivedLevelData) worldInfo, levelSave.getDimensionPath(this.getDimensionKey())); WorldSymlink.create((DerivedLevelData) worldInfo, levelSave.getDimensionPath(this.dimension()));
} }
} }
((ServerChunkProviderBridge) this.chunkSource).bridge$setViewDistance(spigotConfig.viewDistance); ((ServerChunkProviderBridge) this.chunkSource).bridge$setViewDistance(spigotConfig.viewDistance);
@ -168,11 +160,6 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
return this.convertable; return this.convertable;
} }
@Inject(method = "add", at = @At("RETURN"))
private void arclight$validEntity(Entity entityIn, CallbackInfo ci) {
((EntityBridge) entityIn).bridge$setValid(true);
}
@Inject(method = "tickNonPassenger", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;tick()V")) @Inject(method = "tickNonPassenger", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;tick()V"))
private void arclight$tickPortal(Entity entityIn, CallbackInfo ci) { private void arclight$tickPortal(Entity entityIn, CallbackInfo ci) {
((EntityBridge) entityIn).bridge$postTick(); ((EntityBridge) entityIn).bridge$postTick();
@ -183,11 +170,6 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
((EntityBridge) passengerEntity).bridge$postTick(); ((EntityBridge) passengerEntity).bridge$postTick();
} }
@Inject(method = "removeEntityComplete", remap = false, at = @At("RETURN"))
private void arclight$invalidEntity(Entity entityIn, boolean keepData, CallbackInfo ci) {
((EntityBridge) entityIn).bridge$setValid(false);
}
@Inject(method = "tickChunk", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) @Inject(method = "tickChunk", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
public void arclight$thunder(LevelChunk chunkIn, int randomTickSpeed, CallbackInfo ci) { public void arclight$thunder(LevelChunk chunkIn, int randomTickSpeed, CallbackInfo ci) {
bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.LIGHTNING); bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.LIGHTNING);
@ -226,8 +208,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
@Inject(method = "save", at = @At("RETURN")) @Inject(method = "save", at = @At("RETURN"))
private void arclight$saveLevelDat(ProgressListener progress, boolean flush, boolean skipSave, CallbackInfo ci) { private void arclight$saveLevelDat(ProgressListener progress, boolean flush, boolean skipSave, CallbackInfo ci) {
if (this.serverLevelData instanceof PrimaryLevelData) { if (this.serverLevelData instanceof PrimaryLevelData worldInfo) {
PrimaryLevelData worldInfo = (PrimaryLevelData) this.serverLevelData;
worldInfo.setWorldBorder(this.getWorldBorder().createSettings()); worldInfo.setWorldBorder(this.getWorldBorder().createSettings());
worldInfo.setCustomBossEvents(this.shadow$getServer().getCustomBossEvents().save()); 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().registryHolder, worldInfo, this.shadow$getServer().getPlayerList().getSingleplayerData());
@ -317,13 +298,17 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
return addWithUUID(entity); return addWithUUID(entity);
} }
public void addEntityTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
addEntity(entity, reason);
}
@Override @Override
public boolean bridge$addEntitySerialized(Entity entity, CreatureSpawnEvent.SpawnReason reason) { public boolean bridge$addEntitySerialized(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
return addEntitySerialized(entity, reason); return addEntitySerialized(entity, reason);
} }
public boolean addAllEntitiesSafely(Entity entity, CreatureSpawnEvent.SpawnReason reason) { public boolean addAllEntitiesSafely(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
if (entity.getSelfAndPassengers().anyMatch(this::isUUIDUsed)) { if (entity.getSelfAndPassengers().map(Entity::getUUID).anyMatch(this.entityManager::isLoaded)) {
return false; return false;
} }
return this.bridge$addAllEntities(entity, reason); return this.bridge$addAllEntities(entity, reason);
@ -351,14 +336,20 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
@Overwrite @Overwrite
@Nullable @Nullable
public MapItemSavedData getMapData(String mapName) { public MapItemSavedData getMapData(String mapName) {
return this.shadow$getServer().overworld().getDataStorage().get(() -> { return this.shadow$getServer().overworld().getDataStorage().get((nbt) -> {
MapItemSavedData newMap = new MapItemSavedData(mapName); MapItemSavedData newMap = MapItemSavedData.load(nbt);
((MapDataBridge) newMap).bridge$setId(mapName);
MapInitializeEvent event = new MapInitializeEvent(((MapDataBridge) newMap).bridge$getMapView()); MapInitializeEvent event = new MapInitializeEvent(((MapDataBridge) newMap).bridge$getMapView());
Bukkit.getServer().getPluginManager().callEvent(event); Bukkit.getServer().getPluginManager().callEvent(event);
return newMap; return newMap;
}, mapName); }, mapName);
} }
@Inject(method = "setMapData", at = @At("HEAD"))
private void arclight$mapSetId(String id, MapItemSavedData data, CallbackInfo ci) {
((MapDataBridge) data).bridge$setId(id);
}
@Inject(method = "blockUpdated", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V")) @Inject(method = "blockUpdated", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V"))
private void arclight$returnIfPopulate(BlockPos pos, Block block, CallbackInfo ci) { private void arclight$returnIfPopulate(BlockPos pos, Block block, CallbackInfo ci) {
if (populating) { if (populating) {
@ -366,64 +357,9 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
} }
} }
@Override
public BlockEntity bridge$getTileEntity(BlockPos blockPos) {
return this.getTileEntity(blockPos);
}
public BlockEntity hack$getTileEntity(BlockPos pos) {
return this.getTileEntity(pos);
}
@Override
public BlockEntity getTileEntity(BlockPos pos) {
return getTileEntity(pos, true);
}
@Override @Override
public BlockEntity getTileEntity(BlockPos pos, boolean validate) { public BlockEntity getTileEntity(BlockPos pos, boolean validate) {
BlockEntity result = super.getTileEntity(pos); return this.getBlockEntity(pos);
if (!validate || Thread.currentThread() != arclight$getMainThread()) {
return result;
}
BlockState state = getBlockState(pos);
Block type = state.getBlock();
if (result != null && type != Blocks.AIR) {
if (!result.getType().isValid(type)) {
result = fixTileEntity(pos, state, type, result);
}
}
return result;
}
private BlockEntity fixTileEntity(BlockPos pos, Block type, BlockEntity found) {
return fixTileEntity(pos, getBlockState(pos), type, found);
}
private BlockEntity fixTileEntity(BlockPos pos, BlockState state, Block type, BlockEntity found) {
ResourceLocation registryName = found.getType().getRegistryName();
if (registryName == null || !registryName.getNamespace().equals("minecraft")) {
return found;
}
ResourceLocation blockType = type.getRegistryName();
if (blockType == null || !blockType.getNamespace().equals("minecraft")) {
return found;
}
this.getServer().getLogger().log(Level.SEVERE, "Block at {0}, {1}, {2} is {3} but has {4}" + ". "
+ "Bukkit will attempt to fix this, but there may be additional damage that we cannot recover.", new Object[]{pos.getX(), pos.getY(), pos.getZ(), type, found});
if (type.hasTileEntity(state)) {
BlockEntity replacement = type.createTileEntity(state, (BlockGetter) this);
if (replacement == null) return found;
replacement.setLevelAndPosition(((net.minecraft.world.level.Level) (Object) this), pos);
this.setTileEntity(pos, replacement);
return replacement;
} else {
return found;
}
} }
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setDayTime(J)V")) @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setDayTime(J)V"))
@ -433,7 +369,6 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
arclight$timeSkipCancelled = event.isCancelled(); arclight$timeSkipCancelled = event.isCancelled();
if (!event.isCancelled()) { if (!event.isCancelled()) {
world.setDayTime(this.getDayTime() + event.getSkipAmount()); world.setDayTime(this.getDayTime() + event.getSkipAmount());
this.allPlayersSleeping = this.players.stream().allMatch(LivingEntity::isSleeping);
} }
} }

View File

@ -0,0 +1,50 @@
package io.izzel.arclight.common.mixin.core.server.level;
import com.google.common.collect.Lists;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks;
import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(targets = "net/minecraft/server/level/ServerLevel$EntityCallbacks")
public class ServerLevel_EntityCallbacksMixin {
@Inject(method = "onTrackingStart", at = @At("RETURN"))
private void arclight$valid(Entity entity, CallbackInfo ci) {
((EntityBridge) entity).bridge$setValid(true);
}
@Inject(method = "onTrackingEnd", at = @At("HEAD"))
private void arclight$entityCleanup(Entity entity, CallbackInfo ci) {
if (entity instanceof Player player) {
for (ServerLevel serverLevel : ServerLifecycleHooks.getCurrentServer().levels.values()) {
DimensionDataStorage worldData = serverLevel.getDataStorage();
for (Object o : worldData.cache.values()) {
if (o instanceof MapItemSavedData map) {
map.carriedByPlayers.remove(player);
((MapDataBridge) map).bridge$getCarriedBy().removeIf(holdingPlayer -> holdingPlayer.player == entity);
}
}
}
}
if (((EntityBridge) entity).bridge$getBukkitEntity() instanceof InventoryHolder holder) {
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(holder.getInventory().getViewers())) {
h.closeInventory();
}
}
}
@Inject(method = "onTrackingEnd", at = @At("RETURN"))
private void arclight$invalid(Entity entity, CallbackInfo ci) {
((EntityBridge) entity).bridge$setValid(true);
}
}

View File

@ -1,9 +1,12 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import io.izzel.arclight.common.bridge.world.server.TicketManagerBridge; import io.izzel.arclight.common.bridge.world.server.TicketManagerBridge;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.Ticket; import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;
import net.minecraft.util.SortedArraySet; import net.minecraft.util.SortedArraySet;
@ -12,6 +15,10 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Iterator; import java.util.Iterator;
@ -27,14 +34,11 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
@Invoker("purgeStaleTickets") public abstract void bridge$tick(); @Invoker("purgeStaleTickets") public abstract void bridge$tick();
// @formatter:on // @formatter:on
@SuppressWarnings("unused") // mock @Inject(method = "removePlayer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", remap = false, target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;remove(Ljava/lang/Object;)Z"))
public <T> boolean func_219356_a(TicketType<T> type, ChunkPos pos, int level, T value) { private void arclight$remove(SectionPos p_140829_, ServerPlayer p_140830_, CallbackInfo ci, ObjectSet<?> set) {
return addTicketAtLevel(type, pos, level, value); if (set == null) {
} ci.cancel();
}
@SuppressWarnings("unused") // mock
public <T> boolean func_219345_b(TicketType<T> type, ChunkPos pos, int level, T value) {
return removeTicketAtLevel(type, pos, level, value);
} }
public <T> boolean addTicketAtLevel(TicketType<T> type, ChunkPos pos, int level, T value) { public <T> boolean addTicketAtLevel(TicketType<T> type, ChunkPos pos, int level, T value) {
@ -57,12 +61,7 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
return removeTicketAtLevel(type, pos, level, value); return removeTicketAtLevel(type, pos, level, value);
} }
@SuppressWarnings("unused") // mock boolean removeTicket(long chunkPosIn, Ticket<?> ticketIn) {
private boolean func_219349_b(long chunkPosIn, Ticket<?> ticketIn) {
return removeTicket(chunkPosIn, ticketIn);
}
private boolean removeTicket(long chunkPosIn, Ticket<?> ticketIn) {
SortedArraySet<Ticket<?>> ticketSet = this.getTickets(chunkPosIn); SortedArraySet<Ticket<?>> ticketSet = this.getTickets(chunkPosIn);
boolean removed = false; boolean removed = false;
if (ticketSet.remove(ticketIn)) { if (ticketSet.remove(ticketIn)) {
@ -80,12 +79,7 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
return removeTicket(chunkPos, ticket); return removeTicket(chunkPos, ticket);
} }
@SuppressWarnings("unused") // mock boolean addTicket(long chunkPosIn, Ticket<?> ticketIn) {
private boolean func_219347_a(long chunkPosIn, Ticket<?> ticketIn) {
return addTicket(chunkPosIn, ticketIn);
}
private boolean addTicket(long chunkPosIn, Ticket<?> ticketIn) {
SortedArraySet<Ticket<?>> ticketSet = this.getTickets(chunkPosIn); SortedArraySet<Ticket<?>> ticketSet = this.getTickets(chunkPosIn);
int level = getTicketLevelAt(ticketSet); int level = getTicketLevelAt(ticketSet);
Ticket<?> ticket = ticketSet.addOrGet(ticketIn); Ticket<?> ticket = ticketSet.addOrGet(ticketIn);

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.world.server; package io.izzel.arclight.common.mixin.core.server.level;
import io.izzel.arclight.common.bridge.world.server.TicketTypeBridge; import io.izzel.arclight.common.bridge.world.server.TicketTypeBridge;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;

View File

@ -557,7 +557,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
File file2; File file2;
File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile();
File file1 = new File(file, uuid + ".json"); File file1 = new File(file, uuid + ".json");
if (!file1.exists() && (file2 = new File(file, String.valueOf(displayName) + ".json")).exists() && file2.isFile()) { if (!file1.exists() && (file2 = new File(file, displayName + ".json")).exists() && file2.isFile()) {
file2.renameTo(file1); file2.renameTo(file1);
} }
serverstatisticmanager = new ServerStatsCounter(this.server, file1); serverstatisticmanager = new ServerStatsCounter(this.server, file1);

View File

@ -1,69 +0,0 @@
package io.izzel.arclight.common.mixin.core.tileentity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.Containers;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.event.block.BlockCookEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(CampfireBlockEntity.class)
public abstract class CampfireTileEntityMixin extends BlockEntity {
// @formatter:off
@Shadow @Final private NonNullList<ItemStack> items;
@Shadow @Final public int[] cookingProgress;
@Shadow @Final public int[] cookingTime;
@Shadow protected abstract void markUpdated();
// @formatter:on
public CampfireTileEntityMixin(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
private void cook() {
for (int i = 0; i < this.items.size(); ++i) {
ItemStack before = this.items.get(i);
if (!before.isEmpty()) {
++this.cookingProgress[i];
if (this.cookingProgress[i] >= this.cookingTime[i]) {
Container iinventory = new SimpleContainer(before);
ItemStack after = this.level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, iinventory,
this.level).map((cookingRecipe) -> cookingRecipe.assemble(iinventory)).orElse(before);
BlockPos blockpos = this.getBlockPos();
CraftItemStack craftBefore = CraftItemStack.asCraftMirror(before);
org.bukkit.inventory.ItemStack bukkitAfter = CraftItemStack.asBukkitCopy(after);
BlockCookEvent event = new BlockCookEvent(CraftBlock.at(this.level, this.worldPosition), craftBefore, bukkitAfter);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
continue;
}
ItemStack cookFinal = CraftItemStack.asNMSCopy(event.getResult());
Containers.dropItemStack(this.level, blockpos.getX(), blockpos.getY(), blockpos.getZ(), cookFinal);
this.items.set(i, ItemStack.EMPTY);
this.markUpdated();
}
}
}
}
}

View File

@ -1,119 +0,0 @@
package io.izzel.arclight.common.mixin.core.tileentity;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
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.ArrayList;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
@Mixin(ChestBlockEntity.class)
public abstract class ChestTileEntityMixin extends LockableTileEntityMixin {
// @formatter:off
@Shadow private NonNullList<ItemStack> items;
@Shadow public int openCount;
// @formatter:on
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = IInventoryBridge.MAX_STACK;
public boolean opened;
@Inject(method = "startOpen", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/ChestBlockEntity;signalOpenCount()V"))
public void arclight$openRedstone(Player player, CallbackInfo ci) {
if (this.level == null) {
ci.cancel();
return;
}
int oldPower = Mth.clamp(this.openCount - 1, 0, 15);
if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) {
int newPower = Mth.clamp(this.openCount, 0, 15);
if (oldPower != newPower) {
CraftEventFactory.callRedstoneChange(level, worldPosition, oldPower, newPower);
}
}
}
@Inject(method = "stopOpen", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/ChestBlockEntity;signalOpenCount()V"))
public void arclight$closeRedstone(Player player, CallbackInfo ci) {
int oldPower = Mth.clamp(this.openCount + 1, 0, 15);
if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) {
int newPower = Mth.clamp(this.openCount, 0, 15);
if (oldPower != newPower) {
CraftEventFactory.callRedstoneChange(level, worldPosition, oldPower, newPower);
}
}
}
@Inject(method = "tick", cancellable = true, at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/entity/ChestBlockEntity;oOpenness:F"))
private void arclight$openByApi(CallbackInfo ci) {
if (opened) {
this.openCount--;
ci.cancel();
}
}
@Redirect(method = "signalOpenCount", 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$soundIfByPlayer(Level world, BlockPos pos, Block blockIn, int eventID, int eventParam) {
if (!opened) world.blockEvent(pos, blockIn, eventID, eventParam);
}
@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 int getMaxStackSize() {
if (maxStack == 0) maxStack = IInventoryBridge.MAX_STACK;
return maxStack;
}
@Override
public void setMaxStackSize(int size) {
this.maxStack = size;
}
@Override
public boolean onlyOpsCanSetNbt() {
return true;
}
}

View File

@ -1,96 +0,0 @@
package io.izzel.arclight.common.mixin.core.tileentity;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.mojang.authlib.GameProfile;
import com.mysql.jdbc.StringUtils;
import io.izzel.arclight.common.bridge.server.MinecraftServerBridge;
import io.izzel.arclight.common.mod.util.ArclightHeadLoader;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.CraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
@Mixin(SkullBlockEntity.class)
public abstract class SkullTileEntityMixin extends TileEntityMixin {
// @formatter:off
@Shadow public GameProfile owner;
// @formatter:on
private static ExecutorService executor = Executors.newFixedThreadPool(3,
new ThreadFactoryBuilder()
.setNameFormat("Head Conversion Thread - %1$d")
.build()
);
private static LoadingCache<String, GameProfile> skinCache = CacheBuilder.newBuilder().maximumSize(5000L).expireAfterAccess(60L, TimeUnit.MINUTES).build(new ArclightHeadLoader());
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
private void updateOwnerProfile() {
GameProfile profile = this.owner;
b(profile, input -> {
owner = input;
markDirty();
return false;
}, false);
}
@SuppressWarnings({"UnusedReturnValue", "ConstantConditions"})
private static Future<GameProfile> b(GameProfile gameprofile, Predicate<GameProfile> callback, boolean sync) {
if (gameprofile != null && !StringUtils.isNullOrEmpty(gameprofile.getName())) {
if (gameprofile.isComplete() && gameprofile.getProperties().containsKey("textures")) {
callback.apply(gameprofile);
} else if (Bukkit.getServer() == null || ((CraftServer) Bukkit.getServer()).getServer() == null) {
callback.apply(gameprofile);
} else {
GameProfile profile = skinCache.getIfPresent(gameprofile.getName().toLowerCase(Locale.ROOT));
if (profile != null && Iterables.getFirst((profile.getProperties()).get("textures"), null) != null) {
callback.apply(profile);
return Futures.immediateFuture(profile);
}
Callable<GameProfile> callable = () -> {
GameProfile profile1 = skinCache.getUnchecked(gameprofile.getName().toLowerCase(Locale.ROOT));
((MinecraftServerBridge) ((CraftServer) Bukkit.getServer()).getServer()).bridge$queuedProcess(() -> {
if (profile1 == null) {
callback.apply(gameprofile);
} else {
callback.apply(profile1);
}
});
return profile1;
};
if (sync) {
try {
return Futures.immediateFuture(callable.call());
} catch (Exception ex) {
Throwables.throwIfUnchecked(ex);
throw new RuntimeException(ex);
}
}
return executor.submit(callable);
}
} else {
callback.apply(gameprofile);
}
return Futures.immediateFuture(gameprofile);
}
}

View File

@ -7,6 +7,33 @@ import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.world.ExplosionBridge; import io.izzel.arclight.common.bridge.world.ExplosionBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.entity.item.PrimedTnt;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.ProtectionEnchantment;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
@ -29,32 +56,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.entity.item.PrimedTnt;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.ProtectionEnchantment;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.ExplosionDamageCalculator;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@Mixin(Explosion.class) @Mixin(Explosion.class)
public abstract class ExplosionMixin implements ExplosionBridge { public abstract class ExplosionMixin implements ExplosionBridge {
@ -77,9 +78,9 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@Shadow @Final private boolean fire; @Shadow @Final private boolean fire;
@Shadow @Final private Random random; @Shadow @Final private Random random;
@Shadow private static void addBlockDrops(ObjectArrayList<Pair<ItemStack, BlockPos>> dropPositionArray, ItemStack stack, BlockPos pos) { } @Shadow private static void addBlockDrops(ObjectArrayList<Pair<ItemStack, BlockPos>> dropPositionArray, ItemStack stack, BlockPos pos) { }
@Shadow @Final private ExplosionDamageCalculator damageCalculator;
// @formatter:on // @formatter:on
@Shadow @Final private ExplosionDamageCalculator damageCalculator;
@Inject(method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)V", @Inject(method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)V",
at = @At("RETURN")) at = @At("RETURN"))
@ -96,6 +97,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
if (this.radius < 0.1F) { if (this.radius < 0.1F) {
return; return;
} }
this.level.gameEvent(this.source, GameEvent.EXPLODE, new BlockPos(this.x, this.y, this.z));
Set<BlockPos> set = Sets.newHashSet(); Set<BlockPos> set = Sets.newHashSet();
int i = 16; int i = 16;
@ -119,6 +121,11 @@ public abstract class ExplosionMixin implements ExplosionBridge {
BlockPos blockpos = new BlockPos(d4, d6, d8); BlockPos blockpos = new BlockPos(d4, d6, d8);
BlockState blockstate = this.level.getBlockState(blockpos); BlockState blockstate = this.level.getBlockState(blockpos);
FluidState fluidstate = this.level.getFluidState(blockpos); FluidState fluidstate = this.level.getFluidState(blockpos);
if (!this.level.isInWorldBounds(blockpos)) {
break;
}
Optional<Float> optional = this.damageCalculator.getBlockExplosionResistance((Explosion) (Object) this, this.level, blockpos, blockstate, fluidstate); Optional<Float> optional = this.damageCalculator.getBlockExplosionResistance((Explosion) (Object) this, this.level, blockpos, blockstate, fluidstate);
if (optional.isPresent()) { if (optional.isPresent()) {
f -= (optional.get() + 0.3F) * 0.3F; f -= (optional.get() + 0.3F) * 0.3F;
@ -151,12 +158,12 @@ public abstract class ExplosionMixin implements ExplosionBridge {
for (Entity entity : list) { for (Entity entity : list) {
if (!entity.ignoreExplosion()) { if (!entity.ignoreExplosion()) {
double d12 = Mth.sqrt(entity.distanceToSqr(vec3d)) / f3; double d12 = Math.sqrt(entity.distanceToSqr(vec3d)) / f3;
if (d12 <= 1.0D) { if (d12 <= 1.0D) {
double d5 = entity.getX() - this.x; double d5 = entity.getX() - this.x;
double d7 = entity.getEyeY() - this.y; double d7 = entity.getEyeY() - this.y;
double d9 = entity.getZ() - this.z; double d9 = entity.getZ() - this.z;
double d13 = Mth.sqrt(d5 * d5 + d7 * d7 + d9 * d9); double d13 = Math.sqrt(d5 * d5 + d7 * d7 + d9 * d9);
if (d13 != 0.0D) { if (d13 != 0.0D) {
d5 = d5 / d13; d5 = d5 / d13;
d7 = d7 / d13; d7 = d7 / d13;
@ -178,9 +185,8 @@ public abstract class ExplosionMixin implements ExplosionBridge {
} }
entity.setDeltaMovement(entity.getDeltaMovement().add(d5 * d11, d7 * d11, d9 * d11)); entity.setDeltaMovement(entity.getDeltaMovement().add(d5 * d11, d7 * d11, d9 * d11));
if (entity instanceof Player) { if (entity instanceof Player playerentity) {
Player playerentity = (Player) entity; if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.getAbilities().flying)) {
if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.abilities.flying)) {
this.hitPlayers.put(playerentity, new Vec3(d5 * d10, d7 * d10, d9 * d10)); this.hitPlayers.put(playerentity, new Vec3(d5 * d10, d7 * d10, d9 * d10));
} }
} }
@ -231,12 +237,12 @@ public abstract class ExplosionMixin implements ExplosionBridge {
for (BlockPos blockpos : this.toBlow) { for (BlockPos blockpos : this.toBlow) {
BlockState blockstate = this.level.getBlockState(blockpos); BlockState blockstate = this.level.getBlockState(blockpos);
Block block = blockstate.getBlock(); Block block = blockstate.getBlock();
if (!blockstate.isAir(this.level, blockpos)) { if (!blockstate.isAir()) {
BlockPos blockpos1 = blockpos.immutable(); BlockPos blockpos1 = blockpos.immutable();
this.level.getProfiler().push("explosion_blocks"); this.level.getProfiler().push("explosion_blocks");
if (blockstate.canDropFromExplosion(this.level, blockpos, (Explosion) (Object) this) && this.level instanceof ServerLevel) { if (blockstate.canDropFromExplosion(this.level, blockpos, (Explosion) (Object) this) && this.level instanceof ServerLevel) {
BlockEntity tileentity = blockstate.hasTileEntity() ? this.level.getBlockEntity(blockpos) : null; BlockEntity tileentity = blockstate.hasBlockEntity() ? this.level.getBlockEntity(blockpos) : null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerLevel)this.level)).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, this.source); LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerLevel) this.level)).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, this.source);
if (this.blockInteraction == Explosion.BlockInteraction.DESTROY || yield < 1.0F) { if (this.blockInteraction == Explosion.BlockInteraction.DESTROY || yield < 1.0F) {
lootcontext$builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / yield); lootcontext$builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / yield);
} }
@ -247,6 +253,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
} }
blockstate.onBlockExploded(this.level, blockpos, (Explosion) (Object) this); blockstate.onBlockExploded(this.level, blockpos, (Explosion) (Object) this);
block.wasExploded(this.level, blockpos, (Explosion) (Object) this);
this.level.getProfiler().pop(); this.level.getProfiler().pop();
} }
} }

View File

@ -1,16 +1,16 @@
package io.izzel.arclight.common.mixin.core.world; package io.izzel.arclight.common.mixin.core.world;
import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge; import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.ServerLevelAccessor;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import java.util.Iterator; import java.util.Iterator;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.ServerLevelAccessor;
@Mixin(ServerLevelAccessor.class) @Mixin(ServerLevelAccessor.class)
public interface IServerWorldMixin extends LevelAccessor, ServerWorldBridge { public interface IServerWorldMixin extends LevelAccessor, ServerWorldBridge {
@ -46,7 +46,7 @@ public interface IServerWorldMixin extends LevelAccessor, ServerWorldBridge {
bridge$pushAddEntityReason(reason); bridge$pushAddEntityReason(reason);
this.addFreshEntity(next); this.addFreshEntity(next);
} }
return !entity.removed; return !entity.isRemoved();
} }
@Override @Override

View File

@ -1,12 +1,12 @@
package io.izzel.arclight.common.mixin.core.util; package io.izzel.arclight.common.mixin.core.world.damagesource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import io.izzel.arclight.common.bridge.util.DamageSourceBridge; import io.izzel.arclight.common.bridge.util.DamageSourceBridge;
import javax.annotation.Nullable;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
@Mixin(DamageSource.class) @Mixin(DamageSource.class)
public abstract class DamageSourceMixin implements DamageSourceBridge { public abstract class DamageSourceMixin implements DamageSourceBridge {

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.util; package io.izzel.arclight.common.mixin.core.world.damagesource;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -413,8 +413,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Inject(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity$MovementEmission;emitsAnything()Z")) @Inject(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity$MovementEmission;emitsAnything()Z"))
private void arclight$move$blockCollide(MoverType typeIn, Vec3 pos, CallbackInfo ci) { private void arclight$move$blockCollide(MoverType typeIn, Vec3 pos, CallbackInfo ci) {
if (horizontalCollision && this.bridge$getBukkitEntity() instanceof Vehicle) { if (horizontalCollision && this.bridge$getBukkitEntity() instanceof Vehicle vehicle) {
Vehicle vehicle = (Vehicle) this.bridge$getBukkitEntity();
org.bukkit.block.Block block = ((WorldBridge) this.level).bridge$getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); org.bukkit.block.Block block = ((WorldBridge) this.level).bridge$getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()));
Vec3 vec3d = this.collide(pos); Vec3 vec3d = this.collide(pos);
if (pos.x > vec3d.x) { if (pos.x > vec3d.x) {
@ -506,8 +505,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Inject(method = "load", at = @At(value = "RETURN")) @Inject(method = "load", at = @At(value = "RETURN"))
public void arclight$read$ReadBukkitValues(CompoundTag compound, CallbackInfo ci) { public void arclight$read$ReadBukkitValues(CompoundTag compound, CallbackInfo ci) {
// CraftBukkit start // CraftBukkit start
if ((Object) this instanceof LivingEntity) { if ((Object) this instanceof LivingEntity entity) {
LivingEntity entity = (LivingEntity) (Object) this;
this.tickCount = compound.getInt("Spigot.ticksLived"); this.tickCount = compound.getInt("Spigot.ticksLived");

View File

@ -39,7 +39,7 @@ public abstract class EntityTypeMixin<T extends Entity> implements EntityTypeBri
@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;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;",
cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN"),
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;func_242417_l(Lnet/minecraft/world/entity/Entity;)V"))) 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 worldIn, CompoundTag compound, Component customName, Player playerIn, BlockPos pos, MobSpawnType reason, boolean p_220342_7_, boolean p_220342_8_, CallbackInfoReturnable<T> cir, T t) {
if (t != null) { if (t != null) {
cir.setReturnValue(t.isRemoved() ? null : t); cir.setReturnValue(t.isRemoved() ? null : t);

View File

@ -577,8 +577,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
if (entity1 instanceof net.minecraft.world.entity.player.Player) { if (entity1 instanceof net.minecraft.world.entity.player.Player) {
this.lastHurtByPlayerTime = 100; this.lastHurtByPlayerTime = 100;
this.lastHurtByPlayer = (net.minecraft.world.entity.player.Player) entity1; this.lastHurtByPlayer = (net.minecraft.world.entity.player.Player) entity1;
} else if (entity1 instanceof TamableAnimal) { } else if (entity1 instanceof TamableAnimal wolfentity) {
TamableAnimal wolfentity = (TamableAnimal) entity1;
if (wolfentity.isTame()) { if (wolfentity.isTame()) {
this.lastHurtByPlayerTime = 100; this.lastHurtByPlayerTime = 100;
LivingEntity livingentity = wolfentity.getOwner(); LivingEntity livingentity = wolfentity.getOwner();
@ -910,8 +909,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
if (!itemstack1.isEmpty()) { if (!itemstack1.isEmpty()) {
itemstack1.shrink(1); itemstack1.shrink(1);
} }
if (itemstack != null && (Object) this instanceof ServerPlayer) { if (itemstack != null && (Object) this instanceof ServerPlayer serverplayerentity) {
ServerPlayer serverplayerentity = (ServerPlayer) (Object) this;
serverplayerentity.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); serverplayerentity.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING));
CriteriaTriggers.USED_TOTEM.trigger(serverplayerentity, itemstack); CriteriaTriggers.USED_TOTEM.trigger(serverplayerentity, itemstack);
} }

View File

@ -24,7 +24,7 @@ public class FollowOwnerGoalMixin {
private transient boolean arclight$cancelled; private transient boolean arclight$cancelled;
@Redirect(method = "maybeTeleportTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/TamableAnimal;setLocationAndAngles(DDDFF)V")) @Redirect(method = "maybeTeleportTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/TamableAnimal;moveTo(DDDFF)V"))
public void arclight$teleport(TamableAnimal tameableEntity, double x, double y, double z, float yaw, float pitch) { public void arclight$teleport(TamableAnimal tameableEntity, double x, double y, double z, float yaw, float pitch) {
CraftEntity craftEntity = ((EntityBridge) this.tamable).bridge$getBukkitEntity(); CraftEntity craftEntity = ((EntityBridge) this.tamable).bridge$getBukkitEntity();
Location location = new Location(craftEntity.getWorld(), x, y, z, yaw, pitch); Location location = new Location(craftEntity.getWorld(), x, y, z, yaw, pitch);

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.village; package io.izzel.arclight.common.mixin.core.world.entity.ai.village;
import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge; import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;

View File

@ -26,7 +26,7 @@ public abstract class EnderCrystalMixin extends EntityMixin {
} }
} }
@Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/enderdragon/EndCrystal;remove()V")) @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) { 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); cir.setReturnValue(false);

View File

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

View File

@ -12,20 +12,12 @@ import net.minecraft.world.phys.AABB;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List; import java.util.List;
@Mixin(LeashFenceKnotEntity.class) @Mixin(LeashFenceKnotEntity.class)
public abstract class LeashFenceKnotEntityMixin extends HangingEntityMixin { public abstract class LeashFenceKnotEntityMixin extends HangingEntityMixin {
@Inject(method = "recalculateBoundingBox", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;updateChunkPos(Lnet/minecraft/world/entity/Entity;)V"))
private void arclight$checkIfValid(CallbackInfo ci) {
if (!valid) ci.cancel();
}
/** /**
* @author IzzelAliz * @author IzzelAliz
* @reason * @reason

View File

@ -39,7 +39,7 @@ public abstract class VillagerMixin extends AbstractVillagerMixin {
} }
} }
@Inject(method = "thunderHit", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;func_242417_l(Lnet/minecraft/world/entity/Entity;)V")) @Inject(method = "thunderHit", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private void arclight$transformWitch(ServerLevel serverWorld, LightningBolt lightningBolt, CallbackInfo ci, Witch witchEntity) { private void arclight$transformWitch(ServerLevel serverWorld, LightningBolt lightningBolt, CallbackInfo ci, Witch witchEntity) {
if (CraftEventFactory.callEntityTransformEvent((net.minecraft.world.entity.npc.Villager) (Object) this, witchEntity, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { if (CraftEventFactory.callEntityTransformEvent((net.minecraft.world.entity.npc.Villager) (Object) this, witchEntity, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) {
ci.cancel(); ci.cancel();
@ -48,7 +48,7 @@ public abstract class VillagerMixin extends AbstractVillagerMixin {
} }
} }
@Inject(method = "trySpawnGolem", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;func_242417_l(Lnet/minecraft/world/entity/Entity;)V")) @Inject(method = "trySpawnGolem", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private void arclight$ironGolemReason(ServerLevel world, CallbackInfoReturnable<IronGolem> cir) { private void arclight$ironGolemReason(ServerLevel world, CallbackInfoReturnable<IronGolem> cir) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE); ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE);
} }

View File

@ -431,8 +431,7 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
@Inject(method = "stopSleepInBed", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/player/Player;sleepCounter:I")) @Inject(method = "stopSleepInBed", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/player/Player;sleepCounter:I"))
private void arclight$wakeup(boolean flag, boolean flag1, CallbackInfo ci) { private void arclight$wakeup(boolean flag, boolean flag1, CallbackInfo ci) {
BlockPos blockPos = this.getSleepingPos().orElse(null); BlockPos blockPos = this.getSleepingPos().orElse(null);
if (this.bridge$getBukkitEntity() instanceof Player) { if (this.bridge$getBukkitEntity() instanceof Player player) {
Player player = (Player) this.bridge$getBukkitEntity();
Block bed; Block bed;
if (blockPos != null) { if (blockPos != null) {
bed = CraftBlock.at(this.level, blockPos); bed = CraftBlock.at(this.level, blockPos);

View File

@ -1,18 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.entity.projectile; package io.izzel.arclight.common.mixin.core.world.entity.projectile;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
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 io.izzel.arclight.common.bridge.entity.projectile.ArrowEntityBridge; import io.izzel.arclight.common.bridge.entity.projectile.ArrowEntityBridge;
import java.util.Set;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -22,6 +11,17 @@ import net.minecraft.world.entity.projectile.Arrow;
import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionUtils; import net.minecraft.world.item.alchemy.PotionUtils;
import net.minecraft.world.item.alchemy.Potions; import net.minecraft.world.item.alchemy.Potions;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Set;
@Mixin(Arrow.class) @Mixin(Arrow.class)
@Implements(@Interface(iface = ArrowEntityBridge.Hack.class, prefix = "hack$")) @Implements(@Interface(iface = ArrowEntityBridge.Hack.class, prefix = "hack$"))
@ -33,7 +33,7 @@ public abstract class ArrowEntityMixin extends AbstractArrowMixin implements Arr
@Shadow private Potion potion; @Shadow private Potion potion;
// @formatter:on // @formatter:on
@Inject(method = "doPostHurtEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) @Inject(method = "doPostHurtEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z"))
private void arclight$arrowHit(LivingEntity living, CallbackInfo ci) { private void arclight$arrowHit(LivingEntity living, CallbackInfo ci) {
((LivingEntityBridge) living).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ARROW); ((LivingEntityBridge) living).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ARROW);
} }

View File

@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SpectralArrow.class) @Mixin(SpectralArrow.class)
public abstract class SpectralArrowMixin extends AbstractArrowMixin { public abstract class SpectralArrowMixin extends AbstractArrowMixin {
@Inject(method = "doPostHurtEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) @Inject(method = "doPostHurtEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z"))
private void arclight$hit(LivingEntity living, CallbackInfo ci) { private void arclight$hit(LivingEntity living, CallbackInfo ci) {
((LivingEntityBridge) living).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ARROW); ((LivingEntityBridge) living).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ARROW);
} }

View File

@ -1,5 +1,11 @@
package io.izzel.arclight.common.mixin.core.world.raid; package io.izzel.arclight.common.mixin.core.world.entity.raid;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.entity.raid.Raids;
import net.minecraft.world.level.dimension.DimensionType;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -10,12 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Map; import java.util.Map;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.entity.raid.Raids;
import net.minecraft.world.level.dimension.DimensionType;
@Mixin(Raids.class) @Mixin(Raids.class)
public class RaidManagerMixin { public class RaidManagerMixin {

View File

@ -1,8 +1,14 @@
package io.izzel.arclight.common.mixin.core.world.raid; package io.izzel.arclight.common.mixin.core.world.entity.raid;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.raid.RaidBridge; import io.izzel.arclight.common.bridge.world.raid.RaidBridge;
import net.minecraft.advancements.critereon.LocationTrigger;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.entity.raid.Raider;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
@ -23,12 +29,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.minecraft.advancements.critereon.LocationTrigger;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.entity.raid.Raider;
@Mixin(Raid.class) @Mixin(Raid.class)
public class RaidMixin implements RaidBridge { public class RaidMixin implements RaidBridge {

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.util; package io.izzel.arclight.common.mixin.core.world.food;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.util.FoodStatsBridge; import io.izzel.arclight.common.bridge.util.FoodStatsBridge;
import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; import net.minecraft.network.protocol.game.ClientboundSetHealthPacket;
@ -11,6 +12,7 @@ import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityExhaustionEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -21,15 +23,19 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(FoodData.class) @Mixin(FoodData.class)
public abstract class FoodStatsMixin implements FoodStatsBridge { public abstract class FoodDataMixin implements FoodStatsBridge {
// @formatter:off // @formatter:off
@Shadow public int foodLevel; @Shadow public int foodLevel;
@Shadow public abstract void eat(int foodLevelIn, float foodSaturationModifier); @Shadow public abstract void eat(int foodLevelIn, float foodSaturationModifier);
@Shadow public float saturationLevel; @Shadow public float saturationLevel;
@Shadow private int lastFoodLevel;
// @formatter:on // @formatter:on
private Player entityhuman; private Player entityhuman;
public int saturatedRegenRate = 10;
public int unsaturatedRegenRate = 80;
public int starvationRate = 80;
public void arclight$constructor() { public void arclight$constructor() {
throw new RuntimeException(); throw new RuntimeException();
@ -40,8 +46,12 @@ public abstract class FoodStatsMixin implements FoodStatsBridge {
this.entityhuman = playerEntity; this.entityhuman = playerEntity;
} }
@Redirect(method = "eat", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;eat(IF)V")) @Redirect(method = "eat(Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/ItemStack;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;eat(IF)V"))
public void arclight$foodLevelChange(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, Item maybeFood, ItemStack stack) { public void arclight$foodLevelChange(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, Item maybeFood, ItemStack stack) {
if (entityhuman == null) {
foodStats.eat(foodLevelIn, foodSaturationModifier);
return;
}
FoodProperties food = maybeFood.getFoodProperties(); FoodProperties food = maybeFood.getFoodProperties();
int oldFoodLevel = this.foodLevel; int oldFoodLevel = this.foodLevel;
FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, food.getNutrition() + oldFoodLevel, stack); FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, food.getNutrition() + oldFoodLevel, stack);
@ -53,10 +63,15 @@ public abstract class FoodStatsMixin implements FoodStatsBridge {
@Inject(method = "tick", at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Ljava/lang/Math;max(II)I")) @Inject(method = "tick", at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Ljava/lang/Math;max(II)I"))
public void arclight$foodLevelChange2(Player player, CallbackInfo ci) { public void arclight$foodLevelChange2(Player player, CallbackInfo ci) {
FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, Math.max(this.foodLevel - 1, 0)); if (entityhuman == null) {
return;
}
FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, Math.max(this.lastFoodLevel - 1, 0));
if (!event.isCancelled()) { if (!event.isCancelled()) {
this.foodLevel = event.getFoodLevel(); this.foodLevel = event.getFoodLevel();
} else {
this.foodLevel = this.lastFoodLevel;
} }
((ServerPlayer) entityhuman).connection.send(new ClientboundSetHealthPacket(((ServerPlayerEntityBridge) entityhuman).bridge$getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel)); ((ServerPlayer) entityhuman).connection.send(new ClientboundSetHealthPacket(((ServerPlayerEntityBridge) entityhuman).bridge$getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel));
@ -64,7 +79,11 @@ public abstract class FoodStatsMixin implements FoodStatsBridge {
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;heal(F)V")) @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;heal(F)V"))
public void arclight$heal(Player player, CallbackInfo ci) { public void arclight$heal(Player player, CallbackInfo ci) {
if (entityhuman == null) {
entityhuman = player;
}
((LivingEntityBridge) player).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.SATIATED); ((LivingEntityBridge) player).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.SATIATED);
((PlayerEntityBridge) player).bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.REGEN);
} }
@Override @Override

View File

@ -1,18 +1,18 @@
package io.izzel.arclight.common.mixin.core.util; package io.izzel.arclight.common.mixin.core.world.inventory;
import io.izzel.arclight.common.bridge.util.IWorldPosCallableBridge; import io.izzel.arclight.common.bridge.util.IWorldPosCallableBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.level.Level;
import org.bukkit.Location; import org.bukkit.Location;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import java.util.Optional; import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.level.Level;
@Mixin(ContainerLevelAccess.class) @Mixin(ContainerLevelAccess.class)
public interface IWorldPosCallableMixin extends IWorldPosCallableBridge { public interface ContainerLevelAccessMixin extends IWorldPosCallableBridge {
default Level getWorld() { default Level getWorld() {
return bridge$getWorld(); return bridge$getWorld();

View File

@ -19,6 +19,6 @@ public class FurnaceResultSlotMixin {
@Redirect(method = "checkTakeAchievements(Lnet/minecraft/world/item/ItemStack;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;awardUsedRecipesAndPopExperience(Lnet/minecraft/server/level/ServerPlayer;)V")) @Redirect(method = "checkTakeAchievements(Lnet/minecraft/world/item/ItemStack;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;awardUsedRecipesAndPopExperience(Lnet/minecraft/server/level/ServerPlayer;)V"))
public void arclight$furnaceDropExp(AbstractFurnaceBlockEntity furnace, ServerPlayer player, ItemStack stack) { public void arclight$furnaceDropExp(AbstractFurnaceBlockEntity furnace, ServerPlayer player, ItemStack stack) {
((AbstractFurnaceTileEntityBridge) furnace).bridge$dropExp(player.level, player.position(), player, stack, this.removeCount); ((AbstractFurnaceTileEntityBridge) furnace).bridge$dropExp(player, stack, this.removeCount);
} }
} }

View File

@ -42,8 +42,7 @@ public abstract class BowItemMixin extends ProjectileWeaponItem {
*/ */
@Overwrite @Overwrite
public void releaseUsing(ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) { public void releaseUsing(ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) {
if (entityLiving instanceof Player) { if (entityLiving instanceof Player playerentity) {
Player playerentity = (Player) entityLiving;
boolean flag = playerentity.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0; boolean flag = playerentity.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0;
ItemStack itemstack = playerentity.getProjectile(stack); ItemStack itemstack = playerentity.getProjectile(stack);

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.core.world; package io.izzel.arclight.common.mixin.core.world.level;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge; import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge;
import io.izzel.arclight.common.bridge.world.server.ServerChunkProviderBridge; import io.izzel.arclight.common.bridge.world.server.ServerChunkProviderBridge;
@ -23,18 +24,22 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.level.storage.WritableLevelData;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.block.data.CraftBlockData; import org.bukkit.craftbukkit.v.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator; import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator;
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.world.GenericGameEvent;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import org.spigotmc.SpigotWorldConfig; import org.spigotmc.SpigotWorldConfig;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -53,12 +58,11 @@ import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
@Mixin(Level.class) @Mixin(Level.class)
public abstract class WorldMixin implements WorldBridge, LevelWriter { public abstract class LevelMixin implements WorldBridge, LevelWriter {
// @formatter:off // @formatter:off
@Shadow @Nullable public BlockEntity getBlockEntity(BlockPos pos) { return null; } @Shadow @Nullable public BlockEntity getBlockEntity(BlockPos pos) { return null; }
@Shadow public abstract BlockState getBlockState(BlockPos pos); @Shadow public abstract BlockState getBlockState(BlockPos pos);
@Shadow public abstract void setBlockEntity(BlockPos pos, @Nullable BlockEntity tileEntityIn);
@Shadow public abstract WorldBorder getWorldBorder(); @Shadow public abstract WorldBorder getWorldBorder();
@Shadow @Final private WorldBorder worldBorder; @Shadow @Final private WorldBorder worldBorder;
@Shadow public abstract long getDayTime(); @Shadow public abstract long getDayTime();
@ -84,6 +88,7 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
public org.spigotmc.SpigotWorldConfig spigotConfig; public org.spigotmc.SpigotWorldConfig spigotConfig;
@SuppressWarnings("unused") // Access transformed to public by ArclightMixinPlugin @SuppressWarnings("unused") // Access transformed to public by ArclightMixinPlugin
private static BlockPos lastPhysicsProblem; // Spigot private static BlockPos lastPhysicsProblem; // Spigot
public boolean preventPoiUpdated = false;
public void arclight$constructor(WritableLevelData worldInfo, ResourceKey<Level> dimension, final DimensionType dimensionType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed) { public void arclight$constructor(WritableLevelData worldInfo, ResourceKey<Level> dimension, final DimensionType dimensionType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed) {
throw new RuntimeException(); throw new RuntimeException();
@ -100,14 +105,15 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
private void arclight$init(WritableLevelData info, ResourceKey<Level> dimension, DimensionType dimType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, CallbackInfo ci) { private void arclight$init(WritableLevelData info, ResourceKey<Level> dimension, DimensionType dimType, Supplier<ProfilerFiller> profiler, boolean isRemote, boolean isDebug, long seed, CallbackInfo ci) {
this.spigotConfig = new SpigotWorldConfig(((ServerLevelData) info).getLevelName()); this.spigotConfig = new SpigotWorldConfig(((ServerLevelData) info).getLevelName());
((WorldBorderBridge) this.worldBorder).bridge$setWorld((Level) (Object) this); ((WorldBorderBridge) this.worldBorder).bridge$setWorld((Level) (Object) this);
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns();
this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); this.ticksPerMonsterSpawns = this.getCraftServer().getTicksPerMonsterSpawns();
this.ticksPerWaterSpawns = this.getServer().getTicksPerWaterSpawns(); this.ticksPerWaterSpawns = this.getCraftServer().getTicksPerWaterSpawns();
this.ticksPerWaterAmbientSpawns = this.getServer().getTicksPerWaterAmbientSpawns(); this.ticksPerWaterAmbientSpawns = this.getCraftServer().getTicksPerWaterAmbientSpawns();
this.ticksPerAmbientSpawns = this.getServer().getTicksPerAmbientSpawns(); this.ticksPerAmbientSpawns = this.getCraftServer().getTicksPerAmbientSpawns();
this.typeKey = this.getServer().getHandle().getServer().registryAccess().dimensionTypes().getResourceKey(dimensionType) this.typeKey = this.getCraftServer().getHandle().getServer().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY)
.getResourceKey(dimensionType)
.orElseGet(() -> { .orElseGet(() -> {
Registry<DimensionType> registry = this.getServer().getHandle().getServer().registryAccess().dimensionTypes(); Registry<DimensionType> registry = this.getCraftServer().getHandle().getServer().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
ResourceKey<DimensionType> typeRegistryKey = ResourceKey.create(registry.key(), dimension.location()); ResourceKey<DimensionType> typeRegistryKey = ResourceKey.create(registry.key(), dimension.location());
ArclightMod.LOGGER.warn("Assign {} to unknown dimension type {} as {}", typeRegistryKey, dimType); ArclightMod.LOGGER.warn("Assign {} to unknown dimension type {} as {}", typeRegistryKey, dimType);
return typeRegistryKey; return typeRegistryKey;
@ -171,7 +177,7 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
return true; return true;
} }
@Inject(method = "markAndNotifyBlock", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;updateNeighbours(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;II)V")) @Inject(method = "markAndNotifyBlock", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;updateNeighbourShapes(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;II)V"))
private void arclight$callBlockPhysics(BlockPos pos, LevelChunk chunk, BlockState blockstate, BlockState state, int flags, int recursionLeft, CallbackInfo ci) { private void arclight$callBlockPhysics(BlockPos pos, LevelChunk chunk, BlockState blockstate, BlockState state, int flags, int recursionLeft, CallbackInfo ci) {
try { try {
if (this.world != null) { if (this.world != null) {
@ -186,6 +192,13 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
} }
} }
@Inject(method = "markAndNotifyBlock", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;onBlockStateChange(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)V"))
private void arclight$preventPoiUpdate(BlockPos p_46605_, LevelChunk levelchunk, BlockState blockstate, BlockState p_46606_, int p_46607_, int p_46608_, CallbackInfo ci) {
if (this.preventPoiUpdated) {
ci.cancel();
}
}
@Inject(method = "neighborChanged", cancellable = true, @Inject(method = "neighborChanged", cancellable = true,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;neighborChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/core/BlockPos;Z)V"), at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;neighborChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/core/BlockPos;Z)V"),
locals = LocalCapture.CAPTURE_FAILHARD) locals = LocalCapture.CAPTURE_FAILHARD)
@ -204,7 +217,16 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
} }
} }
public CraftServer getServer() { @Inject(method = "postGameEventInRadius", cancellable = true, at = @At("HEAD"))
private void arclight$gameEventEvent(Entity entity, GameEvent gameEvent, BlockPos pos, int i, CallbackInfo ci) {
GenericGameEvent event = new GenericGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(Registry.GAME_EVENT.getKey(gameEvent))), new Location(this.getWorld(), pos.getX(),pos.getY(), pos.getZ()), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), i);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
ci.cancel();
}
}
public CraftServer getCraftServer() {
return (CraftServer) Bukkit.getServer(); return (CraftServer) Bukkit.getServer();
} }
@ -219,9 +241,8 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
} }
} }
if (generator == null) { if (generator == null) {
generator = getServer().getGenerator(((ServerLevelData) this.getLevelData()).getLevelName()); generator = getCraftServer().getGenerator(((ServerLevelData) this.getLevelData()).getLevelName());
if (generator != null && (Object) this instanceof ServerLevel) { if (generator != null && (Object) this instanceof ServerLevel serverWorld) {
ServerLevel serverWorld = (ServerLevel) (Object) this;
CustomChunkGenerator gen = new CustomChunkGenerator(serverWorld, serverWorld.getChunkSource().getGenerator(), generator); CustomChunkGenerator gen = new CustomChunkGenerator(serverWorld, serverWorld.getChunkSource().getGenerator(), generator);
((ServerChunkProviderBridge) serverWorld.getChunkSource()).bridge$setChunkGenerator(gen); ((ServerChunkProviderBridge) serverWorld.getChunkSource()).bridge$setChunkGenerator(gen);
} }
@ -230,7 +251,7 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
environment = ArclightServer.getEnvironment(this.typeKey); environment = ArclightServer.getEnvironment(this.typeKey);
} }
this.world = new CraftWorld((ServerLevel) (Object) this, generator, environment); this.world = new CraftWorld((ServerLevel) (Object) this, generator, environment);
getServer().addWorld(this.world); getCraftServer().addWorld(this.world);
} }
return this.world; return this.world;
} }

View File

@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BeehiveBlock.class) @Mixin(BeehiveBlock.class)
public class BeehiveBlockMixin { public class BeehiveBlockMixin {
@Redirect(method = "angerNearbyBees", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Bee;setAttackTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) @Redirect(method = "angerNearbyBees", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Bee;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V"))
private void arclight$targetReason(Bee beeEntity, LivingEntity livingEntity) { private void arclight$targetReason(Bee beeEntity, LivingEntity livingEntity) {
((MobEntityBridge) beeEntity).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); ((MobEntityBridge) beeEntity).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true);
beeEntity.setTarget(livingEntity); beeEntity.setTarget(livingEntity);

View File

@ -24,8 +24,7 @@ public abstract class CommandBlockMixin {
public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {
if (!worldIn.isClientSide) { if (!worldIn.isClientSide) {
BlockEntity tileentity = worldIn.getBlockEntity(pos); BlockEntity tileentity = worldIn.getBlockEntity(pos);
if (tileentity instanceof CommandBlockEntity) { if (tileentity instanceof CommandBlockEntity commandblocktileentity) {
CommandBlockEntity commandblocktileentity = (CommandBlockEntity) tileentity;
boolean flag = worldIn.hasNeighborSignal(pos); boolean flag = worldIn.hasNeighborSignal(pos);
boolean flag1 = commandblocktileentity.isPowered(); boolean flag1 = commandblocktileentity.isPowered();

View File

@ -1,31 +1,15 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.item.crafting.IRecipeBridge;
import io.izzel.arclight.common.bridge.tileentity.AbstractFurnaceTileEntityBridge; import io.izzel.arclight.common.bridge.tileentity.AbstractFurnaceTileEntityBridge;
import io.izzel.arclight.mixin.Eject;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.bukkit.Bukkit; import net.minecraft.core.BlockPos;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v.util.CraftMagicNumbers;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceExtractEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.WorldlyContainer; import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@ -35,50 +19,75 @@ import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v.util.CraftMagicNumbers;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceExtractEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.event.inventory.FurnaceStartSmeltEvent;
import org.bukkit.inventory.CookingRecipe;
import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Mixin(AbstractFurnaceBlockEntity.class) @Mixin(AbstractFurnaceBlockEntity.class)
public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityMixin implements AbstractFurnaceTileEntityBridge { public abstract class AbstractFurnaceBlockEntityMixin extends LockableBlockEntityMixin implements AbstractFurnaceTileEntityBridge {
// @formatter:off // @formatter:off
@Shadow protected NonNullList<ItemStack> items; @Shadow protected NonNullList<ItemStack> items;
@Shadow protected abstract int getBurnDuration(ItemStack stack); @Shadow protected abstract int getBurnDuration(ItemStack stack);
@Shadow public int litTime;
@Shadow protected abstract boolean isLit(); @Shadow protected abstract boolean isLit();
@Shadow protected abstract boolean canBurn(@Nullable Recipe<?> recipeIn);
@Shadow public abstract void setRecipeUsed(@Nullable Recipe<?> recipe);
@Shadow public abstract List<Recipe<?>> getRecipesToAwardAndPopExperience(Level world, Vec3 pos);
@Shadow @Final private Object2IntOpenHashMap<ResourceLocation> recipesUsed; @Shadow @Final private Object2IntOpenHashMap<ResourceLocation> recipesUsed;
@Shadow public abstract List<Recipe<?>> getRecipesToAwardAndPopExperience(ServerLevel p_154996_, Vec3 p_154997_);
@Shadow protected abstract boolean canBurn(@org.jetbrains.annotations.Nullable Recipe<?> p_155006_, NonNullList<ItemStack> p_155007_, int p_155008_);
// @formatter:on // @formatter:on
public List<HumanEntity> transaction = new ArrayList<>(); public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK; private int maxStack = MAX_STACK;
private transient FurnaceBurnEvent arclight$burnEvent; @Eject(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;isLit()Z"),
slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;litDuration:I"),
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getBurnDuration(Lnet/minecraft/world/item/ItemStack;)I")) to = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/item/ItemStack;hasContainerItem()Z")))
public void arclight$furnaceBurn(CallbackInfo ci) { private static boolean arclight$setBurnTime(AbstractFurnaceBlockEntity furnace, CallbackInfo ci) {
ItemStack itemStack = this.items.get(1); ItemStack itemStack = furnace.getItem(1);
CraftItemStack fuel = CraftItemStack.asCraftMirror(itemStack); CraftItemStack fuel = CraftItemStack.asCraftMirror(itemStack);
FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(furnace.level, furnace.getBlockPos()), fuel, ((AbstractFurnaceTileEntityBridge) furnace).bridge$getBurnDuration(itemStack));
Bukkit.getPluginManager().callEvent(furnaceBurnEvent);
arclight$burnEvent = new FurnaceBurnEvent(CraftBlock.at(this.level, this.worldPosition), fuel, getBurnDuration(itemStack)); if (furnaceBurnEvent.isCancelled()) {
Bukkit.getPluginManager().callEvent(arclight$burnEvent);
if (arclight$burnEvent.isCancelled()) {
ci.cancel(); ci.cancel();
arclight$burnEvent = null; return false;
} }
return ((AbstractFurnaceTileEntityBridge) furnace).bridge$isLit() && furnaceBurnEvent.isBurning();
} }
@Redirect(method = "tick", at = @At(value = "INVOKE", ordinal = 4, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;isLit()Z")) @Inject(method = "serverTick", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;cookingProgress:I"))
public boolean arclight$setBurnTime(AbstractFurnaceBlockEntity furnace) { private static void arclight$startSmelt(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity furnace, CallbackInfo ci, Recipe<?> recipe) {
this.litTime = arclight$burnEvent.getBurnTime(); if (recipe != null && furnace.cookingProgress == 0) {
try { CraftItemStack source = CraftItemStack.asCraftMirror(furnace.getItem(0));
return this.isLit() && arclight$burnEvent.isBurning(); CookingRecipe<?> cookingRecipe = (CookingRecipe<?>) ((IRecipeBridge) recipe).bridge$toBukkitRecipe();
} finally {
arclight$burnEvent = null; FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(level, pos), source, cookingRecipe);
Bukkit.getPluginManager().callEvent(event);
furnace.cookingTotalTime = event.getTotalCookTime();
} }
} }
@ -87,45 +96,42 @@ public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityM
* @reason * @reason
*/ */
@Overwrite @Overwrite
@SuppressWarnings("unchecked") private boolean burn(@Nullable Recipe<?> recipe, NonNullList<ItemStack> items, int i) {
private void burn(@Nullable Recipe<?> recipe) { if (recipe != null && this.canBurn(recipe, items, i)) {
if (recipe != null && this.canBurn(recipe)) { ItemStack itemstack = items.get(0);
ItemStack itemstack = this.items.get(0); ItemStack itemstack1 = ((Recipe<WorldlyContainer>) recipe).assemble((AbstractFurnaceBlockEntity) (Object) this);
ItemStack itemstack1 = ((Recipe<WorldlyContainer>) recipe).assemble((AbstractFurnaceBlockEntity)(Object)this); ItemStack itemstack2 = items.get(2);
ItemStack itemstack2 = this.items.get(2);
CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
FurnaceSmeltEvent event = new FurnaceSmeltEvent(CraftBlock.at(level, worldPosition), source, result); FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(level, worldPosition), source, result);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(furnaceSmeltEvent);
if (event.isCancelled()) { if (furnaceSmeltEvent.isCancelled()) {
return; return false;
} }
result = event.getResult(); result = furnaceSmeltEvent.getResult();
itemstack1 = CraftItemStack.asNMSCopy(result); itemstack1 = CraftItemStack.asNMSCopy(result);
if (!itemstack1.isEmpty()) { if (!itemstack1.isEmpty()) {
if (itemstack2.isEmpty()) { if (itemstack2.isEmpty()) {
this.items.set(2, itemstack1.copy()); items.set(2, itemstack1.copy());
} else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) { } else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) {
itemstack2.grow(itemstack1.getCount()); itemstack2.grow(itemstack1.getCount());
} else { } else {
return; return false;
} }
} }
if (!this.level.isClientSide) { if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !items.get(1).isEmpty() && items.get(1).is(Items.BUCKET)) {
this.setRecipeUsed(recipe); items.set(1, new ItemStack(Items.WATER_BUCKET));
}
if (itemstack.getItem() == Blocks.WET_SPONGE.asItem() && !this.items.get(1).isEmpty() && this.items.get(1).getItem() == Items.BUCKET) {
this.items.set(1, new ItemStack(Items.WATER_BUCKET));
} }
itemstack.shrink(1); itemstack.shrink(1);
return true;
} else {
return false;
} }
} }
@ -134,13 +140,13 @@ public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityM
private static ItemStack arclight$item; private static ItemStack arclight$item;
private static int arclight$captureAmount; private static int arclight$captureAmount;
public List<Recipe<?>> a(Level world, Vec3 pos, Player entity, ItemStack itemStack, int amount) { public List<Recipe<?>> a(ServerLevel world, Vec3 vec, BlockPos pos, Player entity, ItemStack itemStack, int amount) {
try { try {
arclight$item = itemStack; arclight$item = itemStack;
arclight$captureAmount = amount; arclight$captureAmount = amount;
arclight$captureFurnace = (AbstractFurnaceBlockEntity) (Object) this; arclight$captureFurnace = (AbstractFurnaceBlockEntity) (Object) this;
arclight$capturePlayer = entity; arclight$capturePlayer = entity;
List<Recipe<?>> list = this.getRecipesToAwardAndPopExperience(world, pos); List<Recipe<?>> list = this.getRecipesToAwardAndPopExperience(world, vec);
entity.awardRecipes(list); entity.awardRecipes(list);
this.recipesUsed.clear(); this.recipesUsed.clear();
return list; return list;
@ -153,34 +159,19 @@ public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityM
} }
@Override @Override
public List<Recipe<?>> bridge$dropExp(Level world, Vec3 pos, Player entity, ItemStack itemStack, int amount) { public List<Recipe<?>> bridge$dropExp(ServerPlayer entity, ItemStack itemStack, int amount) {
return a(world, pos, entity, itemStack, amount); return a(entity.getLevel(), entity.position(), this.worldPosition, entity, itemStack, amount);
} }
/** @Redirect(method = "createExperience", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ExperienceOrb;award(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/phys/Vec3;I)V"))
* @author IzzelAliz private static void arclight$expEvent(ServerLevel level, Vec3 vec3, int amount) {
* @reason
*/
@Overwrite
private static void createExperience(Level world, Vec3 pos, int craftedAmount, float experience) {
int i = Mth.floor((float) craftedAmount * experience);
float f = Mth.frac((float) craftedAmount * experience);
if (f != 0.0F && Math.random() < (double) f) {
++i;
}
if (arclight$capturePlayer != null && arclight$captureAmount != 0) { if (arclight$capturePlayer != null && arclight$captureAmount != 0) {
FurnaceExtractEvent event = new FurnaceExtractEvent(((ServerPlayerEntityBridge) arclight$capturePlayer).bridge$getBukkitEntity(), FurnaceExtractEvent event = new FurnaceExtractEvent(((ServerPlayerEntityBridge) arclight$capturePlayer).bridge$getBukkitEntity(),
CraftBlock.at(world, arclight$captureFurnace.getBlockPos()), CraftMagicNumbers.getMaterial(arclight$item.getItem()), arclight$captureAmount, i); CraftBlock.at(level, arclight$captureFurnace.getBlockPos()), CraftMagicNumbers.getMaterial(arclight$item.getItem()), arclight$captureAmount, amount);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
i = event.getExpToDrop(); amount = event.getExpToDrop();
}
while (i > 0) {
int j = ExperienceOrb.getExperienceValue(i);
i -= j;
world.addFreshEntity(new ExperienceOrb(world, pos.x, pos.y, pos.z, j));
} }
ExperienceOrb.award(level, vec3, amount);
} }
@Override @Override
@ -217,4 +208,14 @@ public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityM
public void setMaxStackSize(int size) { public void setMaxStackSize(int size) {
this.maxStack = size; this.maxStack = size;
} }
@Override
public int bridge$getBurnDuration(ItemStack stack) {
return this.getBurnDuration(stack);
}
@Override
public boolean bridge$isLit() {
return this.isLit();
}
} }

View File

@ -1,6 +1,10 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BarrelBlockEntity;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
@ -9,13 +13,9 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BarrelBlockEntity;
@Mixin(BarrelBlockEntity.class) @Mixin(BarrelBlockEntity.class)
public abstract class BarrelTileEntityMixin extends LockableTileEntityMixin implements IInventoryBridge, Container { public abstract class BarrelBlockEntityMixin extends LockableBlockEntityMixin implements IInventoryBridge, Container {
// @formatter:off // @formatter:off
@Shadow private NonNullList<ItemStack> items; @Shadow private NonNullList<ItemStack> items;

View File

@ -1,5 +1,10 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.tileentity.BeaconTileEntityBridge;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import org.bukkit.craftbukkit.v.potion.CraftPotionUtil; import org.bukkit.craftbukkit.v.potion.CraftPotionUtil;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -7,14 +12,8 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import io.izzel.arclight.common.bridge.tileentity.BeaconTileEntityBridge;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@Mixin(BeaconBlockEntity.class) @Mixin(BeaconBlockEntity.class)
public abstract class BeaconTileEntityMixin implements BeaconTileEntityBridge { public abstract class BeaconTileEntityMixin implements BeaconTileEntityBridge {
@ -26,7 +25,7 @@ public abstract class BeaconTileEntityMixin implements BeaconTileEntityBridge {
// @formatter:on // @formatter:on
@Inject(method = "load", at = @At("RETURN")) @Inject(method = "load", at = @At("RETURN"))
public void arclight$level(BlockState state, CompoundTag compound, CallbackInfo ci) { public void arclight$level(CompoundTag compound, CallbackInfo ci) {
this.levels = compound.getInt("Levels"); this.levels = compound.getInt("Levels");
} }

View File

@ -1,9 +1,10 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.entity.MobEntityBridge; import io.izzel.arclight.common.bridge.entity.MobEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.tags.EntityTypeTags; import net.minecraft.tags.EntityTypeTags;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -32,11 +33,12 @@ import javax.annotation.Nullable;
import java.util.List; import java.util.List;
@Mixin(BeehiveBlockEntity.class) @Mixin(BeehiveBlockEntity.class)
public abstract class BeehiveTileEntityMixin extends TileEntityMixin { public abstract class BeehiveBlockEntityMixin extends BlockEntityMixin {
// @formatter:off // @formatter:off
@Shadow @Final private List<BeehiveBlockEntity.BeeData> stored; @Shadow @Final private List<BeehiveBlockEntity.BeeData> stored;
@Shadow protected abstract boolean releaseOccupant(BlockState p_235651_1_, BeehiveBlockEntity.BeeData p_235651_2_, @org.jetbrains.annotations.Nullable List<Entity> p_235651_3_, BeehiveBlockEntity.BeeReleaseStatus p_235651_4_); @Shadow @Nullable public BlockPos savedFlowerPos;
@Shadow private static boolean releaseOccupant(Level p_155137_, BlockPos p_155138_, BlockState p_155139_, BeehiveBlockEntity.BeeData p_155140_, @org.jetbrains.annotations.Nullable List<Entity> p_155141_, BeehiveBlockEntity.BeeReleaseStatus p_155142_, @org.jetbrains.annotations.Nullable BlockPos p_155143_) { return false; }
// @formatter:on // @formatter:on
public int maxBees = 3; public int maxBees = 3;
@ -56,16 +58,21 @@ public abstract class BeehiveTileEntityMixin extends TileEntityMixin {
beeEntity.setTarget(livingEntity); beeEntity.setTarget(livingEntity);
} }
public List<Entity> tryReleaseBee(BlockState blockState, BeehiveBlockEntity.BeeReleaseStatus state, boolean force) { public List<Entity> releaseBees(BlockState blockState, BeehiveBlockEntity.BeeReleaseStatus state, boolean force) {
List<Entity> list = Lists.newArrayList(); List<Entity> list = Lists.newArrayList();
this.stored.removeIf(bee -> this.releaseBee(blockState, bee, list, state, force)); this.stored.removeIf(bee -> releaseBee(level, worldPosition, blockState, bee, list, state, this.savedFlowerPos, force));
return list; return list;
} }
@Redirect(method = "addOccupantWithPresetTicks", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;size()I"))
private int arclight$maxBee(List<?> list) {
return list.size() < this.maxBees ? 1 : 3;
}
@Inject(method = "addOccupantWithPresetTicks(Lnet/minecraft/world/entity/Entity;ZI)V", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;stopRiding()V")) @Inject(method = "addOccupantWithPresetTicks(Lnet/minecraft/world/entity/Entity;ZI)V", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;stopRiding()V"))
private void arclight$beeEnterBlock(Entity entity, boolean p_226962_2_, int p_226962_3_, CallbackInfo ci) { private void arclight$beeEnterBlock(Entity entity, boolean p_226962_2_, int p_226962_3_, CallbackInfo ci) {
if (this.level != null) { if (this.level != null) {
EntityEnterBlockEvent event = new EntityEnterBlockEvent(((EntityBridge) entity).bridge$getBukkitEntity(), CraftBlock.at(this.level, this.getPos())); EntityEnterBlockEvent event = new EntityEnterBlockEvent(((EntityBridge) entity).bridge$getBukkitEntity(), CraftBlock.at(this.level, this.worldPosition));
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
if (entity instanceof Bee) { if (entity instanceof Bee) {
@ -76,28 +83,28 @@ public abstract class BeehiveTileEntityMixin extends TileEntityMixin {
} }
} }
private boolean releaseBee(BlockState blockState, BeehiveBlockEntity.BeeData bee, @Nullable List<Entity> list, BeehiveBlockEntity.BeeReleaseStatus state, boolean force) { private static boolean releaseBee(Level world, BlockPos pos, BlockState state, BeehiveBlockEntity.BeeData beeData, @Nullable List<Entity> list, BeehiveBlockEntity.BeeReleaseStatus status, @Nullable BlockPos pos1, boolean force) {
arclight$force = force; arclight$force = force;
try { try {
return this.releaseOccupant(blockState, bee, list, state); return releaseOccupant(world, pos, state, beeData, list, status, pos1);
} finally { } finally {
arclight$force = false; arclight$force = false;
} }
} }
private transient boolean arclight$force; private static transient boolean arclight$force;
@Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;isNight()Z")) @Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;isNight()Z"))
private boolean arclight$bypassNightCheck(Level world) { private static boolean arclight$bypassNightCheck(Level world) {
return !arclight$force && world.isNight(); return !arclight$force && world.isNight();
} }
@Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getType()Lnet/minecraft/world/entity/EntityType;")) @Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getType()Lnet/minecraft/world/entity/EntityType;"))
private EntityType<?> arclight$spawnFirst(Entity entity) { private static EntityType<?> arclight$spawnFirst(Entity entity, Level level) {
EntityType<?> type = entity.getType(); EntityType<?> type = entity.getType();
if (type.is(EntityTypeTags.BEEHIVE_INHABITORS)) { if (type.is(EntityTypeTags.BEEHIVE_INHABITORS)) {
((WorldBridge) this.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BEEHIVE); ((WorldBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BEEHIVE);
if (!this.level.addFreshEntity(entity)) { if (!level.addFreshEntity(entity)) {
return EntityType.ITEM_FRAME; return EntityType.ITEM_FRAME;
} else { } else {
return type; return type;
@ -107,12 +114,12 @@ public abstract class BeehiveTileEntityMixin extends TileEntityMixin {
} }
@Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) @Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private boolean arclight$addedBefore(Level world, Entity entityIn) { private static boolean arclight$addedBefore(Level world, Entity entityIn) {
return true; return true;
} }
@Inject(method = "load", at = @At("RETURN")) @Inject(method = "load", at = @At("RETURN"))
private void arclight$readMax(BlockState state, CompoundTag compound, CallbackInfo ci) { private void arclight$readMax(CompoundTag compound, CallbackInfo ci) {
if (compound.contains("Bukkit.MaxEntities")) { if (compound.contains("Bukkit.MaxEntities")) {
this.maxBees = compound.getInt("Bukkit.MaxEntities"); this.maxBees = compound.getInt("Bukkit.MaxEntities");
} }

View File

@ -1,11 +1,17 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.tileentity.TileEntityBridge; import io.izzel.arclight.common.bridge.tileentity.TileEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer; import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataTypeRegistry; import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataTypeRegistry;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -14,29 +20,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@Mixin(BlockEntity.class) @Mixin(BlockEntity.class)
public abstract class TileEntityMixin implements TileEntityBridge { public abstract class BlockEntityMixin implements TileEntityBridge {
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
public CraftPersistentDataContainer persistentDataContainer; public CraftPersistentDataContainer persistentDataContainer;
// @formatter:off // @formatter:off
@Shadow @Nullable public Level level; @Shadow @Nullable public Level level;
@Shadow protected BlockPos worldPosition; @Shadow @Final protected BlockPos worldPosition;
@Shadow public abstract BlockState getBlockState(); @Shadow public abstract BlockState getBlockState();
@Shadow public abstract void setChanged(); @Shadow public abstract void setChanged();
@Shadow public BlockPos getBlockPos() { return null; } @Shadow public BlockPos getBlockPos() { return null; }
@Shadow public abstract boolean onlyOpCanSetNbt(); @Shadow public abstract boolean onlyOpCanSetNbt();
@Shadow protected static void setChanged(Level p_155233_, BlockPos p_155234_, BlockState p_155235_) { }
// @formatter:on // @formatter:on
@Inject(method = "load", at = @At("RETURN")) @Inject(method = "load", at = @At("RETURN"))
public void arclight$loadPersistent(BlockState state, CompoundTag compound, CallbackInfo ci) { public void arclight$loadPersistent(CompoundTag compound, CallbackInfo ci) {
this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
CompoundTag persistentDataTag = compound.getCompound("PublicBukkitValues"); CompoundTag persistentDataTag = compound.getCompound("PublicBukkitValues");

View File

@ -1,5 +1,14 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.tileentity.TileEntityBridge;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
@ -13,62 +22,42 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; 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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
@Mixin(BrewingStandBlockEntity.class) @Mixin(BrewingStandBlockEntity.class)
public abstract class BrewingStandTileEntityMixin extends LockableTileEntityMixin { public abstract class BrewingStandBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off // @formatter:off
@Shadow private NonNullList<ItemStack> items; @Shadow private NonNullList<ItemStack> items;
@Shadow public int fuel;
// @formatter:on // @formatter:on
public List<HumanEntity> transaction = new ArrayList<>(); public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK; private int maxStack = MAX_STACK;
private transient Integer arclight$fuel; @Eject(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V"))
private transient boolean arclight$consume; private static void arclight$brewFuel(ItemStack stack, int count, CallbackInfo ci, Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity entity) {
BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(stack), 20);
@Inject(method = "tick", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "FIELD", ordinal = 1, target = "Lnet/minecraft/world/level/block/entity/BrewingStandBlockEntity;fuel:I"))
public void arclight$brewFuel(CallbackInfo ci, ItemStack itemStack) {
BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(this.level, this.worldPosition), CraftItemStack.asCraftMirror(itemStack), 20);
Bukkit.getServer().getPluginManager().callEvent(event); Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
ci.cancel(); ci.cancel();
arclight$fuel = null;
} else { } else {
arclight$consume = event.isConsuming(); entity.fuel = event.getFuelPower();
arclight$fuel = event.getFuelPower(); if (entity.fuel > 0 && event.isConsuming()) {
} stack.shrink(count);
}
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V"))
public void arclight$brewFuel(ItemStack itemStack, int count) {
if (arclight$fuel != null) {
this.fuel = arclight$fuel;
if (arclight$fuel > 0 && arclight$consume) {
itemStack.shrink(count);
} }
} }
arclight$fuel = null;
arclight$consume = false;
} }
@Inject(method = "doBrew", cancellable = true, at = @At("HEAD")) @Inject(method = "doBrew", cancellable = true, at = @At("HEAD"))
public void arclight$brewPotion(CallbackInfo ci) { private static void arclight$brewPotion(Level level, BlockPos pos, NonNullList<ItemStack> p_155293_, CallbackInfo ci) {
InventoryHolder owner = this.getOwner(); BrewingStandBlockEntity entity = ArclightCaptures.getTickingBlockEntity();
InventoryHolder owner = entity == null ? null : ((TileEntityBridge) entity).bridge$getOwner();
if (owner != null) { if (owner != null) {
BrewEvent event = new BrewEvent(CraftBlock.at(level, worldPosition), (BrewerInventory) owner.getInventory(), this.fuel); BrewEvent event = new BrewEvent(CraftBlock.at(level, pos), (BrewerInventory) owner.getInventory(), entity.fuel);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
ci.cancel(); ci.cancel();

View File

@ -0,0 +1,64 @@
package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.Containers;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.event.block.BlockCookEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(CampfireBlockEntity.class)
public abstract class CampfireTileEntityMixin extends BlockEntityMixin {
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public static void cookTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity entity) {
boolean flag = false;
for (int i = 0; i < entity.getItems().size(); ++i) {
ItemStack itemstack = entity.getItems().get(i);
if (!itemstack.isEmpty()) {
flag = true;
if (entity.cookingProgress[i] >= entity.cookingTime[i]) {
Container container = new SimpleContainer(itemstack);
ItemStack itemstack1 = level.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, container, level).map((p_155305_) -> {
return p_155305_.assemble(container);
}).orElse(itemstack);
CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, pos), source, result);
Bukkit.getPluginManager().callEvent(blockCookEvent);
if (blockCookEvent.isCancelled()) {
return;
}
result = blockCookEvent.getResult();
itemstack1 = CraftItemStack.asNMSCopy(result);
Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), itemstack1);
entity.getItems().set(i, ItemStack.EMPTY);
level.sendBlockUpdated(pos, state, state, 3);
}
}
}
if (flag) {
setChanged(level, pos, state);
}
}
}

View File

@ -0,0 +1,65 @@
package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList;
import java.util.List;
@Mixin(ChestBlockEntity.class)
public abstract class ChestBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off
@Shadow private NonNullList<ItemStack> items;
// @formatter:on
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = IInventoryBridge.MAX_STACK;
@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 int getMaxStackSize() {
if (maxStack == 0) maxStack = IInventoryBridge.MAX_STACK;
return maxStack;
}
@Override
public void setMaxStackSize(int size) {
this.maxStack = size;
}
@Override
public boolean onlyOpCanSetNbt() {
return true;
}
}

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import io.izzel.arclight.common.bridge.command.CommandSourceBridge; import io.izzel.arclight.common.bridge.command.CommandSourceBridge;

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.command.ICommandSourceBridge; import io.izzel.arclight.common.bridge.command.ICommandSourceBridge;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.Shadow;
@Mixin(targets = "net/minecraft/world/level/block/entity/CommandBlockEntity$1") @Mixin(targets = "net/minecraft/world/level/block/entity/CommandBlockEntity$1")
public class CommandBlockTileEntity1Mixin implements ICommandSourceBridge { public class CommandBlockTileEntity1Mixin implements ICommandSourceBridge {
@Shadow(aliases = {"this$0", "field_145767_a"}, remap = false) private CommandBlockEntity outerThis; @Shadow(aliases = {"this$0", "f_59153_"}, remap = false) private CommandBlockEntity outerThis;
public CommandSender getBukkitSender(CommandSourceStack wrapper) { public CommandSender getBukkitSender(CommandSourceStack wrapper) {
return new CraftBlockCommandSender(wrapper, outerThis); return new CraftBlockCommandSender(wrapper, outerThis);

View File

@ -1,6 +1,11 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.EntityPotionEffectEvent;
@ -10,28 +15,23 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Iterator;
import java.util.List; import java.util.List;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
import net.minecraft.world.phys.AABB;
@Mixin(ConduitBlockEntity.class) @Mixin(ConduitBlockEntity.class)
public abstract class ConduitTileEntityMixin extends TileEntityMixin { public abstract class ConduitBlockEntityMixin extends BlockEntityMixin {
@Inject(method = "applyEffects", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) @Inject(method = "applyEffects", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z"))
public void arclight$addEntity(CallbackInfo ci, int i, int j, int k, int l, int i1, AABB bb, List<?> list, private static void arclight$addEntity(CallbackInfo ci, Player playerEntity) {
Iterator<?> iterator, Player playerEntity) {
((PlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONDUIT); ((PlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONDUIT);
} }
@Inject(method = "updateDestroyTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) @Inject(method = "updateDestroyTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
public void arclight$attackReason(CallbackInfo ci) { private static void arclight$attackReason(Level level, BlockPos pos, BlockState p_155411_, List<BlockPos> p_155412_, ConduitBlockEntity p_155413_, CallbackInfo ci) {
CraftEventFactory.blockDamage = CraftBlock.at(this.level, this.worldPosition); CraftEventFactory.blockDamage = CraftBlock.at(level, pos);
} }
@Inject(method = "updateDestroyTarget", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) @Inject(method = "updateDestroyTarget", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
public void arclight$attackReasonReset(CallbackInfo ci) { private static void arclight$attackReasonReset(CallbackInfo ci) {
CraftEventFactory.blockDamage = null; CraftEventFactory.blockDamage = null;
} }
} }

View File

@ -1,5 +1,8 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
@ -8,12 +11,9 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
@Mixin(DispenserBlockEntity.class) @Mixin(DispenserBlockEntity.class)
public abstract class DispenserTileEntityMixin extends LockableTileEntityMixin { public abstract class DispenserBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off // @formatter:off
@Shadow private NonNullList<ItemStack> items; @Shadow private NonNullList<ItemStack> items;

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.network.play.ServerPlayNetHandlerBridge; import io.izzel.arclight.common.bridge.network.play.ServerPlayNetHandlerBridge;
@ -6,7 +6,9 @@ import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.entity.CraftPlayer;
@ -19,17 +21,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(TheEndGatewayBlockEntity.class) @Mixin(TheEndGatewayBlockEntity.class)
public abstract class EndGatewayTileEntityMixin extends TileEntityMixin { public abstract class EndGatewayBlockEntityMixin extends BlockEntityMixin {
// @formatter:off // @formatter:off
@Shadow public abstract void triggerCooldown(); @Shadow private static void triggerCooldown(Level p_155850_, BlockPos p_155851_, BlockState p_155852_, TheEndGatewayBlockEntity p_155853_) { }
// @formatter:on // @formatter:on
@Inject(method = "teleportEntity", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportToWithTicket(DDD)V")) @Inject(method = "teleportEntity", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPortalCooldown()V"))
public void arclight$portal(Entity entityIn, CallbackInfo ci, BlockPos pos) { private static void arclight$portal(Level level, BlockPos pos, BlockState state, Entity entityIn, TheEndGatewayBlockEntity entity, CallbackInfo ci) {
if (entityIn instanceof ServerPlayer) { if (entityIn instanceof ServerPlayer) {
CraftPlayer player = ((ServerPlayerEntityBridge) entityIn).bridge$getBukkitEntity(); CraftPlayer player = ((ServerPlayerEntityBridge) entityIn).bridge$getBukkitEntity();
Location location = new Location(((WorldBridge) level).bridge$getWorld(), pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); Location location = new Location(((WorldBridge) level).bridge$getWorld(), pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D);
location.setPitch(player.getLocation().getPitch()); location.setPitch(player.getLocation().getPitch());
location.setYaw(player.getLocation().getYaw()); location.setYaw(player.getLocation().getYaw());
@ -40,8 +42,9 @@ public abstract class EndGatewayTileEntityMixin extends TileEntityMixin {
return; return;
} }
entityIn.setPortalCooldown();
((ServerPlayNetHandlerBridge) (((ServerPlayer) entityIn)).connection).bridge$teleport(event.getTo()); ((ServerPlayNetHandlerBridge) (((ServerPlayer) entityIn)).connection).bridge$teleport(event.getTo());
this.triggerCooldown(); // CraftBukkit - call at end of method triggerCooldown(level, pos, state, entity);
ci.cancel(); ci.cancel();
} }
} }

View File

@ -1,7 +1,21 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import io.izzel.arclight.common.bridge.tileentity.TileEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.vehicle.MinecartHopper;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.Hopper;
import net.minecraft.world.level.block.entity.HopperBlockEntity;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.inventory.CraftInventoryDoubleChest; import org.bukkit.craftbukkit.v.inventory.CraftInventoryDoubleChest;
@ -18,45 +32,24 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.vehicle.MinecartHopper;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.Hopper;
import net.minecraft.world.level.block.entity.HopperBlockEntity;
@Mixin(HopperBlockEntity.class) @Mixin(HopperBlockEntity.class)
public abstract class HopperTileEntityMixin extends LockableTileEntityMixin { public abstract class HopperBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off // @formatter:off
@Shadow private NonNullList<ItemStack> items; @Shadow private NonNullList<ItemStack> items;
@Shadow public abstract void setCooldown(int ticks);
@Shadow public abstract void setItem(int index, ItemStack stack); @Shadow public abstract void setItem(int index, ItemStack stack);
// @formatter:on // @formatter:on
public List<HumanEntity> transaction = new ArrayList<>(); public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK; private int maxStack = MAX_STACK;
private static transient boolean arclight$moveItem; @Eject(method = "ejectItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;"))
private static ItemStack arclight$moveItem(Container source, Container destination, ItemStack stack, Direction direction, CallbackInfoReturnable<Boolean> cir, Level level) {
@Inject(method = "ejectItems", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) HopperBlockEntity entity = ArclightCaptures.getTickingBlockEntity();
public void arclight$returnIfMoveFail(CallbackInfoReturnable<Boolean> cir, Container inv, Direction direction, int i, ItemStack itemStack) {
if (arclight$moveItem) {
this.setItem(i, itemStack);
cir.setReturnValue(false);
}
arclight$moveItem = false;
}
@Redirect(method = "ejectItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;"))
public ItemStack arclight$moveItem(Container source, Container destination, ItemStack stack, Direction direction) {
CraftItemStack original = CraftItemStack.asCraftMirror(stack); CraftItemStack original = CraftItemStack.asCraftMirror(stack);
Inventory destinationInventory; Inventory destinationInventory;
@ -67,26 +60,19 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
destinationInventory = ((IInventoryBridge) destination).getOwnerInventory(); destinationInventory = ((IInventoryBridge) destination).getOwnerInventory();
} }
InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), original.clone(), destinationInventory, true); InventoryMoveItemEvent event = new InventoryMoveItemEvent(((TileEntityBridge) entity).bridge$getOwner().getInventory(), original.clone(), destinationInventory, true);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (arclight$moveItem = event.isCancelled()) { if (event.isCancelled()) {
this.setCooldown(8); // Delay hopper checks entity.setCooldown(((WorldBridge) level).bridge$spigotConfig().hopperTransfer); // Delay hopper checks
cir.setReturnValue(false);
return null; return null;
} }
return HopperBlockEntity.addItem(source, destination, CraftItemStack.asNMSCopy(event.getItem()), direction); return HopperBlockEntity.addItem(source, destination, CraftItemStack.asNMSCopy(event.getItem()), direction);
} }
@Inject(method = "tryTakeInItemFromSlot", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;"))
private static void arclight$returnIfPullFail(Hopper hopper, Container inventoryIn, int index, Direction direction, CallbackInfoReturnable<Boolean> cir, ItemStack item, ItemStack item1) {
if (arclight$moveItem) {
inventoryIn.setItem(index, item1);
cir.setReturnValue(false);
}
arclight$moveItem = false;
}
@Redirect(method = "tryTakeInItemFromSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) @Redirect(method = "tryTakeInItemFromSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;"))
private static ItemStack arclight$pullItem(Container source, Container destination, ItemStack stack, Direction direction) { private static ItemStack arclight$pullItem(Container source, Container destination, ItemStack stack, Direction direction, CallbackInfoReturnable<Boolean> cir, Hopper hopper, Container inv, int index) {
ItemStack origin = inv.getItem(index).copy();
CraftItemStack original = CraftItemStack.asCraftMirror(stack); CraftItemStack original = CraftItemStack.asCraftMirror(stack);
Inventory sourceInventory; Inventory sourceInventory;
@ -99,18 +85,20 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, original.clone(), ((IInventoryBridge) destination).getOwnerInventory(), false); InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, original.clone(), ((IInventoryBridge) destination).getOwnerInventory(), false);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (arclight$moveItem = event.isCancelled()) { if (event.isCancelled()) {
inv.setItem(index, origin);
if (destination instanceof HopperBlockEntity) { if (destination instanceof HopperBlockEntity) {
((HopperBlockEntity) destination).setCooldown(8); // Delay hopper checks ((HopperBlockEntity) destination).setCooldown(8); // Delay hopper checks
} else if (destination instanceof MinecartHopper) { } else if (destination instanceof MinecartHopper) {
((MinecartHopper) destination).setCooldown(4); // Delay hopper minecart checks ((MinecartHopper) destination).setCooldown(4); // Delay hopper minecart checks
} }
cir.setReturnValue(false);
return null; return null;
} }
return HopperBlockEntity.addItem(source, destination, CraftItemStack.asNMSCopy(event.getItem()), direction); return HopperBlockEntity.addItem(source, destination, CraftItemStack.asNMSCopy(event.getItem()), direction);
} }
@Inject(method = "addItem", cancellable = true, at = @At("HEAD")) @Inject(method = "addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/entity/item/ItemEntity;)Z", cancellable = true, at = @At("HEAD"))
private static void arclight$pickupItem(Container inventory, ItemEntity itemEntity, CallbackInfoReturnable<Boolean> cir) { private static void arclight$pickupItem(Container inventory, ItemEntity itemEntity, CallbackInfoReturnable<Boolean> cir) {
InventoryPickupItemEvent event = new InventoryPickupItemEvent(((IInventoryBridge) inventory).getOwnerInventory(), (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity()); InventoryPickupItemEvent event = new InventoryPickupItemEvent(((IInventoryBridge) inventory).getOwnerInventory(), (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity());
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.command.ICommandSourceBridge; import io.izzel.arclight.common.bridge.command.ICommandSourceBridge;
import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge;
@ -33,7 +33,7 @@ import javax.annotation.Nullable;
import java.util.UUID; import java.util.UUID;
@Mixin(LecternBlockEntity.class) @Mixin(LecternBlockEntity.class)
public abstract class LecternTileEntityMixin extends TileEntityMixin implements CommandSource, ICommandSourceBridge { public abstract class LecternBlockEntityMixin extends BlockEntityMixin implements CommandSource, ICommandSourceBridge {
// @formatter:off // @formatter:off
@Shadow @Final public Container bookAccess; @Shadow @Final public Container bookAccess;

View File

@ -1,28 +1,28 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import io.izzel.arclight.common.bridge.tileentity.TileEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.block.LecternBlock;
import net.minecraft.world.level.block.entity.LecternBlockEntity;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import io.izzel.arclight.common.bridge.tileentity.TileEntityBridge;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.block.LecternBlock;
import net.minecraft.world.level.block.entity.LecternBlockEntity;
@Mixin(targets = "net/minecraft/world/level/block/entity/LecternBlockEntity$1") @Mixin(targets = "net/minecraft/world/level/block/entity/LecternBlockEntity$1")
public abstract class LecternTileEntity1Mixin implements IInventoryBridge, Container { public abstract class LecternTileEntity1Mixin implements IInventoryBridge, Container {
@Shadow(aliases = {"this$0", "field_214028_a"}, remap = false) private LecternBlockEntity outerThis; @Shadow(aliases = {"this$0", "f_59572_"}, remap = false) private LecternBlockEntity outerThis;
public List<HumanEntity> transaction = new ArrayList<>(); public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = 1; private int maxStack = 1;

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import net.minecraft.world.Container; import net.minecraft.world.Container;
@ -9,7 +9,7 @@ import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@Mixin(BaseContainerBlockEntity.class) @Mixin(BaseContainerBlockEntity.class)
public abstract class LockableTileEntityMixin extends TileEntityMixin implements IInventoryBridge, Container { public abstract class LockableBlockEntityMixin extends BlockEntityMixin implements IInventoryBridge, Container {
@Override @Override
public Location getLocation() { public Location getLocation() {

View File

@ -1,5 +1,9 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import net.minecraft.core.NonNullList;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
@ -11,13 +15,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.core.NonNullList;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
@Mixin(ShulkerBoxBlockEntity.class) @Mixin(ShulkerBoxBlockEntity.class)
public abstract class ShulkerBoxTileEntityMixin extends LockableTileEntityMixin { public abstract class ShulkerBoxBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off // @formatter:off
@Shadow private NonNullList<ItemStack> itemStacks; @Shadow private NonNullList<ItemStack> itemStacks;

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.tileentity; package io.izzel.arclight.common.mixin.core.world.level.block.entity;
import io.izzel.arclight.common.bridge.command.ICommandSourceBridge; import io.izzel.arclight.common.bridge.command.ICommandSourceBridge;
import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge;
@ -9,7 +9,6 @@ import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec2;
@ -22,13 +21,13 @@ import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.UUID; import java.util.UUID;
@Mixin(SignBlockEntity.class) @Mixin(SignBlockEntity.class)
public abstract class SignTileEntityMixin extends TileEntityMixin implements SignTileEntityBridge, CommandSource, ICommandSourceBridge { public abstract class SignBlockEntityMixin extends BlockEntityMixin implements SignTileEntityBridge, CommandSource, ICommandSourceBridge {
// @formatter:off // @formatter:off
@Override @Accessor("isEditable") public abstract void bridge$setEditable(boolean editable); @Override @Accessor("isEditable") public abstract void bridge$setEditable(boolean editable);
@ -39,10 +38,10 @@ public abstract class SignTileEntityMixin extends TileEntityMixin implements Sig
return new CommandSourceStack(this, vec3d, vec2f, world, i, s, component, server, entity); return new CommandSourceStack(this, vec3d, vec2f, world, i, s, component, server, entity);
} }
@Inject(method = "setColor", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;sendBlockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;I)V")) @Inject(method = "markUpdated", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;sendBlockUpdated(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;I)V"))
public void arclight$setColor(DyeColor newColor, CallbackInfoReturnable<Boolean> cir) { public void arclight$setColor(CallbackInfo ci) {
if (this.level == null) { if (this.level == null) {
cir.setReturnValue(true); ci.cancel();
} }
} }

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.world.border; package io.izzel.arclight.common.mixin.core.world.level.border;
import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge; import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.world.biome; package io.izzel.arclight.common.mixin.core.world.level.chunk;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
@ -8,17 +8,21 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@Mixin(ChunkBiomeContainer.class) @Mixin(ChunkBiomeContainer.class)
public class BiomeContainerMixin { public class ChunkBiomeContainerMixin {
// @formatter:off // @formatter:off
@Shadow @Final private Biome[] biomes; @Shadow @Final private Biome[] biomes;
@Shadow @Final private static int WIDTH_BITS; @Shadow @Final private static int WIDTH_BITS;
@Shadow @Final private static int HORIZONTAL_MASK;
@Shadow @Final private int quartMinY;
@Shadow @Final private int quartHeight;
// @formatter:on // @formatter:on
public void setBiome(int i, int j, int k, Biome biome) { public void setBiome(int i, int j, int k, Biome biome) {
int l = i & ChunkBiomeContainer.HORIZONTAL_MASK; int l = i & HORIZONTAL_MASK;
int i2 = Mth.clamp(j, 0, ChunkBiomeContainer.VERTICAL_MASK); int i1 = Mth.clamp(j - this.quartMinY, 0, this.quartHeight);
int j2 = k & ChunkBiomeContainer.HORIZONTAL_MASK; int j1 = k & HORIZONTAL_MASK;
this.biomes[i2 << WIDTH_BITS + WIDTH_BITS | j2 << WIDTH_BITS | l] = biome;
this.biomes[i1 << WIDTH_BITS + WIDTH_BITS | j1 << WIDTH_BITS | l] = biome;
} }
} }

View File

@ -1,7 +1,21 @@
package io.izzel.arclight.common.mixin.core.world.chunk; package io.izzel.arclight.common.mixin.core.world.level.chunk;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.chunk.ChunkBridge; import io.izzel.arclight.common.bridge.world.chunk.ChunkBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.TickList;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.material.Fluid;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.CraftChunk; import org.bukkit.craftbukkit.v.CraftChunk;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer; import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer;
@ -17,56 +31,45 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.core.BlockPos; import java.util.Map;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.ClassInstanceMultiMap;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.TickList;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.material.Fluid;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@Mixin(LevelChunk.class) @Mixin(LevelChunk.class)
public abstract class ChunkMixin implements ChunkBridge { public abstract class LevelChunkMixin implements ChunkBridge {
// @formatter:off // @formatter:off
@Shadow @Nullable public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving); @Shadow @Nullable public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving);
@Shadow @Final public Level level; @Shadow @Final public Level level;
@Shadow @Final private ChunkPos chunkPos; @Shadow @Final private ChunkPos chunkPos;
@Shadow private volatile boolean unsaved; @Shadow private volatile boolean unsaved;
@Shadow private boolean lastSaveHadEntities; @Shadow @Final private Map<BlockPos, CompoundTag> pendingBlockEntities;
@Shadow private long lastSaveTime;
@Shadow @Final public ClassInstanceMultiMap<Entity>[] entitySections;
// @formatter:on // @formatter:on
public org.bukkit.Chunk bukkitChunk; public org.bukkit.Chunk bukkitChunk;
public boolean mustNotSave; public boolean mustNotSave;
public boolean needsDecoration; public boolean needsDecoration;
private transient boolean arclight$doPlace; private transient boolean arclight$doPlace;
public ServerLevel $$world; public ServerLevel $$level;
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
public final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); public final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
@Inject(method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/world/level/chunk/ChunkBiomeContainer;Lnet/minecraft/world/level/chunk/UpgradeData;Lnet/minecraft/world/level/TickList;Lnet/minecraft/world/level/TickList;J[Lnet/minecraft/world/level/chunk/LevelChunkSection;Ljava/util/function/Consumer;)V", at = @At("RETURN")) @Inject(method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/world/level/chunk/ChunkBiomeContainer;Lnet/minecraft/world/level/chunk/UpgradeData;Lnet/minecraft/world/level/TickList;Lnet/minecraft/world/level/TickList;J[Lnet/minecraft/world/level/chunk/LevelChunkSection;Ljava/util/function/Consumer;)V", at = @At("RETURN"))
private void arclight$init(Level worldIn, ChunkPos chunkPosIn, ChunkBiomeContainer biomeContainerIn, UpgradeData upgradeDataIn, TickList<Block> tickBlocksIn, TickList<Fluid> tickFluidsIn, long inhabitedTimeIn, LevelChunkSection[] sectionsIn, Consumer<LevelChunk> postLoadConsumerIn, CallbackInfo ci) { private void arclight$init(Level worldIn, ChunkPos chunkPosIn, ChunkBiomeContainer biomeContainerIn, UpgradeData upgradeDataIn, TickList<Block> tickBlocksIn, TickList<Fluid> tickFluidsIn, long inhabitedTimeIn, LevelChunkSection[] sectionsIn, Consumer<LevelChunk> postLoadConsumerIn, CallbackInfo ci) {
this.$$world = ((ServerLevel) worldIn); this.$$level = ((ServerLevel) worldIn);
bridge$setBukkitChunk(new CraftChunk((LevelChunk) (Object) this)); bridge$setBukkitChunk(new CraftChunk((LevelChunk) (Object) this));
} }
@SuppressWarnings("unchecked") @Inject(method = "<init>(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ProtoChunk;Ljava/util/function/Consumer;)V", at = @At("RETURN"))
public List<Entity>[] getEntitySlices() { private void arclight$init(ServerLevel p_156365_, ProtoChunk p_156366_, Consumer<LevelChunk> p_156367_, CallbackInfo ci) {
return Arrays.stream(this.entitySections).map(ClassInstanceMultiMap::getAllInstances).toArray(List[]::new); this.needsDecoration = true;
}
@Inject(method = "removeBlockEntity", at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Ljava/util/Map;remove(Ljava/lang/Object;)Ljava/lang/Object;"))
private void arclight$remove(BlockPos pos, CallbackInfo ci) {
if (!pendingBlockEntities.isEmpty()) {
pendingBlockEntities.remove(pos);
}
} }
public org.bukkit.Chunk getBukkitChunk() { public org.bukkit.Chunk getBukkitChunk() {
@ -169,12 +172,6 @@ public abstract class ChunkMixin implements ChunkBridge {
this.mustNotSave = !unloadEvent.isSaveChunk(); this.mustNotSave = !unloadEvent.isSaveChunk();
} }
@Inject(method = "<init>(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/chunk/ProtoChunk;)V",
at = @At("RETURN"))
public void arclight$setNeedsDecoration(Level worldIn, ProtoChunk primer, CallbackInfo ci) {
this.needsDecoration = true;
}
@Redirect(method = "setBlockState", at = @At(value = "FIELD", ordinal = 1, target = "Lnet/minecraft/world/level/Level;isClientSide:Z")) @Redirect(method = "setBlockState", at = @At(value = "FIELD", ordinal = 1, target = "Lnet/minecraft/world/level/Level;isClientSide:Z"))
public boolean arclight$redirectIsRemote(Level world) { public boolean arclight$redirectIsRemote(Level world) {
return world.isClientSide && this.arclight$doPlace; return world.isClientSide && this.arclight$doPlace;
@ -186,6 +183,6 @@ public abstract class ChunkMixin implements ChunkBridge {
*/ */
@Overwrite @Overwrite
public boolean isUnsaved() { public boolean isUnsaved() {
return !this.mustNotSave && (this.unsaved || this.lastSaveHadEntities && this.level.getGameTime() != this.lastSaveTime); return !this.mustNotSave && this.unsaved;
} }
} }

View File

@ -0,0 +1,26 @@
package io.izzel.arclight.common.mixin.core.world.level.chunk;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(targets = "net/minecraft/world/level/chunk/LevelChunk$BoundTickingBlockEntity")
public class LevelChunk_BoundTickingBlockEntityMixin<T extends BlockEntity> {
@Shadow @Final private T blockEntity;
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/entity/BlockEntity;)V"))
private void arclight$captureBlockEntity(CallbackInfo ci) {
ArclightCaptures.captureTickingBlockEntity(this.blockEntity);
}
@Inject(method = "tick", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/entity/BlockEntity;)V"))
private void arclight$resetBlockEntity(CallbackInfo ci) {
ArclightCaptures.resetTickingBlockEntity();
}
}

View File

@ -1,17 +1,17 @@
package io.izzel.arclight.common.mixin.core.world.chunk.storage; package io.izzel.arclight.common.mixin.core.world.level.chunk.storage;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.storage.ChunkStorage; import net.minecraft.world.level.chunk.storage.ChunkStorage;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler;
import net.minecraft.world.level.storage.DimensionDataStorage; import net.minecraft.world.level.storage.DimensionDataStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
import java.util.List; import java.util.List;
@Mixin(ChunkStorage.class) @Mixin(ChunkStorage.class)

View File

@ -1,6 +1,10 @@
package io.izzel.arclight.common.mixin.core.world.chunk.storage; package io.izzel.arclight.common.mixin.core.world.level.chunk.storage;
import io.izzel.arclight.common.bridge.world.chunk.storage.RegionFileCacheBridge; import io.izzel.arclight.common.bridge.world.chunk.storage.RegionFileCacheBridge;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.storage.RegionFile;
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -11,10 +15,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.storage.RegionFile;
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
@Mixin(RegionFileStorage.class) @Mixin(RegionFileStorage.class)
public abstract class RegionFileCacheMixin implements RegionFileCacheBridge { public abstract class RegionFileCacheMixin implements RegionFileCacheBridge {

View File

@ -1,8 +1,15 @@
package io.izzel.arclight.common.mixin.core.world; package io.izzel.arclight.common.mixin.core.world.level.portal;
import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.world.TeleporterBridge; import io.izzel.arclight.common.bridge.world.TeleporterBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
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.Entity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.portal.PortalForcer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
@ -20,16 +27,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
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.Entity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.portal.PortalForcer;
@Mixin(PortalForcer.class) @Mixin(PortalForcer.class)
public abstract class TeleporterMixin implements TeleporterBridge { public abstract class PortalForcerMixin implements TeleporterBridge {
// @formatter:off // @formatter:off
@Shadow public abstract Optional<BlockUtil.FoundRectangle> createPortal(BlockPos pos, Direction.Axis axis); @Shadow public abstract Optional<BlockUtil.FoundRectangle> createPortal(BlockPos pos, Direction.Axis axis);
@ -58,7 +58,7 @@ public abstract class TeleporterMixin implements TeleporterBridge {
return findPortal(pos, searchRadius); return findPortal(pos, searchRadius);
} }
@ModifyArg(method = "makePortal", index = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/BlockPos;func_243514_a(Lnet/minecraft/util/math/BlockPos;ILnet/minecraft/util/Direction;Lnet/minecraft/util/Direction;)Ljava/lang/Iterable;")) @ModifyArg(method = "createPortal", index = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;spiralAround(Lnet/minecraft/core/BlockPos;ILnet/minecraft/core/Direction;Lnet/minecraft/core/Direction;)Ljava/lang/Iterable;"))
private int arclight$changeRadius(int i) { private int arclight$changeRadius(int i) {
return this.arclight$createRadius == -1 ? i : this.arclight$createRadius; return this.arclight$createRadius == -1 ? i : this.arclight$createRadius;
} }

View File

@ -1,10 +1,15 @@
package io.izzel.arclight.common.mixin.core.world.storage; package io.izzel.arclight.common.mixin.core.world.level.saveddata.maps;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge; import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.map.CraftMapView; import org.bukkit.craftbukkit.v.map.CraftMapView;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -13,40 +18,39 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
@Mixin(MapItemSavedData.class) @Mixin(MapItemSavedData.class)
public abstract class MapDataMixin implements MapDataBridge { public abstract class MapDataMixin implements MapDataBridge {
// @formatter:off // @formatter:off
@Shadow public ResourceKey<Level> dimension; @Shadow @Final public ResourceKey<Level> dimension;
@Shadow @Final private List<MapItemSavedData.HoldingPlayer> carriedBy;
// @formatter:on // @formatter:on
public CraftMapView mapView; public CraftMapView mapView;
private CraftServer server; private CraftServer server;
private UUID uniqueId; private UUID uniqueId;
public String id;
@Inject(method = "<init>", at = @At("RETURN")) @Inject(method = "<init>", at = @At("RETURN"))
public void arclight$init(String mapname, CallbackInfo ci) { public void arclight$init(int p_164768_, int p_164769_, byte p_164770_, boolean p_164771_, boolean p_164772_, boolean p_164773_, ResourceKey<Level> p_164774_, CallbackInfo ci) {
this.mapView = new CraftMapView((MapItemSavedData) (Object) this); this.mapView = new CraftMapView((MapItemSavedData) (Object) this);
this.server = (CraftServer) Bukkit.getServer(); this.server = (CraftServer) Bukkit.getServer();
} }
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Redirect(method = "load", at = @At(value = "INVOKE", target = "Ljava/util/Optional;orElseThrow(Ljava/util/function/Supplier;)Ljava/lang/Object;")) @Redirect(method = "load", at = @At(value = "INVOKE", target = "Ljava/util/Optional;orElseThrow(Ljava/util/function/Supplier;)Ljava/lang/Object;"))
public Object arclight$customDimension(Optional<ResourceKey<Level>> optional, Supplier<?> exceptionSupplier, CompoundTag nbt) { private static Object arclight$customDimension(Optional<ResourceKey<Level>> optional, Supplier<?> exceptionSupplier, CompoundTag nbt) {
return optional.orElseGet(() -> { return optional.orElseGet(() -> {
long least = nbt.getLong("UUIDLeast"); long least = nbt.getLong("UUIDLeast");
long most = nbt.getLong("UUIDMost"); long most = nbt.getLong("UUIDMost");
if (least != 0L && most != 0L) { if (least != 0L && most != 0L) {
this.uniqueId = new UUID(most, least); UUID uniqueId = new UUID(most, least);
CraftWorld world = (CraftWorld) this.server.getWorld(this.uniqueId); CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId);
if (world != null) { if (world != null) {
return world.getHandle().dimension(); return world.getHandle().dimension();
} }
@ -71,6 +75,16 @@ public abstract class MapDataMixin implements MapDataBridge {
} }
} }
@Override
public void bridge$setId(String id) {
this.id = id;
}
@Override
public List<MapItemSavedData.HoldingPlayer> bridge$getCarriedBy() {
return this.carriedBy;
}
@Override @Override
public CraftMapView bridge$getMapView() { public CraftMapView bridge$getMapView() {
return mapView; return mapView;

View File

@ -1,6 +1,12 @@
package io.izzel.arclight.common.mixin.core.world.storage; package io.izzel.arclight.common.mixin.core.world.level.saveddata.maps;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.saveddata.maps.MapDecoration;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import org.bukkit.craftbukkit.v.map.RenderData; import org.bukkit.craftbukkit.v.map.RenderData;
import org.bukkit.craftbukkit.v.util.CraftChatMessage; import org.bukkit.craftbukkit.v.util.CraftChatMessage;
import org.bukkit.map.MapCursor; import org.bukkit.map.MapCursor;
@ -8,21 +14,13 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.MapItem;
import net.minecraft.world.level.saveddata.maps.MapDecoration;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@Mixin(MapItemSavedData.HoldingPlayer.class) @Mixin(MapItemSavedData.HoldingPlayer.class)
public class MapData_MapInfoMixin { public abstract class MapData_MapInfoMixin {
// @formatter:off // @formatter:off
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "field_176107_c"}, remap = false) private MapItemSavedData outerThis; @SuppressWarnings("target") @Shadow(aliases = {"this$0", "field_176107_c"}, remap = false) private MapItemSavedData outerThis;
@ -33,6 +31,8 @@ public class MapData_MapInfoMixin {
@Shadow private int maxDirtyY; @Shadow private int maxDirtyY;
@Shadow private int tick; @Shadow private int tick;
@Shadow @Final public Player player; @Shadow @Final public Player player;
@Shadow private boolean dirtyDecorations;
@Shadow protected abstract MapItemSavedData.MapPatch createPatch();
// @formatter:on // @formatter:on
/** /**
@ -41,20 +41,32 @@ public class MapData_MapInfoMixin {
*/ */
@Overwrite @Overwrite
@Nullable @Nullable
public Packet<?> nextUpdatePacket(ItemStack stack) { public Packet<?> nextUpdatePacket(int i) {
RenderData render = ((MapDataBridge) outerThis).bridge$getMapView().render(((ServerPlayerEntityBridge) this.player).bridge$getBukkitEntity()); // CraftBukkit RenderData render = ((MapDataBridge) outerThis).bridge$getMapView().render(((ServerPlayerEntityBridge) this.player).bridge$getBukkitEntity()); // CraftBukkit
Collection<MapDecoration> icons = new ArrayList<>(); MapItemSavedData.MapPatch patch;
for (MapCursor cursor : render.cursors) {
if (cursor.isVisible()) {
icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()),
cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption())));
}
}
if (this.dirtyData) { if (this.dirtyData) {
this.dirtyData = false; this.dirtyData = false;
return new ClientboundMapItemDataPacket(MapItem.getMapId(stack), outerThis.scale, outerThis.trackingPosition, outerThis.locked, icons, render.buffer, this.minDirtyX, this.minDirtyY, this.maxDirtyX + 1 - this.minDirtyX, this.maxDirtyY + 1 - this.minDirtyY); var colors = outerThis.colors;
outerThis.colors = render.buffer;
patch = this.createPatch();
outerThis.colors = colors;
} else { } else {
return this.tick++ % 5 == 0 ? new ClientboundMapItemDataPacket(MapItem.getMapId(stack), outerThis.scale, outerThis.trackingPosition, outerThis.locked, icons, render.buffer, 0, 0, 0, 0) : null; patch = null;
} }
Collection<MapDecoration> icons;
if (this.tick++ % 5 == 0) {
this.dirtyDecorations = false;
icons = new ArrayList<>();
for (MapCursor cursor : render.cursors) {
if (cursor.isVisible()) {
icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()),
cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption())));
}
}
} else {
icons = null;
}
return icons == null && patch == null ? null : new ClientboundMapItemDataPacket(i, outerThis.scale, outerThis.locked, icons, patch);
} }
} }

View File

@ -4,10 +4,10 @@ import io.izzel.arclight.common.bridge.entity.MobEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge; import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
@ -20,7 +20,6 @@ import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.ForgeEventFactory;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -28,30 +27,26 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.Optional; import java.util.Optional;
@Mixin(BaseSpawner.class) @Mixin(BaseSpawner.class)
public abstract class AbstractSpawnerMixin { public abstract class AbstractSpawnerMixin {
// @formatter:off // @formatter:off
@Shadow public abstract Level getLevel(); @Shadow public WeightedRandomList<SpawnData> spawnPotentials;
@Shadow @Final public List<SpawnData> spawnPotentials;
@Shadow protected abstract boolean isNearPlayer();
@Shadow private double oSpin;
@Shadow private double spin;
@Shadow public abstract BlockPos getPos();
@Shadow public int spawnDelay; @Shadow public int spawnDelay;
@Shadow protected abstract void delay();
@Shadow public int spawnCount; @Shadow public int spawnCount;
@Shadow public SpawnData nextSpawnData; @Shadow public SpawnData nextSpawnData;
@Shadow public int spawnRange; @Shadow public int spawnRange;
@Shadow public int maxNearbyEntities; @Shadow public int maxNearbyEntities;
@Shadow private static WeightedRandomList<SpawnData> EMPTY_POTENTIALS;
@Shadow protected abstract boolean isNearPlayer(Level p_151344_, BlockPos p_151345_);
@Shadow protected abstract void delay(Level p_151351_, BlockPos p_151352_);
// @formatter:on // @formatter:on
@Inject(method = "setEntityId", at = @At("RETURN")) @Inject(method = "setEntityId", at = @At("RETURN"))
public void arclight$clearMobs(EntityType<?> type, CallbackInfo ci) { public void arclight$clearMobs(EntityType<?> type, CallbackInfo ci) {
this.spawnPotentials.clear(); this.spawnPotentials = EMPTY_POTENTIALS;
} }
/** /**
@ -59,110 +54,87 @@ public abstract class AbstractSpawnerMixin {
* @reason * @reason
*/ */
@Overwrite @Overwrite
public void tick() { public void serverTick(ServerLevel level, BlockPos pos) {
if (!this.isNearPlayer()) { if (this.isNearPlayer(level, pos)) {
this.oSpin = this.spin; if (this.spawnDelay == -1) {
} else { this.delay(level, pos);
Level world = this.getLevel(); }
BlockPos blockpos = this.getPos();
if (!(world instanceof ServerLevel)) {
double d3 = (double) blockpos.getX() + world.random.nextDouble();
double d4 = (double) blockpos.getY() + world.random.nextDouble();
double d5 = (double) blockpos.getZ() + world.random.nextDouble();
world.addParticle(ParticleTypes.SMOKE, d3, d4, d5, 0.0D, 0.0D, 0.0D);
world.addParticle(ParticleTypes.FLAME, d3, d4, d5, 0.0D, 0.0D, 0.0D);
if (this.spawnDelay > 0) {
--this.spawnDelay;
}
this.oSpin = this.spin; if (this.spawnDelay > 0) {
this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; --this.spawnDelay;
} else { } else {
if (this.spawnDelay == -1) {
this.delay();
}
if (this.spawnDelay > 0) {
--this.spawnDelay;
return;
}
boolean flag = false; boolean flag = false;
for (int i = 0; i < this.spawnCount; ++i) { for (int i = 0; i < this.spawnCount; ++i) {
CompoundTag compoundnbt = this.nextSpawnData.getTag(); CompoundTag compoundtag = this.nextSpawnData.getTag();
Optional<EntityType<?>> optional = EntityType.by(compoundnbt); Optional<EntityType<?>> optional = EntityType.by(compoundtag);
if (!optional.isPresent()) { if (optional.isEmpty()) {
this.delay(); this.delay(level, pos);
return; return;
} }
ListTag listnbt = compoundnbt.getList("Pos", 6); ListTag listtag = compoundtag.getList("Pos", 6);
int j = listnbt.size(); int j = listtag.size();
double d0 = j >= 1 ? listnbt.getDouble(0) : (double) blockpos.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D; double d0 = j >= 1 ? listtag.getDouble(0) : (double) pos.getX() + (level.random.nextDouble() - level.random.nextDouble()) * (double) this.spawnRange + 0.5D;
double d1 = j >= 2 ? listnbt.getDouble(1) : (double) (blockpos.getY() + world.random.nextInt(3) - 1); double d1 = j >= 2 ? listtag.getDouble(1) : (double) (pos.getY() + level.random.nextInt(3) - 1);
double d2 = j >= 3 ? listnbt.getDouble(2) : (double) blockpos.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D; double d2 = j >= 3 ? listtag.getDouble(2) : (double) pos.getZ() + (level.random.nextDouble() - level.random.nextDouble()) * (double) this.spawnRange + 0.5D;
if (world.noCollision(optional.get().getAABB(d0, d1, d2))) { if (level.noCollision(optional.get().getAABB(d0, d1, d2)) && SpawnPlacements.checkSpawnRules(optional.get(), level, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), level.getRandom())) {
ServerLevel serverworld = (ServerLevel) world; Entity entity = EntityType.loadEntityRecursive(compoundtag, level, (p_151310_) -> {
if (SpawnPlacements.checkSpawnRules(optional.get(), serverworld, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) { p_151310_.moveTo(d0, d1, d2, p_151310_.getYRot(), p_151310_.getXRot());
Entity entity = EntityType.loadEntityRecursive(compoundnbt, world, (p_221408_6_) -> { return p_151310_;
p_221408_6_.moveTo(d0, d1, d2, p_221408_6_.yRot, p_221408_6_.xRot); });
return p_221408_6_; if (entity == null) {
}); this.delay(level, pos);
if (entity == null) { return;
this.delay(); }
return;
}
int k = world.getEntitiesOfClass(entity.getClass(), (new AABB(blockpos.getX(), blockpos.getY(), blockpos.getZ(), blockpos.getX() + 1, blockpos.getY() + 1, blockpos.getZ() + 1)).inflate(this.spawnRange)).size(); int k = level.getEntitiesOfClass(entity.getClass(), (new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)).inflate(this.spawnRange)).size();
if (k >= this.maxNearbyEntities) { if (k >= this.maxNearbyEntities) {
this.delay(); this.delay(level, pos);
return; return;
} }
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), level.random.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob) { if (entity instanceof Mob mob) {
Mob mobentity = (Mob) entity; if (!ForgeEventFactory.canEntitySpawnSpawner(mob, level, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this)) {
if (!ForgeEventFactory.canEntitySpawnSpawner(mobentity, world, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this)) {
continue;
}
if (this.nextSpawnData.getTag().size() == 1 && this.nextSpawnData.getTag().contains("id", 8)) {
if (!ForgeEventFactory.doSpecialSpawn(mobentity, world, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this, MobSpawnType.SPAWNER))
((Mob) entity).finalizeSpawn(serverworld, world.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, null, null);
}
if (((WorldBridge) mobentity.level).bridge$spigotConfig().nerfSpawnerMobs) {
((MobEntityBridge) mobentity).bridge$setAware(false);
}
}
if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockpos).isCancelled()) {
Entity vehicle = entity.getVehicle();
if (vehicle != null) {
vehicle.remove();
}
for (Entity passenger : entity.getIndirectPassengers()) {
passenger.remove();
}
continue; continue;
} }
if (!((ServerWorldBridge) serverworld).bridge$addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
this.delay();
return;
}
world.levelEvent(2004, blockpos, 0); if (this.nextSpawnData.getTag().size() == 1 && this.nextSpawnData.getTag().contains("id", 8)) {
if (entity instanceof Mob) { if (!ForgeEventFactory.doSpecialSpawn(mob, level, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this, MobSpawnType.SPAWNER))
((Mob) entity).spawnAnim(); ((Mob) entity).finalizeSpawn(level, level.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, null, null);
}
if (((WorldBridge) mob.level).bridge$spigotConfig().nerfSpawnerMobs) {
((MobEntityBridge) mob).bridge$setAware(false);
} }
flag = true;
} }
if (CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
Entity vehicle = entity.getVehicle();
if (vehicle != null) {
vehicle.discard();
}
for (Entity passenger : entity.getIndirectPassengers()) {
passenger.discard();
}
continue;
}
if (!((ServerWorldBridge) level).bridge$addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
this.delay(level, pos);
return;
}
level.levelEvent(2004, pos, 0);
if (entity instanceof Mob) {
((Mob) entity).spawnAnim();
}
flag = true;
} }
} }
if (flag) { if (flag) {
this.delay(); this.delay(level, pos);
} }
} }
} }

View File

@ -3,6 +3,17 @@ package io.izzel.arclight.common.mixin.core.world.spawner;
import io.izzel.arclight.common.bridge.world.IWorldWriterBridge; import io.izzel.arclight.common.bridge.world.IWorldWriterBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.spawner.WorldEntitySpawnerBridge; import io.izzel.arclight.common.bridge.world.spawner.WorldEntitySpawnerBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.NaturalSpawner;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.storage.LevelData;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -14,16 +25,6 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random; import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.NaturalSpawner;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.storage.LevelData;
@Mixin(NaturalSpawner.class) @Mixin(NaturalSpawner.class)
public abstract class WorldEntitySpawnerMixin { public abstract class WorldEntitySpawnerMixin {
@ -61,30 +62,25 @@ public abstract class WorldEntitySpawnerMixin {
boolean spawnThisTick = true; boolean spawnThisTick = true;
int limit = classification.getMaxInstancesPerChunk(); int limit = classification.getMaxInstancesPerChunk();
switch (classification) { switch (classification) {
case MONSTER: { case MONSTER -> {
spawnThisTick = spawnMonsterThisTick; spawnThisTick = spawnMonsterThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getMonsterSpawnLimit(); limit = ((WorldBridge) world).bridge$getWorld().getMonsterSpawnLimit();
break;
} }
case CREATURE: { case CREATURE -> {
spawnThisTick = spawnAnimalThisTick; spawnThisTick = spawnAnimalThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getAnimalSpawnLimit(); limit = ((WorldBridge) world).bridge$getWorld().getAnimalSpawnLimit();
break;
} }
case WATER_CREATURE: { case WATER_CREATURE -> {
spawnThisTick = spawnWaterThisTick; spawnThisTick = spawnWaterThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getWaterAnimalSpawnLimit(); limit = ((WorldBridge) world).bridge$getWorld().getWaterAnimalSpawnLimit();
break;
} }
case AMBIENT: { case AMBIENT -> {
spawnThisTick = spawnAmbientThisTick; spawnThisTick = spawnAmbientThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getAmbientSpawnLimit(); limit = ((WorldBridge) world).bridge$getWorld().getAmbientSpawnLimit();
break;
} }
case WATER_AMBIENT: { case WATER_AMBIENT -> {
spawnThisTick = spawnWaterAmbientThisTick; spawnThisTick = spawnWaterAmbientThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getWaterAmbientSpawnLimit(); limit = ((WorldBridge) world).bridge$getWorld().getWaterAmbientSpawnLimit();
break;
} }
} }
if (spawnThisTick) { if (spawnThisTick) {
@ -99,13 +95,22 @@ public abstract class WorldEntitySpawnerMixin {
world.getProfiler().pop(); world.getProfiler().pop();
} }
@Inject(method = "spawnCategoryForPosition", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")) @Inject(method = "spawnCategoryForPosition(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/NaturalSpawner$SpawnPredicate;Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private static void arclight$naturalSpawn(MobCategory p_234966_0_, ServerLevel worldIn, ChunkAccess p_234966_2_, BlockPos p_234966_3_, NaturalSpawner.SpawnPredicate p_234966_4_, NaturalSpawner.AfterSpawnCallback p_234966_5_, CallbackInfo ci) { private static void arclight$naturalSpawn(MobCategory p_234966_0_, ServerLevel worldIn, ChunkAccess p_234966_2_, BlockPos p_234966_3_, NaturalSpawner.SpawnPredicate p_234966_4_, NaturalSpawner.AfterSpawnCallback p_234966_5_, CallbackInfo ci) {
((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.NATURAL); ((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.NATURAL);
} }
@Redirect(method = "spawnCategoryForPosition(Lnet/minecraft/world/entity/MobCategory;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/NaturalSpawner$SpawnPredicate;Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/NaturalSpawner$AfterSpawnCallback;run(Lnet/minecraft/world/entity/Mob;Lnet/minecraft/world/level/chunk/ChunkAccess;)V"))
private static void arclight$skipRun(NaturalSpawner.AfterSpawnCallback afterSpawnCallback, Mob mob, ChunkAccess chunkAccess) {
if (!mob.isRemoved()) {
afterSpawnCallback.run(mob, chunkAccess);
}
}
@Inject(method = "spawnMobsForChunkGeneration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerLevelAccessor;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")) @Inject(method = "spawnMobsForChunkGeneration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerLevelAccessor;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))
private static void arclight$worldGenSpawn(ServerLevelAccessor worldIn, Biome biomeIn, int centerX, int centerZ, Random diameterX, CallbackInfo ci) { private static void arclight$worldGenSpawn(ServerLevelAccessor accessor, Biome p_151618_, ChunkPos p_151619_, Random p_151620_, CallbackInfo ci) {
((IWorldWriterBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.CHUNK_GEN); ((IWorldWriterBridge) accessor).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.CHUNK_GEN);
} }
} }

View File

@ -2,6 +2,11 @@ package io.izzel.arclight.common.mixin.core.world.storage;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.storage.PlayerDataBridge; import io.izzel.arclight.common.bridge.world.storage.PlayerDataBridge;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.storage.PlayerDataStorage;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.entity.CraftPlayer;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -13,11 +18,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.storage.PlayerDataStorage;
@Mixin(PlayerDataStorage.class) @Mixin(PlayerDataStorage.class)
public class PlayerDataMixin implements PlayerDataBridge { public class PlayerDataMixin implements PlayerDataBridge {
@ -32,7 +32,7 @@ public class PlayerDataMixin implements PlayerDataBridge {
if (player instanceof ServerPlayer) { if (player instanceof ServerPlayer) {
CraftPlayer craftPlayer = ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity(); CraftPlayer craftPlayer = ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity();
// Only update first played if it is older than the one we have // Only update first played if it is older than the one we have
long modified = new File(this.playerDir, player.getUUID().toString() + ".dat").lastModified(); long modified = new File(this.playerDir, player.getUUID() + ".dat").lastModified();
if (modified < craftPlayer.getFirstPlayed()) { if (modified < craftPlayer.getFirstPlayed()) {
craftPlayer.setFirstPlayed(modified); craftPlayer.setFirstPlayed(modified);
} }

View File

@ -6,9 +6,9 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.level.storage.WorldData;
import net.minecraftforge.fml.FMLWorldPersistenceHook;
import net.minecraftforge.fml.MavenVersionStringHelper;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fmllegacy.FMLWorldPersistenceHook;
import net.minecraftforge.fmllegacy.MavenVersionStringHelper;
import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData; import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.RegistryManager; import net.minecraftforge.registries.RegistryManager;

View File

@ -9,7 +9,7 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container; import net.minecraft.world.Container;
import net.minecraft.world.MenuProvider; import net.minecraft.world.MenuProvider;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fmllegacy.network.NetworkHooks;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -40,7 +40,7 @@ public class NetworkHooksMixin {
} }
} }
@Inject(method = "sendMCRegistryPackets", remap = false, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/network/FMLMCRegisterPacketHandler;addChannels(Ljava/util/Set;Lnet/minecraft/network/NetworkManager;)V")) @Inject(method = "sendMCRegistryPackets", remap = false, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fmllegacy/network/FMLMCRegisterPacketHandler;addChannels(Ljava/util/Set;Lnet/minecraft/network/Connection;)V"))
private static void arclight$withBukkitChannels(Connection manager, String direction, CallbackInfo ci, Set<ResourceLocation> resourceLocations) { private static void arclight$withBukkitChannels(Connection manager, String direction, CallbackInfo ci, Set<ResourceLocation> resourceLocations) {
Bukkit.getMessenger().getIncomingChannels().stream().map(ResourceLocation::new).forEach(resourceLocations::add); Bukkit.getMessenger().getIncomingChannels().stream().map(ResourceLocation::new).forEach(resourceLocations::add);
} }

View File

@ -2,7 +2,7 @@ package io.izzel.arclight.common.mixin.forge;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fmllegacy.network.PacketDistributor;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;

View File

@ -191,8 +191,7 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
} }
for (MethodNode method : classNode.methods) { for (MethodNode method : classNode.methods) {
for (AbstractInsnNode instruction : method.instructions) { for (AbstractInsnNode instruction : method.instructions) {
if (instruction instanceof FieldInsnNode) { if (instruction instanceof FieldInsnNode node) {
FieldInsnNode node = (FieldInsnNode) instruction;
node.name = map.getOrDefault(node.name, node.name); node.name = map.getOrDefault(node.name, node.name);
} }
} }
@ -241,8 +240,7 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
private void remapCtor(ClassNode classNode, MethodNode methodNode) { private void remapCtor(ClassNode classNode, MethodNode methodNode) {
boolean initialized = false; boolean initialized = false;
for (AbstractInsnNode node : methodNode.instructions) { for (AbstractInsnNode node : methodNode.instructions) {
if (node instanceof MethodInsnNode) { if (node instanceof MethodInsnNode methodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) node;
if (methodInsnNode.name.equals("arclight$constructor")) { if (methodInsnNode.name.equals("arclight$constructor")) {
if (initialized) { if (initialized) {
throw new ClassFormatError("Duplicate constructor call"); throw new ClassFormatError("Duplicate constructor call");

View File

@ -1,7 +1,9 @@
package io.izzel.arclight.common.mod.server.event; package io.izzel.arclight.common.mod.server.event;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.mod.util.ArclightBlockSnapshot;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.BlockSnapshot;
@ -9,15 +11,12 @@ import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockMultiPlaceEvent; import org.bukkit.event.block.BlockMultiPlaceEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import io.izzel.arclight.common.mod.util.ArclightBlockSnapshot;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -27,9 +26,8 @@ public class BlockPlaceEventDispatcher {
@SubscribeEvent(receiveCanceled = true) @SubscribeEvent(receiveCanceled = true)
public void onBlockPlace(BlockEvent.EntityPlaceEvent event) { public void onBlockPlace(BlockEvent.EntityPlaceEvent event) {
Entity entity = event.getEntity(); Entity entity = event.getEntity();
if (entity instanceof ServerPlayer) { if (entity instanceof ServerPlayerEntityBridge playerEntity) {
ServerPlayer playerEntity = (ServerPlayer) entity; Player player = playerEntity.bridge$getBukkitEntity();
Player player = ((CraftServer) Bukkit.getServer()).getPlayer(playerEntity);
Direction direction = ArclightCaptures.getPlaceEventDirection(); Direction direction = ArclightCaptures.getPlaceEventDirection();
if (direction != null) { if (direction != null) {
InteractionHand hand = ArclightCaptures.getPlaceEventHand(InteractionHand.MAIN_HAND); InteractionHand hand = ArclightCaptures.getPlaceEventHand(InteractionHand.MAIN_HAND);
@ -63,9 +61,8 @@ public class BlockPlaceEventDispatcher {
@SubscribeEvent(receiveCanceled = true) @SubscribeEvent(receiveCanceled = true)
public void onMultiPlace(BlockEvent.EntityMultiPlaceEvent event) { public void onMultiPlace(BlockEvent.EntityMultiPlaceEvent event) {
Entity entity = event.getEntity(); Entity entity = event.getEntity();
if (entity instanceof ServerPlayer) { if (entity instanceof ServerPlayerEntityBridge playerEntity) {
ServerPlayer playerEntity = (ServerPlayer) entity; Player player = playerEntity.bridge$getBukkitEntity();
Player player = ((CraftServer) Bukkit.getServer()).getPlayer(playerEntity);
Direction direction = ArclightCaptures.getPlaceEventDirection(); Direction direction = ArclightCaptures.getPlaceEventDirection();
if (direction != null) { if (direction != null) {
InteractionHand hand = ArclightCaptures.getPlaceEventHand(InteractionHand.MAIN_HAND); InteractionHand hand = ArclightCaptures.getPlaceEventHand(InteractionHand.MAIN_HAND);

View File

@ -9,6 +9,7 @@ import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.DataPackConfig; import net.minecraft.world.level.DataPackConfig;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.bukkit.TreeType; import org.bukkit.TreeType;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.v.event.CraftPortalEvent; import org.bukkit.craftbukkit.v.event.CraftPortalEvent;
@ -230,6 +231,21 @@ public class ArclightCaptures {
} }
} }
private static transient BlockEntity tickingBlockEntity;
public static void captureTickingBlockEntity(BlockEntity entity) {
tickingBlockEntity = entity;
}
public static void resetTickingBlockEntity() {
tickingBlockEntity = null;
}
@SuppressWarnings("unchecked")
public static <T extends BlockEntity> T getTickingBlockEntity() {
return (T) tickingBlockEntity;
}
private static void recapture(String type) { private static void recapture(String type) {
throw new IllegalStateException("Recapturing " + type); throw new IllegalStateException("Recapturing " + type);
} }

View File

@ -23,7 +23,6 @@ import java.net.JarURLConnection;
import java.net.URLConnection; import java.net.URLConnection;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel; import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -97,7 +96,7 @@ public abstract class ArclightClassCache implements AutoCloseable {
String store; String store;
Path version = basePath.resolve(".version"); Path version = basePath.resolve(".version");
if (Files.exists(version)) { if (Files.exists(version)) {
store = new String(Files.readAllBytes(version), StandardCharsets.UTF_8); store = Files.readString(version);
} else { } else {
store = null; store = null;
} }
@ -117,7 +116,7 @@ public abstract class ArclightClassCache implements AutoCloseable {
Files.createDirectories(blob); Files.createDirectories(blob);
} }
if (obsolete) { if (obsolete) {
Files.write(version, current.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE); Files.writeString(version, current, StandardOpenOption.CREATE);
ArclightMod.LOGGER.info(MARKER, "Obsolete plugin class cache is cleared"); ArclightMod.LOGGER.info(MARKER, "Obsolete plugin class cache is cleared");
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -162,8 +162,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
private static void redirect(ClassNode classNode, ClassLoaderRemapper remapper) { private static void redirect(ClassNode classNode, ClassLoaderRemapper remapper) {
for (MethodNode methodNode : classNode.methods) { for (MethodNode methodNode : classNode.methods) {
for (AbstractInsnNode insnNode : methodNode.instructions) { for (AbstractInsnNode insnNode : methodNode.instructions) {
if (insnNode instanceof MethodInsnNode) { if (insnNode instanceof MethodInsnNode from) {
MethodInsnNode from = (MethodInsnNode) insnNode;
if (from.getOpcode() == Opcodes.INVOKESPECIAL if (from.getOpcode() == Opcodes.INVOKESPECIAL
&& Objects.equals(from.owner, classNode.superName) && Objects.equals(from.owner, classNode.superName)
&& Objects.equals(from.name, methodNode.name) && Objects.equals(from.name, methodNode.name)
@ -176,8 +175,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
Object[] bsmArgs = invokeDynamic.bsmArgs; Object[] bsmArgs = invokeDynamic.bsmArgs;
for (int i = 0; i < bsmArgs.length; i++) { for (int i = 0; i < bsmArgs.length; i++) {
Object bsmArg = bsmArgs[i]; Object bsmArg = bsmArgs[i];
if (bsmArg instanceof Handle) { if (bsmArg instanceof Handle handle) {
Handle handle = (Handle) bsmArg;
if (toOpcode(handle.getTag()) != -1) { if (toOpcode(handle.getTag()) != -1) {
bsmArgs[i] = processHandle(handle, remapper); bsmArgs[i] = processHandle(handle, remapper);
} }
@ -389,29 +387,21 @@ public class ArclightRedirectAdapter implements PluginTransformer {
} }
private static int toOpcode(int handleType) { private static int toOpcode(int handleType) {
switch (handleType) { return switch (handleType) {
case Opcodes.H_INVOKEINTERFACE: case Opcodes.H_INVOKEINTERFACE -> Opcodes.INVOKEINTERFACE;
return Opcodes.INVOKEINTERFACE; case Opcodes.H_INVOKEVIRTUAL -> Opcodes.INVOKEVIRTUAL;
case Opcodes.H_INVOKEVIRTUAL: case Opcodes.H_INVOKESTATIC -> Opcodes.INVOKESTATIC;
return Opcodes.INVOKEVIRTUAL; default -> -1;
case Opcodes.H_INVOKESTATIC: };
return Opcodes.INVOKESTATIC;
default:
return -1;
}
} }
private static int toHandle(int opcode) { private static int toHandle(int opcode) {
switch (opcode) { return switch (opcode) {
case Opcodes.INVOKEINTERFACE: case Opcodes.INVOKEINTERFACE -> Opcodes.H_INVOKEINTERFACE;
return Opcodes.H_INVOKEINTERFACE; case Opcodes.INVOKESTATIC -> Opcodes.H_INVOKESTATIC;
case Opcodes.INVOKESTATIC: case Opcodes.INVOKEVIRTUAL -> Opcodes.H_INVOKEVIRTUAL;
return Opcodes.H_INVOKESTATIC; default -> -1;
case Opcodes.INVOKEVIRTUAL: };
return Opcodes.H_INVOKEVIRTUAL;
default:
return -1;
}
} }
static AbstractInsnNode loadInt(int i) { static AbstractInsnNode loadInt(int i) {

View File

@ -62,8 +62,7 @@ public class ClassLoaderAdapter implements PluginTransformer {
} }
for (MethodNode methodNode : node.methods) { for (MethodNode methodNode : node.methods) {
for (AbstractInsnNode insnNode : methodNode.instructions) { for (AbstractInsnNode insnNode : methodNode.instructions) {
if (insnNode instanceof MethodInsnNode) { if (insnNode instanceof MethodInsnNode methodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
if (methodInsnNode.getOpcode() == Opcodes.INVOKESPECIAL && methodNode.name.equals("<init>") && methodInsnNode.name.equals("<init>") && methodInsnNode.owner.equals(node.superName)) { if (methodInsnNode.getOpcode() == Opcodes.INVOKESPECIAL && methodNode.name.equals("<init>") && methodInsnNode.name.equals("<init>") && methodInsnNode.owner.equals(node.superName)) {
methodInsnNode.owner = info.superName; methodInsnNode.owner = info.superName;
} }

View File

@ -27,113 +27,31 @@
"commands.synchronization.ArgumentTypesMixin", "commands.synchronization.ArgumentTypesMixin",
"fluid.FlowingFluidMixin", "fluid.FlowingFluidMixin",
"fluid.LavaFluidMixin", "fluid.LavaFluidMixin",
"world.inventory.CraftingInventoryMixin",
"world.inventory.CraftResultInventoryMixin",
"world.CompoundContainerMixin",
"world.inventory.EnderChestInventoryMixin",
"world.ContainerMixin",
"world.SimpleContainerMixin",
"world.inventory.MerchantInventoryMixin",
"world.inventory.AbstractFurnaceContainerMixin",
"world.inventory.ItemCombinerMixin",
"world.inventory.BeaconContainerMixin",
"world.inventory.BrewingStandContainerMixin",
"world.inventory.CartographyContainer1Mixin",
"world.inventory.CartographyContainer2Mixin",
"world.inventory.CartographyContainerMixin",
"world.inventory.ChestContainerMixin",
"world.inventory.AbstractContainerMenuMixin",
"world.inventory.ContainerTypeMixin",
"world.inventory.DispenserContainerMixin",
"world.inventory.EnchantmentContainer1Mixin",
"world.inventory.EnchantmentContainerMixin",
"world.inventory.FurnaceResultSlotMixin",
"world.inventory.GrindstoneContainer1Mixin",
"world.inventory.GrindstoneContainerMixin",
"world.inventory.HopperContainerMixin",
"world.inventory.HorseInventoryContainerMixin",
"world.inventory.LecternContainerMixin",
"world.inventory.LoomContainer1Mixin",
"world.inventory.LoomContainer2Mixin",
"world.inventory.LoomContainerMixin",
"world.inventory.MerchantContainerMixin",
"world.inventory.PlayerContainerMixin",
"world.inventory.RepairContainerMixin",
"world.inventory.ShulkerBoxContainerMixin",
"world.inventory.SlotMixin",
"world.inventory.SmithingTableContainerMixin",
"world.inventory.StonecutterContainer1Mixin",
"world.inventory.StonecutterContainerMixin",
"world.inventory.CraftingMenuMixin",
"world.item.ArmorStandItemMixin",
"world.item.BlockItemMixin",
"world.item.BoatItemMixin",
"world.item.BowItemMixin",
"world.item.BucketItemMixin",
"world.item.ChorusFruitItemMixin",
"world.item.CrossbowItemMixin",
"world.item.DyeItemMixin",
"world.item.EggItemMixin",
"world.item.EnderCrystalItemMixin",
"world.item.EnderEyeItemMixin",
"world.item.EnderPearlItemMixin",
"world.item.MapItemMixin",
"world.item.FireChargeItemMixin",
"world.item.FishingRodItemMixin",
"world.item.FlintAndSteelItemMixin",
"world.item.HangingEntityItemMixin",
"world.item.ItemStackMixin",
"world.item.LeadItemMixin",
"world.item.MerchantOfferMixin",
"world.item.MilkBucketItemMixin",
"world.item.MinecartItemMixin",
"world.item.PotionItemMixin",
"world.item.ShearsItemMixin",
"world.item.SnowballItemMixin",
"world.item.SpawnEggItemMixin",
"world.item.TridentItemMixin",
"world.item.crafting.BlastingRecipeMixin",
"world.item.crafting.CampfireCookingRecipeMixin",
"world.item.crafting.FurnaceRecipeMixin",
"world.item.crafting.IngredientMixin",
"world.item.crafting.RecipeMixin",
"world.item.crafting.RecipeManagerMixin",
"world.item.crafting.ServerRecipeBookMixin",
"world.item.crafting.ShapedRecipeMixin",
"world.item.crafting.ShapelessRecipeMixin",
"world.item.crafting.SmithingRecipeMixin",
"world.item.crafting.SmokingRecipeMixin",
"world.item.crafting.CustomRecipeMixin",
"world.item.crafting.StonecuttingRecipeMixin",
"world.level.storage.loot.entries.LootEntry_SerializerMixin",
"world.level.storage.loot.parameters.LootParametersMixin",
"world.level.storage.loot.LootTableManagerMixin",
"world.level.storage.loot.LootTableMixin",
"world.level.storage.loot.predicates.RandomChanceWithLootingMixin",
"world.level.storage.loot.predicates.SurvivesExplosionMixin",
"world.level.storage.loot.functions.LootingEnchantBonusMixin",
"network.ConnectionMixin", "network.ConnectionMixin",
"network.protocol.PacketThreadUtilMixin",
"network.SynchedEntityDataMixin",
"network.ServerHandshakeNetHandlerMixin", "network.ServerHandshakeNetHandlerMixin",
"network.protocol.handshake.CHandshakePacketMixin",
"network.ServerLoginNetHandlerMixin", "network.ServerLoginNetHandlerMixin",
"network.ServerPlayNetHandlerMixin", "network.ServerPlayNetHandlerMixin",
"network.ServerStatusNetHandlerMixin",
"network.SynchedEntityDataMixin",
"network.chat.ComponentMixin",
"network.chat.StyleMixin",
"network.chat.TextColorMixin",
"network.protocol.PacketThreadUtilMixin",
"network.protocol.game.CChatMessagePacketMixin", "network.protocol.game.CChatMessagePacketMixin",
"network.protocol.game.CCloseWindowPacketMixin", "network.protocol.game.CCloseWindowPacketMixin",
"network.protocol.game.CPlayerTryUseItemOnBlockPacketMixin", "network.protocol.game.CPlayerTryUseItemOnBlockPacketMixin",
"network.protocol.game.CPlayerTryUseItemPacketMixin", "network.protocol.game.CPlayerTryUseItemPacketMixin",
"network.protocol.game.SChatPacketMixin", "network.protocol.game.SChatPacketMixin",
"network.protocol.game.SWorldBorderPacketMixin", "network.protocol.game.SWorldBorderPacketMixin",
"network.protocol.handshake.CHandshakePacketMixin",
"network.rcon.RConConsoleSourceMixin", "network.rcon.RConConsoleSourceMixin",
"network.ServerStatusNetHandlerMixin", "server.BootstrapMixin",
"world.effect.MobEffectMixin",
"server.ServerScoreboardMixin",
"server.CustomServerBossInfoMixin", "server.CustomServerBossInfoMixin",
"server.MainMixin", "server.MainMixin",
"server.MinecraftServerMixin", "server.MinecraftServerMixin",
"server.PlayerAdvancementsMixin", "server.PlayerAdvancementsMixin",
"server.ServerFunctionManagerMixin", "server.ServerFunctionManagerMixin",
"server.ServerScoreboardMixin",
"server.commands.EffectCommandMixin", "server.commands.EffectCommandMixin",
"server.commands.GameRuleCommandMixin", "server.commands.GameRuleCommandMixin",
"server.commands.ReloadCommandMixin", "server.commands.ReloadCommandMixin",
@ -141,61 +59,39 @@
"server.commands.TeleportCommandMixin", "server.commands.TeleportCommandMixin",
"server.commands.TimeCommandMixin", "server.commands.TimeCommandMixin",
"server.dedicated.DedicatedServerMixin", "server.dedicated.DedicatedServerMixin",
"server.level.ChunkHolderMixin",
"server.level.ChunkMap_TrackedEntityMixin",
"server.level.ChunkMapMixin",
"server.level.ServerChunkCache_MainThreadExecutorMixin",
"server.level.ServerChunkCacheMixin",
"server.level.ServerEntityMixin",
"server.level.ServerLevel_EntityCallbacksMixin",
"server.level.ServerLevelMixin",
"server.level.TicketManagerMixin",
"server.level.TicketTypeMixin",
"server.management.BanEntryMixin", "server.management.BanEntryMixin",
"server.management.ServerPlayerGameModeMixin",
"server.management.PlayerListMixin", "server.management.PlayerListMixin",
"server.management.ServerPlayerGameModeMixin",
"server.management.UserListMixin", "server.management.UserListMixin",
"world.level.block.state.properties.IntegerPropertyMixin",
"stats.StatisticsCounterMixin", "stats.StatisticsCounterMixin",
"tileentity.AbstractFurnaceTileEntityMixin", "world.CompoundContainerMixin",
"tileentity.BarrelTileEntityMixin", "world.ContainerMixin",
"tileentity.BeaconTileEntityMixin",
"tileentity.BeehiveTileEntityMixin",
"tileentity.BrewingStandTileEntityMixin",
"tileentity.CampfireTileEntityMixin",
"tileentity.ChestTileEntityMixin",
"tileentity.CommandBlockLogicMixin",
"tileentity.CommandBlockTileEntity1Mixin",
"tileentity.ConduitTileEntityMixin",
"tileentity.DispenserTileEntityMixin",
"tileentity.EndGatewayTileEntityMixin",
"tileentity.HopperTileEntityMixin",
"tileentity.LecternTileEntity1Mixin",
"tileentity.LecternTileEntityMixin",
"tileentity.LockableTileEntityMixin",
"tileentity.ShulkerBoxTileEntityMixin",
"tileentity.SignTileEntityMixin",
"tileentity.SkullTileEntityMixin",
"tileentity.TileEntityMixin",
"util.BootstrapMixin",
"util.DamageSourceMixin",
"util.FoodStatsMixin",
"util.IndirectEntityDamageSourceMixin",
"util.IWorldPosCallableMixin",
"util.text.ColorMixin",
"util.text.ITextComponentMixin",
"util.text.StyleMixin",
"village.VillageSiegeMixin",
"world.ExplosionMixin", "world.ExplosionMixin",
"world.IBlockReaderMixin", "world.IBlockReaderMixin",
"world.IServerWorldMixin", "world.IServerWorldMixin",
"world.IWorldMixin", "world.IWorldMixin",
"world.IWorldWriterMixin", "world.IWorldWriterMixin",
"world.TeleporterMixin", "world.SimpleContainerMixin",
"world.TrackedEntityMixin", "world.damagesource.DamageSourceMixin",
"world.WorldMixin", "world.damagesource.IndirectEntityDamageSourceMixin",
"world.biome.BiomeContainerMixin", "world.effect.MobEffectMixin",
"world.border.WorldBorderMixin",
"world.chunk.ChunkMixin",
"world.chunk.storage.ChunkLoaderMixin",
"world.chunk.storage.RegionFileCacheMixin",
"world.entity.AgeableMobMixin", "world.entity.AgeableMobMixin",
"world.entity.AreaEffectCloudEntityMixin", "world.entity.AreaEffectCloudEntityMixin",
"world.entity.ItemBaseSteeringMixin",
"world.entity.EntityMixin", "world.entity.EntityMixin",
"world.entity.EntityTypeMixin", "world.entity.EntityTypeMixin",
"world.entity.ExperienceOrbMixin", "world.entity.ExperienceOrbMixin",
"world.entity.IAngerableMixin", "world.entity.IAngerableMixin",
"world.entity.ItemBaseSteeringMixin",
"world.entity.LightningBoltMixin", "world.entity.LightningBoltMixin",
"world.entity.LivingEntityMixin", "world.entity.LivingEntityMixin",
"world.entity.MobMixin", "world.entity.MobMixin",
@ -222,6 +118,7 @@
"world.entity.ai.goal.SkeletonTrapGoalMixin", "world.entity.ai.goal.SkeletonTrapGoalMixin",
"world.entity.ai.goal.TargetGoalMixin", "world.entity.ai.goal.TargetGoalMixin",
"world.entity.ai.goal.TemptGoalMixin", "world.entity.ai.goal.TemptGoalMixin",
"world.entity.ai.village.VillageSiegeMixin",
"world.entity.ambient.BatMixin", "world.entity.ambient.BatMixin",
"world.entity.animal.AbstractFishMixin", "world.entity.animal.AbstractFishMixin",
"world.entity.animal.AnimalMixin", "world.entity.animal.AnimalMixin",
@ -229,18 +126,40 @@
"world.entity.animal.Bee_HurtByOtherGoalMixin", "world.entity.animal.Bee_HurtByOtherGoalMixin",
"world.entity.animal.BeeMixin", "world.entity.animal.BeeMixin",
"world.entity.animal.BucketableMixin", "world.entity.animal.BucketableMixin",
"world.entity.animal.ChickenMixin",
"world.entity.animal.CowMixin",
"world.entity.animal.DolphinEntity_SwimWithPlayerGoalMixin",
"world.entity.animal.DolphinMixin",
"world.entity.animal.Fox_BreedGoalMixin",
"world.entity.animal.Fox_EatBerriesGoalMixin",
"world.entity.animal.FoxMixin",
"world.entity.animal.IronGolemMixin",
"world.entity.animal.MushroomCowMixin",
"world.entity.animal.OcelotMixin",
"world.entity.animal.Panda_HurtByTargetGoalMixin",
"world.entity.animal.PandaMixin",
"world.entity.animal.ParrotMixin",
"world.entity.animal.PigMixin",
"world.entity.animal.PufferfishEntityMixin", "world.entity.animal.PufferfishEntityMixin",
"world.entity.animal.Rabbit_RaidGardenGoalMixin",
"world.entity.animal.RabbitMixin",
"world.entity.animal.Sheep1Mixin",
"world.entity.animal.SheepMixin",
"world.entity.animal.SnowGolemMixin",
"world.entity.animal.TameableAnimalMixin",
"world.entity.animal.Turtle_LayEggGoalMixin",
"world.entity.animal.TurtleMixin",
"world.entity.animal.WolfMixin",
"world.entity.animal.horse.AbstractHorseMixin", "world.entity.animal.horse.AbstractHorseMixin",
"world.entity.animal.horse.TraderLlamaEntity_FollowTraderGoalMixin", "world.entity.animal.horse.TraderLlamaEntity_FollowTraderGoalMixin",
"world.entity.boss.WitherEntityMixin",
"world.entity.boss.enderdragon.EnderCrystalMixin", "world.entity.boss.enderdragon.EnderCrystalMixin",
"world.entity.boss.enderdragon.EnderDragonMixin", "world.entity.boss.enderdragon.EnderDragonMixin",
"world.entity.boss.enderdragon.phases.EnderDragonPhaseManagerMixin", "world.entity.boss.enderdragon.phases.EnderDragonPhaseManagerMixin",
"world.entity.boss.wither.WitherBossMixin", "world.entity.boss.wither.WitherBossMixin",
"world.entity.decoration.ArmorStandMixin",
"world.entity.decoration.ItemFrameMixin", "world.entity.decoration.ItemFrameMixin",
"world.entity.decoration.LeashFenceKnotEntityMixin", "world.entity.decoration.LeashFenceKnotEntityMixin",
"world.entity.decoration.PaintingMixin", "world.entity.decoration.PaintingMixin",
"world.entity.item.ArmorStandEntityMixin",
"world.entity.item.FallingBlockEntityMixin", "world.entity.item.FallingBlockEntityMixin",
"world.entity.item.HangingEntityMixin", "world.entity.item.HangingEntityMixin",
"world.entity.item.ItemEntityMixin", "world.entity.item.ItemEntityMixin",
@ -275,70 +194,127 @@
"world.entity.npc.AbstractVillagerMixin", "world.entity.npc.AbstractVillagerMixin",
"world.entity.npc.VillagerMixin", "world.entity.npc.VillagerMixin",
"world.entity.npc.WanderingTraderMixin", "world.entity.npc.WanderingTraderMixin",
"world.entity.animal.ChickenMixin",
"world.entity.animal.CowMixin",
"world.entity.animal.DolphinEntity_SwimWithPlayerGoalMixin",
"world.entity.animal.DolphinMixin",
"world.entity.animal.Fox_EatBerriesGoalMixin",
"world.entity.animal.Fox_BreedGoalMixin",
"world.entity.passive.FoxEntity_RevengeGoalMixin",
"world.entity.animal.FoxMixin",
"world.entity.animal.IronGolemMixin",
"world.entity.animal.MushroomCowMixin",
"world.entity.animal.OcelotMixin",
"world.entity.animal.Panda_HurtByTargetGoalMixin",
"world.entity.animal.PandaMixin",
"world.entity.animal.ParrotMixin",
"world.entity.animal.PigMixin",
"world.entity.animal.Rabbit_RaidGardenGoalMixin",
"world.entity.animal.RabbitMixin",
"world.entity.animal.Sheep1Mixin",
"world.entity.animal.SheepMixin",
"world.entity.animal.SnowGolemMixin",
"world.entity.animal.TameableAnimalMixin",
"world.entity.animal.Turtle_LayEggGoalMixin",
"world.entity.animal.TurtleMixin",
"world.entity.animal.WolfMixin",
"world.entity.player.PlayerMixin",
"world.entity.player.InventoryMixin", "world.entity.player.InventoryMixin",
"world.entity.player.PlayerMixin",
"world.entity.player.ServerPlayerMixin", "world.entity.player.ServerPlayerMixin",
"world.entity.projectile.AbstractArrowMixin", "world.entity.projectile.AbstractArrowMixin",
"world.entity.projectile.FireballMixin",
"world.entity.projectile.ArrowEntityMixin",
"world.entity.projectile.AbstractHurtingProjectileMixin", "world.entity.projectile.AbstractHurtingProjectileMixin",
"world.entity.projectile.ThrownEggMixin", "world.entity.projectile.ArrowEntityMixin",
"world.entity.projectile.EvokerFangsMixin", "world.entity.projectile.EvokerFangsMixin",
"world.entity.projectile.LargeFireballMixin", "world.entity.projectile.FireballMixin",
"world.entity.projectile.FireworkRocketEntityMixin", "world.entity.projectile.FireworkRocketEntityMixin",
"world.entity.projectile.FishingHookMixin", "world.entity.projectile.FishingHookMixin",
"world.entity.projectile.ThrownPotionMixin", "world.entity.projectile.LargeFireballMixin",
"world.entity.projectile.ProjectileMixin", "world.entity.projectile.ProjectileMixin",
"world.entity.projectile.ShulkerBulletMixin", "world.entity.projectile.ShulkerBulletMixin",
"world.entity.projectile.SmallFireballMixin", "world.entity.projectile.SmallFireballMixin",
"world.entity.projectile.SpectralArrowMixin", "world.entity.projectile.SpectralArrowMixin",
"world.entity.projectile.ThrowableItemProjectileMixin", "world.entity.projectile.ThrowableItemProjectileMixin",
"world.entity.projectile.ThrowableProjectileMixin", "world.entity.projectile.ThrowableProjectileMixin",
"world.entity.projectile.ThrownEggMixin",
"world.entity.projectile.ThrownEnderpearlMixin", "world.entity.projectile.ThrownEnderpearlMixin",
"world.entity.projectile.ThrownExperienceBottleMixin", "world.entity.projectile.ThrownExperienceBottleMixin",
"world.entity.projectile.ThrownPotionMixin",
"world.entity.projectile.ThrownTridentMixin", "world.entity.projectile.ThrownTridentMixin",
"world.entity.projectile.WitherSkullMixin", "world.entity.projectile.WitherSkullMixin",
"world.entity.raid.RaidManagerMixin",
"world.entity.raid.RaidMixin",
"world.entity.raider.Raider_HoldGroundAttackGoalMixin", "world.entity.raider.Raider_HoldGroundAttackGoalMixin",
"world.entity.raider.RaiderMixin", "world.entity.raider.RaiderMixin",
"world.entity.vehicle.AbstractMinecartContainerMixin", "world.entity.vehicle.AbstractMinecartContainerMixin",
"world.entity.vehicle.AbstractMinecartMixin", "world.entity.vehicle.AbstractMinecartMixin",
"world.entity.vehicle.BoatMixin", "world.entity.vehicle.BoatMixin",
"world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin", "world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin",
"world.food.FoodDataMixin",
"world.gen.WorldGenRegionMixin", "world.gen.WorldGenRegionMixin",
"world.gen.feature.structure.StructureManagerMixin", "world.gen.feature.structure.StructureManagerMixin",
"world.gen.feature.structure.SwampHutPieceMixin", "world.gen.feature.structure.SwampHutPieceMixin",
"world.gen.feature.template.TemplateManagerMixin", "world.gen.feature.template.TemplateManagerMixin",
"world.inventory.AbstractContainerMenuMixin",
"world.inventory.AbstractFurnaceContainerMixin",
"world.inventory.BeaconContainerMixin",
"world.inventory.BrewingStandContainerMixin",
"world.inventory.CartographyContainer1Mixin",
"world.inventory.CartographyContainer2Mixin",
"world.inventory.CartographyContainerMixin",
"world.inventory.ChestContainerMixin",
"world.inventory.ContainerLevelAccessMixin",
"world.inventory.ContainerTypeMixin",
"world.inventory.CraftingInventoryMixin",
"world.inventory.CraftingMenuMixin",
"world.inventory.CraftResultInventoryMixin",
"world.inventory.DispenserContainerMixin",
"world.inventory.EnchantmentContainer1Mixin",
"world.inventory.EnchantmentContainerMixin",
"world.inventory.EnderChestInventoryMixin",
"world.inventory.FurnaceResultSlotMixin",
"world.inventory.GrindstoneContainer1Mixin",
"world.inventory.GrindstoneContainerMixin",
"world.inventory.HopperContainerMixin",
"world.inventory.HorseInventoryContainerMixin",
"world.inventory.ItemCombinerMixin",
"world.inventory.LecternContainerMixin",
"world.inventory.LoomContainer1Mixin",
"world.inventory.LoomContainer2Mixin",
"world.inventory.LoomContainerMixin",
"world.inventory.MerchantContainerMixin",
"world.inventory.MerchantInventoryMixin",
"world.inventory.PlayerContainerMixin",
"world.inventory.RepairContainerMixin",
"world.inventory.ShulkerBoxContainerMixin",
"world.inventory.SlotMixin",
"world.inventory.SmithingTableContainerMixin",
"world.inventory.StonecutterContainer1Mixin",
"world.inventory.StonecutterContainerMixin",
"world.item.ArmorStandItemMixin",
"world.item.BlockItemMixin",
"world.item.BoatItemMixin",
"world.item.BowItemMixin",
"world.item.BucketItemMixin",
"world.item.ChorusFruitItemMixin",
"world.item.CrossbowItemMixin",
"world.item.DyeItemMixin",
"world.item.EggItemMixin",
"world.item.EnderCrystalItemMixin",
"world.item.EnderEyeItemMixin",
"world.item.EnderPearlItemMixin",
"world.item.FireChargeItemMixin",
"world.item.FishingRodItemMixin",
"world.item.FlintAndSteelItemMixin",
"world.item.HangingEntityItemMixin",
"world.item.ItemStackMixin",
"world.item.LeadItemMixin",
"world.item.MapItemMixin",
"world.item.MerchantMixin", "world.item.MerchantMixin",
"world.item.MerchantOfferMixin",
"world.item.MilkBucketItemMixin",
"world.item.MinecartItemMixin",
"world.item.PotionItemMixin",
"world.item.ShearsItemMixin",
"world.item.SnowballItemMixin",
"world.item.SpawnEggItemMixin",
"world.item.TridentItemMixin",
"world.item.crafting.BlastingRecipeMixin",
"world.item.crafting.CampfireCookingRecipeMixin",
"world.item.crafting.CustomRecipeMixin",
"world.item.crafting.FurnaceRecipeMixin",
"world.item.crafting.IngredientMixin",
"world.item.crafting.RecipeManagerMixin",
"world.item.crafting.RecipeMixin",
"world.item.crafting.ServerRecipeBookMixin",
"world.item.crafting.ShapedRecipeMixin",
"world.item.crafting.ShapelessRecipeMixin",
"world.item.crafting.SmithingRecipeMixin",
"world.item.crafting.SmokingRecipeMixin",
"world.item.crafting.StonecuttingRecipeMixin",
"world.item.enchantment.DamageEnchantmentMixin", "world.item.enchantment.DamageEnchantmentMixin",
"world.item.enchantment.FrostWalkerEnchantmentMixin", "world.item.enchantment.FrostWalkerEnchantmentMixin",
"world.level.LevelMixin",
"world.level.block.BambooBlockMixin", "world.level.block.BambooBlockMixin",
"world.level.block.BambooSaplingBlockMixin", "world.level.block.BambooSaplingBlockMixin",
"world.level.block.BaseFireBlockMixin", "world.level.block.BaseFireBlockMixin",
"world.level.block.BasePressurePlateBlockMixin", "world.level.block.BasePressurePlateBlockMixin",
"world.level.block.BedBlockMixin",
"world.level.block.BeehiveBlockMixin", "world.level.block.BeehiveBlockMixin",
"world.level.block.BlockMixin", "world.level.block.BlockMixin",
"world.level.block.BushBlockMixin", "world.level.block.BushBlockMixin",
@ -421,18 +397,44 @@
"world.level.block.WeightedPressurePlateBlockMixin", "world.level.block.WeightedPressurePlateBlockMixin",
"world.level.block.WitherRoseBlockMixin", "world.level.block.WitherRoseBlockMixin",
"world.level.block.WitherSkullBlockMixin", "world.level.block.WitherSkullBlockMixin",
"world.level.block.entity.AbstractFurnaceBlockEntityMixin",
"world.level.block.entity.BarrelBlockEntityMixin",
"world.level.block.entity.BeaconTileEntityMixin",
"world.level.block.entity.BeehiveBlockEntityMixin",
"world.level.block.entity.BlockEntityMixin",
"world.level.block.entity.BrewingStandBlockEntityMixin",
"world.level.block.entity.CampfireTileEntityMixin",
"world.level.block.entity.ChestBlockEntityMixin",
"world.level.block.entity.CommandBlockLogicMixin",
"world.level.block.entity.CommandBlockTileEntity1Mixin",
"world.level.block.entity.ConduitBlockEntityMixin",
"world.level.block.entity.DispenserBlockEntityMixin",
"world.level.block.entity.EndGatewayBlockEntityMixin",
"world.level.block.entity.HopperBlockEntityMixin",
"world.level.block.entity.LecternBlockEntityMixin",
"world.level.block.entity.LecternTileEntity1Mixin",
"world.level.block.entity.LockableBlockEntityMixin",
"world.level.block.entity.ShulkerBoxBlockEntityMixin",
"world.level.block.entity.SignBlockEntityMixin",
"world.level.block.state.BlockBehaviour_BlockStateBaseMixin", "world.level.block.state.BlockBehaviour_BlockStateBaseMixin",
"world.level.block.state.BlockBehaviourMixin", "world.level.block.state.BlockBehaviourMixin",
"world.raid.RaidManagerMixin", "world.level.block.state.properties.IntegerPropertyMixin",
"world.raid.RaidMixin", "world.level.border.WorldBorderMixin",
"world.server.ChunkHolderMixin", "world.level.chunk.ChunkBiomeContainerMixin",
"world.server.ChunkManager_EntityTrackerMixin", "world.level.chunk.LevelChunk_BoundTickingBlockEntityMixin",
"world.server.ChunkManagerMixin", "world.level.chunk.LevelChunkMixin",
"world.server.ServerChunkProvider_ChunkExecutorMixin", "world.level.chunk.storage.ChunkLoaderMixin",
"world.server.ServerChunkProviderMixin", "world.level.chunk.storage.RegionFileCacheMixin",
"world.server.ServerWorldMixin", "world.level.portal.PortalForcerMixin",
"world.server.TicketManagerMixin", "world.level.saveddata.maps.MapData_MapInfoMixin",
"world.server.TicketTypeMixin", "world.level.saveddata.maps.MapDataMixin",
"world.level.storage.loot.LootTableManagerMixin",
"world.level.storage.loot.LootTableMixin",
"world.level.storage.loot.entries.LootEntry_SerializerMixin",
"world.level.storage.loot.functions.LootingEnchantBonusMixin",
"world.level.storage.loot.parameters.LootParametersMixin",
"world.level.storage.loot.predicates.RandomChanceWithLootingMixin",
"world.level.storage.loot.predicates.SurvivesExplosionMixin",
"world.spawner.AbstractSpawnerMixin", "world.spawner.AbstractSpawnerMixin",
"world.spawner.PatrolSpawnerMixin", "world.spawner.PatrolSpawnerMixin",
"world.spawner.PhantomSpawnerMixin", "world.spawner.PhantomSpawnerMixin",
@ -440,8 +442,6 @@
"world.spawner.WorldEntitySpawner_EntityDensityManagerMixin", "world.spawner.WorldEntitySpawner_EntityDensityManagerMixin",
"world.spawner.WorldEntitySpawnerMixin", "world.spawner.WorldEntitySpawnerMixin",
"world.storage.DerivedWorldInfoMixin", "world.storage.DerivedWorldInfoMixin",
"world.storage.MapData_MapInfoMixin",
"world.storage.MapDataMixin",
"world.storage.PlayerDataMixin", "world.storage.PlayerDataMixin",
"world.storage.SaveFormat_LevelSaveMixin", "world.storage.SaveFormat_LevelSaveMixin",
"world.storage.SaveFormatMixin", "world.storage.SaveFormatMixin",

View File

@ -23,7 +23,7 @@ apply plugin: 'maven-publish'
arclight { arclight {
mcVersion = minecraftVersion mcVersion = minecraftVersion
forgeVersion = project.ext.forgeVersion forgeVersion = project.ext.forgeVersion
bukkitVersion = 'v1_16_R3' bukkitVersion = 'v1_17_R1'
wipeVersion = true wipeVersion = true
reobfVersion = true reobfVersion = true
accessTransformer = project(':arclight-common').file('bukkit.at') accessTransformer = project(':arclight-common').file('bukkit.at')
@ -86,6 +86,7 @@ def embedLibs = [/*'org.spongepowered:mixin:0.8.1',*/ 'org.ow2.asm:asm-util:9.0'
dependencies { dependencies {
minecraft "net.minecraftforge:forge:$minecraftVersion-$forgeVersion" minecraft "net.minecraftforge:forge:$minecraftVersion-$forgeVersion"
implementation group: 'org.jetbrains', name: 'annotations', version: '19.0.0' implementation group: 'org.jetbrains', name: 'annotations', version: '19.0.0'
implementation 'org.spongepowered:mixin:0.8.3'
implementation(project(':arclight-common')) { implementation(project(':arclight-common')) {
exclude module: 'forge' exclude module: 'forge'
} }
@ -102,7 +103,7 @@ dependencies {
embed 'com.github.ArclightTeam:mixin-tools:1.0.0@jar' embed 'com.github.ArclightTeam:mixin-tools:1.0.0@jar'
embed "io.izzel:tools:$toolsVersion" embed "io.izzel:tools:$toolsVersion"
embed "io.izzel.arclight:arclight-api:$apiVersion" embed "io.izzel.arclight:arclight-api:$apiVersion"
annotationProcessor 'org.spongepowered:mixin:0.8.2:processor' annotationProcessor 'org.spongepowered:mixin:0.8.3:processor'
annotationProcessor 'com.github.ArclightTeam:mixin-tools:1.0.0' annotationProcessor 'com.github.ArclightTeam:mixin-tools:1.0.0'
} }

View File

@ -2,13 +2,13 @@ package io.izzel.arclight.impl.common.optimization;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList; import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleList; import it.unimi.dsi.fastutil.doubles.DoubleList;
import net.minecraft.util.math.shapes.IDoubleListMerger; import net.minecraft.world.phys.shapes.IndexMerger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* @author jellysquid3 (LGPLv3) * @author jellysquid3 (LGPLv3)
*/ */
public class OptimizedIndirectMerger implements IDoubleListMerger { public class OptimizedIndirectMerger implements IndexMerger {
private final double[] merged; private final double[] merged;
private final int[] indicesFirst; private final int[] indicesFirst;
@ -108,12 +108,12 @@ public class OptimizedIndirectMerger implements IDoubleListMerger {
} }
@Override @Override
public @NotNull DoubleList func_212435_a() { public @NotNull DoubleList getList() {
return this.pairs; return this.pairs;
} }
@Override @Override
public boolean forMergedIndexes(@NotNull IConsumer consumer) { public boolean forMergedIndexes(@NotNull IndexConsumer consumer) {
int l = this.pairs.size() - 1; int l = this.pairs.size() - 1;
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
@ -124,4 +124,9 @@ public class OptimizedIndirectMerger implements IDoubleListMerger {
return true; return true;
} }
@Override
public int size() {
return this.pairs.size();
}
} }

View File

@ -2,18 +2,18 @@ package io.izzel.arclight.impl.mixin.optimization.dfu;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.DataFixerBuilder;
import net.minecraft.util.SharedConstants; import net.minecraft.SharedConstants;
import net.minecraft.util.datafix.DataFixesManager; import net.minecraft.util.datafix.DataFixers;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DataFixesManager.class) @Mixin(DataFixers.class)
public class DataFixesManagerMixin { public class DataFixesManagerMixin {
@Inject(method = "createFixer", cancellable = true, at = @At("HEAD")) @Inject(method = "createFixerUpper", cancellable = true, at = @At("HEAD"))
private static void arclight$disableDfu(CallbackInfoReturnable<DataFixer> cir) { private static void arclight$disableDfu(CallbackInfoReturnable<DataFixer> cir) {
cir.setReturnValue(new DataFixerBuilder(SharedConstants.getVersion().getWorldVersion()).build(r -> {})); cir.setReturnValue(new DataFixerBuilder(SharedConstants.getCurrentVersion().getWorldVersion()).build(r -> {}));
} }
} }

View File

@ -1,46 +0,0 @@
package io.izzel.arclight.impl.mixin.optimization.dfu;
import com.google.common.collect.ImmutableSet;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityClassification;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.FMLPlayMessages;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
@Mixin(EntityType.Builder.class)
public class EntityType_BuilderMixin<T extends Entity> {
@Shadow private boolean serializable;
@Shadow @Final private EntityType.IFactory<T> factory;
@Shadow @Final private EntityClassification classification;
@Shadow private boolean summonable;
@Shadow private boolean immuneToFire;
@Shadow private boolean field_225436_f;
@Shadow private EntitySize size;
@Shadow private Predicate<EntityType<?>> velocityUpdateSupplier;
@Shadow private ToIntFunction<EntityType<?>> trackingRangeSupplier;
@Shadow private ToIntFunction<EntityType<?>> updateIntervalSupplier;
@Shadow private BiFunction<FMLPlayMessages.SpawnEntity, World, T> customClientFactory;
@Shadow private int field_233605_i_;
@Shadow private int trackingRange;
@Shadow private ImmutableSet<Block> field_233603_c_;
/**
* @author Izzel_Aliz
* @reason
*/
@Overwrite
public EntityType<T> build(String id) {
return new EntityType<>(this.factory, this.classification, this.serializable, this.summonable, this.immuneToFire, this.field_225436_f, this.field_233603_c_, this.size, this.trackingRange, this.field_233605_i_, velocityUpdateSupplier, trackingRangeSupplier, updateIntervalSupplier, customClientFactory);
}
}

View File

@ -2,7 +2,7 @@ package io.izzel.arclight.impl.mixin.optimization.dfu;
import io.izzel.arclight.i18n.ArclightLocale; import io.izzel.arclight.i18n.ArclightLocale;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.storage.SaveFormat; import net.minecraft.world.level.storage.LevelStorageSource;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@ -11,9 +11,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class) @Mixin(MinecraftServer.class)
public abstract class MinecraftServerMixin { public abstract class MinecraftServerMixin {
@Inject(method = "func_240777_a_", cancellable = true, at = @At("HEAD")) @Inject(method = "convertFromRegionFormatIfNeeded", cancellable = true, at = @At("HEAD"))
private static void arclight$skipConvert(SaveFormat.LevelSave levelSave, CallbackInfo ci) { private static void arclight$skipConvert(LevelStorageSource.LevelStorageAccess levelSave, CallbackInfo ci) {
if (levelSave.isSaveFormatOutdated()) { if (levelSave.requiresConversion()) {
throw new RuntimeException(ArclightLocale.getInstance().get("dfu-disable.map-convert")); throw new RuntimeException(ArclightLocale.getInstance().get("dfu-disable.map-convert"));
} }
ci.cancel(); ci.cancel();

View File

@ -1,20 +0,0 @@
package io.izzel.arclight.impl.mixin.optimization.dfu;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(TileEntityType.class)
public class TileEntityTypeMixin {
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
private static <T extends TileEntity> TileEntityType<T> register(String key, TileEntityType.Builder<T> builder) {
return Registry.register(Registry.BLOCK_ENTITY_TYPE, key, builder.build(null));
}
}

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