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.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'
implementation 'com.github.ArclightTeam:mixin-tools:1.0.0'

View File

@ -1,13 +1,16 @@
package io.izzel.arclight.common.bridge.tileentity;
import java.util.List;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
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 {
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();
LevelChunk bridge$getFullChunk();
LevelChunk bridge$getFullChunkUnchecked();
}

View File

@ -1,12 +1,13 @@
package io.izzel.arclight.common.bridge.world.server;
import io.izzel.arclight.common.mod.util.ArclightCallbackExecutor;
import java.util.function.BooleanSupplier;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
public interface ChunkManagerBridge {
import java.util.function.BooleanSupplier;
public interface ChunkMapBridge {
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);
LevelStorageSource.LevelStorageAccess bridge$getConvertable();
interface Hack {
BlockEntity getTileEntity(BlockPos blockPos);
}
}

View File

@ -1,8 +1,15 @@
package io.izzel.arclight.common.bridge.world.storage;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import org.bukkit.craftbukkit.v.map.CraftMapView;
import java.util.List;
public interface MapDataBridge {
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) {
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);
}
CraftItemStack that = (CraftItemStack) stack;
if (handle == ((CraftItemStackBridge) (Object) that).bridge$getHandle()) {
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.world.WorldBridge;
import io.izzel.arclight.common.mod.server.ArclightServer;
import jline.console.ConsoleReader;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.dedicated.DedicatedPlayerList;
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.CallbackInfoReturnable;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;
@ -72,19 +70,6 @@ public abstract class CraftServerMixin implements CraftServerBridge {
return "Arclight";
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite(remap = false)
public ConsoleReader getReader() {
try {
return new ConsoleReader();
} catch (IOException e) {
return null;
}
}
@Override
public void bridge$setPlayerList(PlayerList 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 io.izzel.arclight.common.bridge.util.text.ITextComponentBridge;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -10,10 +11,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
import net.minecraft.network.chat.Component;
@Mixin(Component.class)
public interface ITextComponentMixin extends ITextComponentBridge, Iterable<Component> {
public interface ComponentMixin extends ITextComponentBridge, Iterable<Component> {
// @formatter:off
@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.HoverEvent;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
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)
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.Mixin;
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 javax.annotation.Nullable;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextColor;
@Mixin(TextColor.class)
public class ColorMixin {
public class TextColorMixin {
// @formatter:off
@Shadow @Final @Mutable @Nullable public String name;

View File

@ -1,6 +1,9 @@
package io.izzel.arclight.common.mixin.core.network.protocol.game;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.minecraft.network.protocol.game.ServerGamePacketListener;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -9,13 +12,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.minecraft.network.protocol.game.ServerGamePacketListener;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
@Mixin(ServerboundChatPacket.class)
public class CChatMessagePacketMixin {
@Shadow private String message;
@Shadow @Final private String message;
private static final ExecutorService executors = Executors.newCachedThreadPool(
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;
import net.minecraft.network.protocol.game.ServerboundContainerClosePacket;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ServerboundContainerClosePacket.class)
public class CCloseWindowPacketMixin {
@Shadow private int containerId;
@Shadow @Final @Mutable private int containerId;
public void arclight$constructor() {
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.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import io.izzel.arclight.api.Unsafe;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.server.Bootstrap;
@Mixin(Bootstrap.class)
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 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.ChunkManagerBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkMapBridge;
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.spongepowered.asm.mixin.Final;
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 java.util.concurrent.CompletableFuture;
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 java.util.concurrent.Executor;
@Mixin(ChunkHolder.class)
public abstract class ChunkHolderMixin implements ChunkHolderBridge {
@ -29,7 +32,8 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
// @formatter:off
@Shadow public int oldTicketLevel;
@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();
// @formatter:on
@ -37,9 +41,13 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
if (!ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
return null; // note: using oldTicketLevel for isLoaded checks
}
return this.getFullChunkUnchecked();
}
public LevelChunk getFullChunkUnchecked() {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL);
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
@ -47,16 +55,27 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
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),
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,
ChunkHolder.FullChunkStatus locationType, ChunkHolder.FullChunkStatus locationType1) {
if (locationType.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !locationType1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
LevelChunk chunk = (LevelChunk) either.left().orElse(null);
if (chunk != null) {
((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().execute(() -> {
((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().execute(() -> {
chunk.setUnsaved(true);
((ChunkBridge) chunk).bridge$unloadCallback();
});
@ -68,19 +87,19 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
});
// 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)
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,
ChunkHolder.FullChunkStatus locationType, ChunkHolder.FullChunkStatus locationType1) {
if (!locationType.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && locationType1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
LevelChunk chunk = (LevelChunk) either.left().orElse(null);
if (chunk != null) {
((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().execute(
((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().execute(
((ChunkBridge) chunk)::bridge$loadCallback
);
}
@ -90,7 +109,7 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
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.server.ChunkManagerBridge;
import io.izzel.arclight.common.bridge.world.server.ChunkMapBridge;
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.Mixin;
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 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;
@Mixin(ChunkMap.class)
public abstract class ChunkManagerMixin implements ChunkManagerBridge {
public abstract class ChunkMapMixin implements ChunkMapBridge {
// @formatter:off
@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 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.Mixin;
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 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)
public abstract class ChunkManager_EntityTrackerMixin {
public abstract class ChunkMap_TrackedEntityMixin {
// @formatter:off
@Shadow @Final private ServerEntity serverEntity;
@Shadow @Final ServerEntity serverEntity;
@Shadow @Final public Set<ServerPlayer> seenBy;
// @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.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.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.ChunkMap;
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.LevelChunk;
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.util.function.Consumer;
@Mixin(ServerChunkCache.class)
public abstract class ServerChunkProviderMixin implements ServerChunkProviderBridge {
public abstract class ServerChunkCacheMixin implements ServerChunkProviderBridge {
// @formatter:off
@Shadow public abstract void save(boolean flush);
@Shadow @Final private ThreadedLevelLightEngine lightEngine;
@Shadow @Final ThreadedLevelLightEngine lightEngine;
@Shadow @Final public ChunkMap chunkMap;
@Shadow @Final public ServerLevel level;
@Shadow @Final private DistanceManager distanceManager;
@Shadow protected abstract void clearCache();
@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 public boolean spawnEnemies;
@Shadow public boolean spawnFriendlies;
@ -52,10 +52,18 @@ public abstract class ServerChunkProviderMixin implements ServerChunkProviderBri
// @formatter:on
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;
}
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
public boolean bridge$isChunkLoaded(int x, int z) {
return isChunkLoaded(x, z);
@ -64,12 +72,12 @@ public abstract class ServerChunkProviderMixin implements ServerChunkProviderBri
@Override
public void bridge$setChunkGenerator(ChunkGenerator chunkGenerator) {
this.generator = chunkGenerator;
((ChunkManagerBridge) this.chunkMap).bridge$setChunkGenerator(chunkGenerator);
((ChunkMapBridge) this.chunkMap).bridge$setChunkGenerator(chunkGenerator);
}
@Override
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"))
@ -113,7 +121,7 @@ public abstract class ServerChunkProviderMixin implements ServerChunkProviderBri
((TicketManagerBridge) this.distanceManager).bridge$tick();
this.bridge$tickDistanceManager();
this.level.getProfiler().popPush("unload");
((ChunkManagerBridge) this.chunkMap).bridge$tick(() -> true);
((ChunkMapBridge) this.chunkMap).bridge$tick(() -> true);
this.level.getProfiler().pop();
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.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.mod.server.ArclightServer;
import net.minecraft.server.level.ServerChunkCache;
@ -12,13 +12,13 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@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
@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
protected ServerChunkProvider_ChunkExecutorMixin(String nameIn) {
protected ServerChunkCache_MainThreadExecutorMixin(String nameIn) {
super(nameIn);
}
@ -27,7 +27,7 @@ public abstract class ServerChunkProvider_ChunkExecutorMixin extends BlockableEv
* @reason
*/
@Overwrite
protected boolean pollTask() {
public boolean pollTask() {
try {
if (((ServerChunkProviderBridge) outer).bridge$tickDistanceManager()) {
return true;
@ -36,7 +36,7 @@ public abstract class ServerChunkProvider_ChunkExecutorMixin extends BlockableEv
return super.pollTask();
}
} finally {
((ChunkManagerBridge) outer.chunkMap).bridge$getCallbackExecutor().run();
((ChunkMapBridge) outer.chunkMap).bridge$getCallbackExecutor().run();
((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.mojang.datafixers.util.Pair;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
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.game.ClientboundAddMobPacket;
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.level.saveddata.maps.MapItemSavedData;
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)
public abstract class TrackedEntityMixin implements TrackedEntityBridge {
public abstract class ServerEntityMixin implements TrackedEntityBridge {
// @formatter:off
@Shadow @Final private Entity entity;
@ -111,11 +111,11 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
this.lastPassengers = list;
this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity));
}
if (this.entity instanceof ItemFrame) {
ItemFrame itemframeentity = (ItemFrame) this.entity;
ItemStack itemstack = itemframeentity.getItem();
MapItemSavedData mapdata = MapItem.getOrCreateSavedData(itemstack, this.level);
if (this.tickCount % 10 == 0 && mapdata != null && itemstack.getItem() instanceof MapItem) {
if (this.entity instanceof ItemFrame itemFrame) {
ItemStack itemstack = itemFrame.getItem();
if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) {
MapItemSavedData mapdata = MapItem.getSavedData(itemstack, this.level);
if (mapdata != null) {
for (ServerPlayer serverplayerentity : this.trackedPlayers) {
mapdata.tickCarriedBy(serverplayerentity, itemstack);
Packet<?> ipacket = ((MapItem) itemstack.getItem()).getUpdatePacket(itemstack, this.level, serverplayerentity);
@ -124,12 +124,13 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
}
}
}
}
this.sendDirtyEntityData();
}
if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) {
if (this.entity.isPassenger()) {
int i1 = Mth.floor(this.entity.yRot * 256.0F / 360.0F);
int l1 = Mth.floor(this.entity.xRot * 256.0F / 360.0F);
int i1 = Mth.floor(this.entity.getYRot() * 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;
if (flag2) {
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;
} else {
++this.teleportDelay;
int l = Mth.floor(this.entity.yRot * 256.0F / 360.0F);
int k1 = Mth.floor(this.entity.xRot * 256.0F / 360.0F);
int l = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F);
int k1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F);
Vec3 vector3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp));
boolean flag3 = vector3d.lengthSqr() >= (double) 7.6293945E-6F;
Packet<?> ipacket1 = null;
@ -239,7 +240,7 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
ServerPlayer player = arclight$player;
arclight$player = null;
Mob entityinsentient;
if (this.entity.removed) {
if (this.entity.isRemoved()) {
return;
}
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));
}
boolean flag = this.trackDelta;
if (this.entity instanceof LivingEntity) {
Collection<AttributeInstance> collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes();
if (this.entity instanceof LivingEntity livingEntity) {
Collection<AttributeInstance> collection = livingEntity.getAttributes().getSyncableAttributes();
if (this.entity.getId() == player.getId()) {
((ServerPlayerEntityBridge) this.entity).bridge$getBukkitEntity().injectScaledMaxHealth(collection, false);
}
if (!collection.isEmpty()) {
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection));
}
if (((LivingEntity) this.entity).isFallFlying()) {
if (livingEntity.isFallFlying()) {
flag = true;
}
}
@ -278,11 +279,11 @@ public abstract class TrackedEntityMixin implements TrackedEntityBridge {
}
this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0f / 360.0f);
consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) this.yHeadRotp));
if (this.entity instanceof LivingEntity) {
LivingEntity entityliving = (LivingEntity) this.entity;
for (MobEffectInstance mobeffect : entityliving.getActiveEffects()) {
if (this.entity instanceof LivingEntity livingEntity) {
for (MobEffectInstance mobeffect : livingEntity.getActiveEffects()) {
consumer.accept(new ClientboundUpdateMobEffectPacket(this.entity.getId(), mobeffect));
}
livingEntity.detectEquipmentUpdates();
}
if (!this.entity.getPassengers().isEmpty()) {
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"))
private void arclight$sendScaledHealth(CallbackInfo ci, SynchedEntityData entitydatamanager, Set<AttributeInstance> set) {
if (this.entity instanceof ServerPlayer) {
((ServerPlayerEntityBridge) this.entity).bridge$getBukkitEntity().injectScaledMaxHealth(set, false);
if (this.entity instanceof ServerPlayerEntityBridge player) {
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 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.MapDataBridge;
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.util.ArclightCaptures;
import io.izzel.arclight.common.mod.util.DelegateWorldInfo;
import io.izzel.arclight.i18n.ArclightConfig;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
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.entity.Entity;
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.Explosion;
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.LevelChunk;
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.storage.DerivedLevelData;
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.objectweb.asm.Opcodes;
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.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@ -84,11 +79,9 @@ import javax.annotation.Nullable;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.logging.Level;
@Mixin(ServerLevel.class)
@Implements(@Interface(iface = ServerWorldBridge.Hack.class, prefix = "hack$"))
public abstract class ServerWorldMixin extends WorldMixin implements ServerWorldBridge {
public abstract class ServerLevelMixin extends LevelMixin implements ServerWorldBridge {
// @formatter:off
@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 @Nonnull public abstract MinecraftServer shadow$getServer();
@Shadow @Final private List<ServerPlayer> players;
@Shadow @Final public Int2ObjectMap<Entity> entitiesById;
@Shadow public abstract ServerChunkCache getChunkSource();
@Shadow private boolean allPlayersSleeping;
@Shadow protected abstract void wakeUpAllPlayers();
@Shadow @Final private ServerChunkCache chunkSource;
@Shadow protected abstract boolean isUUIDUsed(Entity entityIn);
@Shadow @Final public static BlockPos END_SPAWN_POINT;
@Shadow @Final public ServerLevelData serverLevelData;
@Shadow @Final private PersistentEntitySectionManager<Entity> entityManager;
// @formatter:on
@SuppressWarnings({"FieldCanBeLocal", "unused"})
public PrimaryLevelData $$worldDataServer;
private int tickPosition;
public LevelStorageSource.LevelStorageAccess convertable;
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) {
this.pvpMode = minecraftServer.isPvpAllowed();
this.convertable = levelSave;
this.uuid = WorldUUID.getUUID(levelSave.getDimensionPath(this.getDimensionKey()));
this.uuid = WorldUUID.getUUID(levelSave.getDimensionPath(this.dimension()));
if (worldInfo instanceof PrimaryLevelData) {
this.$$worldDataServer = (PrimaryLevelData) worldInfo;
} else if (worldInfo instanceof DerivedLevelData) {
@ -139,7 +131,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
this.$$worldDataServer = DelegateWorldInfo.wrap(((DerivedLevelData) worldInfo));
((DerivedWorldInfoBridge) worldInfo).bridge$setDimType(this.getTypeKey());
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);
@ -168,11 +160,6 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
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"))
private void arclight$tickPortal(Entity entityIn, CallbackInfo ci) {
((EntityBridge) entityIn).bridge$postTick();
@ -183,11 +170,6 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
((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"))
public void arclight$thunder(LevelChunk chunkIn, int randomTickSpeed, CallbackInfo ci) {
bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.LIGHTNING);
@ -226,8 +208,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
@Inject(method = "save", at = @At("RETURN"))
private void arclight$saveLevelDat(ProgressListener progress, boolean flush, boolean skipSave, CallbackInfo ci) {
if (this.serverLevelData instanceof PrimaryLevelData) {
PrimaryLevelData worldInfo = (PrimaryLevelData) this.serverLevelData;
if (this.serverLevelData instanceof PrimaryLevelData worldInfo) {
worldInfo.setWorldBorder(this.getWorldBorder().createSettings());
worldInfo.setCustomBossEvents(this.shadow$getServer().getCustomBossEvents().save());
this.convertable.saveDataTag(this.shadow$getServer().registryHolder, worldInfo, this.shadow$getServer().getPlayerList().getSingleplayerData());
@ -317,13 +298,17 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
return addWithUUID(entity);
}
public void addEntityTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
addEntity(entity, reason);
}
@Override
public boolean bridge$addEntitySerialized(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
return addEntitySerialized(entity, 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 this.bridge$addAllEntities(entity, reason);
@ -351,14 +336,20 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
@Overwrite
@Nullable
public MapItemSavedData getMapData(String mapName) {
return this.shadow$getServer().overworld().getDataStorage().get(() -> {
MapItemSavedData newMap = new MapItemSavedData(mapName);
return this.shadow$getServer().overworld().getDataStorage().get((nbt) -> {
MapItemSavedData newMap = MapItemSavedData.load(nbt);
((MapDataBridge) newMap).bridge$setId(mapName);
MapInitializeEvent event = new MapInitializeEvent(((MapDataBridge) newMap).bridge$getMapView());
Bukkit.getServer().getPluginManager().callEvent(event);
return newMap;
}, 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"))
private void arclight$returnIfPopulate(BlockPos pos, Block block, CallbackInfo ci) {
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
public BlockEntity getTileEntity(BlockPos pos, boolean validate) {
BlockEntity result = super.getTileEntity(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;
}
return this.getBlockEntity(pos);
}
@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();
if (!event.isCancelled()) {
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 it.unimi.dsi.fastutil.longs.Long2ObjectMap;
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.ServerPlayer;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
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.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Iterator;
@ -27,14 +34,11 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
@Invoker("purgeStaleTickets") public abstract void bridge$tick();
// @formatter:on
@SuppressWarnings("unused") // mock
public <T> boolean func_219356_a(TicketType<T> type, ChunkPos pos, int level, T value) {
return addTicketAtLevel(type, pos, level, value);
@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"))
private void arclight$remove(SectionPos p_140829_, ServerPlayer p_140830_, CallbackInfo ci, ObjectSet<?> set) {
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) {
@ -57,12 +61,7 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
return removeTicketAtLevel(type, pos, level, value);
}
@SuppressWarnings("unused") // mock
private boolean func_219349_b(long chunkPosIn, Ticket<?> ticketIn) {
return removeTicket(chunkPosIn, ticketIn);
}
private boolean removeTicket(long chunkPosIn, Ticket<?> ticketIn) {
boolean removeTicket(long chunkPosIn, Ticket<?> ticketIn) {
SortedArraySet<Ticket<?>> ticketSet = this.getTickets(chunkPosIn);
boolean removed = false;
if (ticketSet.remove(ticketIn)) {
@ -80,12 +79,7 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
return removeTicket(chunkPos, ticket);
}
@SuppressWarnings("unused") // mock
private boolean func_219347_a(long chunkPosIn, Ticket<?> ticketIn) {
return addTicket(chunkPosIn, ticketIn);
}
private boolean addTicket(long chunkPosIn, Ticket<?> ticketIn) {
boolean addTicket(long chunkPosIn, Ticket<?> ticketIn) {
SortedArraySet<Ticket<?>> ticketSet = this.getTickets(chunkPosIn);
int level = getTicketLevelAt(ticketSet);
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 net.minecraft.server.level.TicketType;

View File

@ -557,7 +557,7 @@ public abstract class PlayerListMixin implements PlayerListBridge {
File file2;
File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile();
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);
}
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.WorldBridge;
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.Location;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
@ -29,32 +56,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Random;
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)
public abstract class ExplosionMixin implements ExplosionBridge {
@ -77,9 +78,9 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@Shadow @Final private boolean fire;
@Shadow @Final private Random random;
@Shadow private static void addBlockDrops(ObjectArrayList<Pair<ItemStack, BlockPos>> dropPositionArray, ItemStack stack, BlockPos pos) { }
@Shadow @Final private ExplosionDamageCalculator damageCalculator;
// @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",
at = @At("RETURN"))
@ -96,6 +97,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
if (this.radius < 0.1F) {
return;
}
this.level.gameEvent(this.source, GameEvent.EXPLODE, new BlockPos(this.x, this.y, this.z));
Set<BlockPos> set = Sets.newHashSet();
int i = 16;
@ -119,6 +121,11 @@ public abstract class ExplosionMixin implements ExplosionBridge {
BlockPos blockpos = new BlockPos(d4, d6, d8);
BlockState blockstate = this.level.getBlockState(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);
if (optional.isPresent()) {
f -= (optional.get() + 0.3F) * 0.3F;
@ -151,12 +158,12 @@ public abstract class ExplosionMixin implements ExplosionBridge {
for (Entity entity : list) {
if (!entity.ignoreExplosion()) {
double d12 = Mth.sqrt(entity.distanceToSqr(vec3d)) / f3;
double d12 = Math.sqrt(entity.distanceToSqr(vec3d)) / f3;
if (d12 <= 1.0D) {
double d5 = entity.getX() - this.x;
double d7 = entity.getEyeY() - this.y;
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) {
d5 = d5 / 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));
if (entity instanceof Player) {
Player playerentity = (Player) entity;
if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.abilities.flying)) {
if (entity instanceof Player playerentity) {
if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.getAbilities().flying)) {
this.hitPlayers.put(playerentity, new Vec3(d5 * d10, d7 * d10, d9 * d10));
}
}
@ -231,11 +237,11 @@ public abstract class ExplosionMixin implements ExplosionBridge {
for (BlockPos blockpos : this.toBlow) {
BlockState blockstate = this.level.getBlockState(blockpos);
Block block = blockstate.getBlock();
if (!blockstate.isAir(this.level, blockpos)) {
if (!blockstate.isAir()) {
BlockPos blockpos1 = blockpos.immutable();
this.level.getProfiler().push("explosion_blocks");
if (blockstate.canDropFromExplosion(this.level, blockpos, (Explosion) (Object) this) && this.level instanceof ServerLevel) {
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);
if (this.blockInteraction == Explosion.BlockInteraction.DESTROY || yield < 1.0F) {
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);
block.wasExploded(this.level, blockpos, (Explosion) (Object) this);
this.level.getProfiler().pop();
}
}

View File

@ -1,16 +1,16 @@
package io.izzel.arclight.common.mixin.core.world;
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.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
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)
public interface IServerWorldMixin extends LevelAccessor, ServerWorldBridge {
@ -46,7 +46,7 @@ public interface IServerWorldMixin extends LevelAccessor, ServerWorldBridge {
bridge$pushAddEntityReason(reason);
this.addFreshEntity(next);
}
return !entity.removed;
return !entity.isRemoved();
}
@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 javax.annotation.Nullable;
import net.minecraft.world.damagesource.DamageSource;
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)
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.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"))
private void arclight$move$blockCollide(MoverType typeIn, Vec3 pos, CallbackInfo ci) {
if (horizontalCollision && this.bridge$getBukkitEntity() instanceof Vehicle) {
Vehicle vehicle = (Vehicle) this.bridge$getBukkitEntity();
if (horizontalCollision && this.bridge$getBukkitEntity() instanceof Vehicle vehicle) {
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);
if (pos.x > vec3d.x) {
@ -506,8 +505,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Inject(method = "load", at = @At(value = "RETURN"))
public void arclight$read$ReadBukkitValues(CompoundTag compound, CallbackInfo ci) {
// CraftBukkit start
if ((Object) this instanceof LivingEntity) {
LivingEntity entity = (LivingEntity) (Object) this;
if ((Object) this instanceof LivingEntity entity) {
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;",
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) {
if (t != null) {
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) {
this.lastHurtByPlayerTime = 100;
this.lastHurtByPlayer = (net.minecraft.world.entity.player.Player) entity1;
} else if (entity1 instanceof TamableAnimal) {
TamableAnimal wolfentity = (TamableAnimal) entity1;
} else if (entity1 instanceof TamableAnimal wolfentity) {
if (wolfentity.isTame()) {
this.lastHurtByPlayerTime = 100;
LivingEntity livingentity = wolfentity.getOwner();
@ -910,8 +909,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
if (!itemstack1.isEmpty()) {
itemstack1.shrink(1);
}
if (itemstack != null && (Object) this instanceof ServerPlayer) {
ServerPlayer serverplayerentity = (ServerPlayer) (Object) this;
if (itemstack != null && (Object) this instanceof ServerPlayer serverplayerentity) {
serverplayerentity.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING));
CriteriaTriggers.USED_TOTEM.trigger(serverplayerentity, itemstack);
}

View File

@ -24,7 +24,7 @@ public class FollowOwnerGoalMixin {
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) {
CraftEntity craftEntity = ((EntityBridge) this.tamable).bridge$getBukkitEntity();
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 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) {
if (CraftEventFactory.handleNonLivingEntityDamageEvent((EndCrystal) (Object)this, source, amount)) {
cir.setReturnValue(false);

View File

@ -162,14 +162,15 @@ public abstract class ArmorStandMixin extends LivingEntityMixin {
@Override
public void setSlot(net.minecraft.world.entity.EquipmentSlot slotIn, ItemStack stack, boolean silent) {
switch (slotIn.getType()) {
case HAND:
case HAND -> {
this.bridge$playEquipSound(stack, silent);
this.handItems.set(slotIn.getIndex(), stack);
break;
case ARMOR:
}
case ARMOR -> {
this.bridge$playEquipSound(stack, silent);
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.spongepowered.asm.mixin.Mixin;
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;
@Mixin(LeashFenceKnotEntity.class)
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
* @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) {
if (CraftEventFactory.callEntityTransformEvent((net.minecraft.world.entity.npc.Villager) (Object) this, witchEntity, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) {
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) {
((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"))
private void arclight$wakeup(boolean flag, boolean flag1, CallbackInfo ci) {
BlockPos blockPos = this.getSleepingPos().orElse(null);
if (this.bridge$getBukkitEntity() instanceof Player) {
Player player = (Player) this.bridge$getBukkitEntity();
if (this.bridge$getBukkitEntity() instanceof Player player) {
Block bed;
if (blockPos != null) {
bed = CraftBlock.at(this.level, blockPos);

View File

@ -1,18 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.entity.projectile;
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 java.util.Set;
import net.minecraft.core.Registry;
import net.minecraft.network.syncher.EntityDataAccessor;
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.PotionUtils;
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)
@Implements(@Interface(iface = ArrowEntityBridge.Hack.class, prefix = "hack$"))
@ -33,7 +33,7 @@ public abstract class ArrowEntityMixin extends AbstractArrowMixin implements Arr
@Shadow private Potion potion;
// @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) {
((LivingEntityBridge) living).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ARROW);
}

View File

@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SpectralArrow.class)
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) {
((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.spongepowered.asm.mixin.Final;
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 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)
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.world.WorldBridge;
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.entity.Player;
import org.bukkit.event.entity.CreatureSpawnEvent;
@ -23,12 +29,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
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)
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.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.util.FoodStatsBridge;
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.ItemStack;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityExhaustionEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
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;
@Mixin(FoodData.class)
public abstract class FoodStatsMixin implements FoodStatsBridge {
public abstract class FoodDataMixin implements FoodStatsBridge {
// @formatter:off
@Shadow public int foodLevel;
@Shadow public abstract void eat(int foodLevelIn, float foodSaturationModifier);
@Shadow public float saturationLevel;
@Shadow private int lastFoodLevel;
// @formatter:on
private Player entityhuman;
public int saturatedRegenRate = 10;
public int unsaturatedRegenRate = 80;
public int starvationRate = 80;
public void arclight$constructor() {
throw new RuntimeException();
@ -40,8 +46,12 @@ public abstract class FoodStatsMixin implements FoodStatsBridge {
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) {
if (entityhuman == null) {
foodStats.eat(foodLevelIn, foodSaturationModifier);
return;
}
FoodProperties food = maybeFood.getFoodProperties();
int oldFoodLevel = this.foodLevel;
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"))
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()) {
this.foodLevel = event.getFoodLevel();
} else {
this.foodLevel = this.lastFoodLevel;
}
((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"))
public void arclight$heal(Player player, CallbackInfo ci) {
if (entityhuman == null) {
entityhuman = player;
}
((LivingEntityBridge) player).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.SATIATED);
((PlayerEntityBridge) player).bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.REGEN);
}
@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 net.minecraft.core.BlockPos;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.level.Level;
import org.bukkit.Location;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import java.util.Optional;
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)
public interface IWorldPosCallableMixin extends IWorldPosCallableBridge {
public interface ContainerLevelAccessMixin extends IWorldPosCallableBridge {
default Level 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"))
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
public void releaseUsing(ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) {
if (entityLiving instanceof Player) {
Player playerentity = (Player) entityLiving;
if (entityLiving instanceof Player playerentity) {
boolean flag = playerentity.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0;
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.border.WorldBorderBridge;
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.chunk.LevelChunk;
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.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator;
import org.bukkit.craftbukkit.v.util.CraftNamespacedKey;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.world.GenericGameEvent;
import org.bukkit.generator.ChunkGenerator;
import org.spigotmc.SpigotWorldConfig;
import org.spongepowered.asm.mixin.Final;
@ -53,12 +58,11 @@ import java.util.Optional;
import java.util.function.Supplier;
@Mixin(Level.class)
public abstract class WorldMixin implements WorldBridge, LevelWriter {
public abstract class LevelMixin implements WorldBridge, LevelWriter {
// @formatter:off
@Shadow @Nullable public BlockEntity getBlockEntity(BlockPos pos) { return null; }
@Shadow public abstract BlockState getBlockState(BlockPos pos);
@Shadow public abstract void setBlockEntity(BlockPos pos, @Nullable BlockEntity tileEntityIn);
@Shadow public abstract WorldBorder getWorldBorder();
@Shadow @Final private WorldBorder worldBorder;
@Shadow public abstract long getDayTime();
@ -84,6 +88,7 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
public org.spigotmc.SpigotWorldConfig spigotConfig;
@SuppressWarnings("unused") // Access transformed to public by ArclightMixinPlugin
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) {
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) {
this.spigotConfig = new SpigotWorldConfig(((ServerLevelData) info).getLevelName());
((WorldBorderBridge) this.worldBorder).bridge$setWorld((Level) (Object) this);
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns();
this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns();
this.ticksPerWaterSpawns = this.getServer().getTicksPerWaterSpawns();
this.ticksPerWaterAmbientSpawns = this.getServer().getTicksPerWaterAmbientSpawns();
this.ticksPerAmbientSpawns = this.getServer().getTicksPerAmbientSpawns();
this.typeKey = this.getServer().getHandle().getServer().registryAccess().dimensionTypes().getResourceKey(dimensionType)
this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns();
this.ticksPerMonsterSpawns = this.getCraftServer().getTicksPerMonsterSpawns();
this.ticksPerWaterSpawns = this.getCraftServer().getTicksPerWaterSpawns();
this.ticksPerWaterAmbientSpawns = this.getCraftServer().getTicksPerWaterAmbientSpawns();
this.ticksPerAmbientSpawns = this.getCraftServer().getTicksPerAmbientSpawns();
this.typeKey = this.getCraftServer().getHandle().getServer().registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY)
.getResourceKey(dimensionType)
.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());
ArclightMod.LOGGER.warn("Assign {} to unknown dimension type {} as {}", typeRegistryKey, dimType);
return typeRegistryKey;
@ -171,7 +177,7 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
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) {
try {
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,
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)
@ -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();
}
@ -219,9 +241,8 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
}
}
if (generator == null) {
generator = getServer().getGenerator(((ServerLevelData) this.getLevelData()).getLevelName());
if (generator != null && (Object) this instanceof ServerLevel) {
ServerLevel serverWorld = (ServerLevel) (Object) this;
generator = getCraftServer().getGenerator(((ServerLevelData) this.getLevelData()).getLevelName());
if (generator != null && (Object) this instanceof ServerLevel serverWorld) {
CustomChunkGenerator gen = new CustomChunkGenerator(serverWorld, serverWorld.getChunkSource().getGenerator(), generator);
((ServerChunkProviderBridge) serverWorld.getChunkSource()).bridge$setChunkGenerator(gen);
}
@ -230,7 +251,7 @@ public abstract class WorldMixin implements WorldBridge, LevelWriter {
environment = ArclightServer.getEnvironment(this.typeKey);
}
this.world = new CraftWorld((ServerLevel) (Object) this, generator, environment);
getServer().addWorld(this.world);
getCraftServer().addWorld(this.world);
}
return this.world;
}

View File

@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BeehiveBlock.class)
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) {
((MobEntityBridge) beeEntity).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true);
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) {
if (!worldIn.isClientSide) {
BlockEntity tileentity = worldIn.getBlockEntity(pos);
if (tileentity instanceof CommandBlockEntity) {
CommandBlockEntity commandblocktileentity = (CommandBlockEntity) tileentity;
if (tileentity instanceof CommandBlockEntity commandblocktileentity) {
boolean flag = worldIn.hasNeighborSignal(pos);
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.item.crafting.IRecipeBridge;
import io.izzel.arclight.common.bridge.tileentity.AbstractFurnaceTileEntityBridge;
import io.izzel.arclight.mixin.Eject;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
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.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.BlockPos;
import net.minecraft.core.NonNullList;
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.entity.ExperienceOrb;
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.block.Blocks;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
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.List;
@Mixin(AbstractFurnaceBlockEntity.class)
public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityMixin implements AbstractFurnaceTileEntityBridge {
public abstract class AbstractFurnaceBlockEntityMixin extends LockableBlockEntityMixin implements AbstractFurnaceTileEntityBridge {
// @formatter:off
@Shadow protected NonNullList<ItemStack> items;
@Shadow protected abstract int getBurnDuration(ItemStack stack);
@Shadow public int litTime;
@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 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
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK;
private transient FurnaceBurnEvent arclight$burnEvent;
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;getBurnDuration(Lnet/minecraft/world/item/ItemStack;)I"))
public void arclight$furnaceBurn(CallbackInfo ci) {
ItemStack itemStack = this.items.get(1);
@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"),
to = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/item/ItemStack;hasContainerItem()Z")))
private static boolean arclight$setBurnTime(AbstractFurnaceBlockEntity furnace, CallbackInfo ci) {
ItemStack itemStack = furnace.getItem(1);
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));
Bukkit.getPluginManager().callEvent(arclight$burnEvent);
if (arclight$burnEvent.isCancelled()) {
if (furnaceBurnEvent.isCancelled()) {
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"))
public boolean arclight$setBurnTime(AbstractFurnaceBlockEntity furnace) {
this.litTime = arclight$burnEvent.getBurnTime();
try {
return this.isLit() && arclight$burnEvent.isBurning();
} finally {
arclight$burnEvent = null;
@Inject(method = "serverTick", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;cookingProgress:I"))
private static void arclight$startSmelt(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity furnace, CallbackInfo ci, Recipe<?> recipe) {
if (recipe != null && furnace.cookingProgress == 0) {
CraftItemStack source = CraftItemStack.asCraftMirror(furnace.getItem(0));
CookingRecipe<?> cookingRecipe = (CookingRecipe<?>) ((IRecipeBridge) recipe).bridge$toBukkitRecipe();
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
*/
@Overwrite
@SuppressWarnings("unchecked")
private void burn(@Nullable Recipe<?> recipe) {
if (recipe != null && this.canBurn(recipe)) {
ItemStack itemstack = this.items.get(0);
private boolean burn(@Nullable Recipe<?> recipe, NonNullList<ItemStack> items, int i) {
if (recipe != null && this.canBurn(recipe, items, i)) {
ItemStack itemstack = items.get(0);
ItemStack itemstack1 = ((Recipe<WorldlyContainer>) recipe).assemble((AbstractFurnaceBlockEntity) (Object) this);
ItemStack itemstack2 = this.items.get(2);
ItemStack itemstack2 = items.get(2);
CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
FurnaceSmeltEvent event = new FurnaceSmeltEvent(CraftBlock.at(level, worldPosition), source, result);
Bukkit.getPluginManager().callEvent(event);
FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(level, worldPosition), source, result);
Bukkit.getPluginManager().callEvent(furnaceSmeltEvent);
if (event.isCancelled()) {
return;
if (furnaceSmeltEvent.isCancelled()) {
return false;
}
result = event.getResult();
result = furnaceSmeltEvent.getResult();
itemstack1 = CraftItemStack.asNMSCopy(result);
if (!itemstack1.isEmpty()) {
if (itemstack2.isEmpty()) {
this.items.set(2, itemstack1.copy());
items.set(2, itemstack1.copy());
} else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) {
itemstack2.grow(itemstack1.getCount());
} else {
return;
return false;
}
}
if (!this.level.isClientSide) {
this.setRecipeUsed(recipe);
}
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));
if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !items.get(1).isEmpty() && items.get(1).is(Items.BUCKET)) {
items.set(1, new ItemStack(Items.WATER_BUCKET));
}
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 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 {
arclight$item = itemStack;
arclight$captureAmount = amount;
arclight$captureFurnace = (AbstractFurnaceBlockEntity) (Object) this;
arclight$capturePlayer = entity;
List<Recipe<?>> list = this.getRecipesToAwardAndPopExperience(world, pos);
List<Recipe<?>> list = this.getRecipesToAwardAndPopExperience(world, vec);
entity.awardRecipes(list);
this.recipesUsed.clear();
return list;
@ -153,34 +159,19 @@ public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityM
}
@Override
public List<Recipe<?>> bridge$dropExp(Level world, Vec3 pos, Player entity, ItemStack itemStack, int amount) {
return a(world, pos, entity, itemStack, amount);
}
/**
* @author IzzelAliz
* @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;
public List<Recipe<?>> bridge$dropExp(ServerPlayer entity, ItemStack itemStack, int 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"))
private static void arclight$expEvent(ServerLevel level, Vec3 vec3, int amount) {
if (arclight$capturePlayer != null && arclight$captureAmount != 0) {
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);
i = event.getExpToDrop();
}
while (i > 0) {
int j = ExperienceOrb.getExperienceValue(i);
i -= j;
world.addFreshEntity(new ExperienceOrb(world, pos.x, pos.y, pos.z, j));
amount = event.getExpToDrop();
}
ExperienceOrb.award(level, vec3, amount);
}
@Override
@ -217,4 +208,14 @@ public abstract class AbstractFurnaceTileEntityMixin extends LockableTileEntityM
public void setMaxStackSize(int 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 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.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
@ -9,13 +13,9 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList;
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)
public abstract class BarrelTileEntityMixin extends LockableTileEntityMixin implements IInventoryBridge, Container {
public abstract class BarrelBlockEntityMixin extends LockableBlockEntityMixin implements IInventoryBridge, Container {
// @formatter:off
@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.potion.PotionEffect;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import io.izzel.arclight.common.bridge.tileentity.BeaconTileEntityBridge;
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)
public abstract class BeaconTileEntityMixin implements BeaconTileEntityBridge {
@ -26,7 +25,7 @@ public abstract class BeaconTileEntityMixin implements BeaconTileEntityBridge {
// @formatter:on
@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");
}

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 io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.entity.MobEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.tags.EntityTypeTags;
import net.minecraft.world.entity.Entity;
@ -32,11 +33,12 @@ import javax.annotation.Nullable;
import java.util.List;
@Mixin(BeehiveBlockEntity.class)
public abstract class BeehiveTileEntityMixin extends TileEntityMixin {
public abstract class BeehiveBlockEntityMixin extends BlockEntityMixin {
// @formatter:off
@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
public int maxBees = 3;
@ -56,16 +58,21 @@ public abstract class BeehiveTileEntityMixin extends TileEntityMixin {
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();
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;
}
@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"))
private void arclight$beeEnterBlock(Entity entity, boolean p_226962_2_, int p_226962_3_, CallbackInfo ci) {
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);
if (event.isCancelled()) {
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;
try {
return this.releaseOccupant(blockState, bee, list, state);
return releaseOccupant(world, pos, state, beeData, list, status, pos1);
} finally {
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"))
private boolean arclight$bypassNightCheck(Level world) {
private static boolean arclight$bypassNightCheck(Level world) {
return !arclight$force && world.isNight();
}
@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();
if (type.is(EntityTypeTags.BEEHIVE_INHABITORS)) {
((WorldBridge) this.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BEEHIVE);
if (!this.level.addFreshEntity(entity)) {
((WorldBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BEEHIVE);
if (!level.addFreshEntity(entity)) {
return EntityType.ITEM_FRAME;
} else {
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"))
private boolean arclight$addedBefore(Level world, Entity entityIn) {
private static boolean arclight$addedBefore(Level world, Entity entityIn) {
return true;
}
@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")) {
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.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.persistence.CraftPersistentDataContainer;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataTypeRegistry;
import org.bukkit.inventory.InventoryHolder;
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;
@ -14,29 +20,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
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)
public abstract class TileEntityMixin implements TileEntityBridge {
public abstract class BlockEntityMixin implements TileEntityBridge {
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
public CraftPersistentDataContainer persistentDataContainer;
// @formatter:off
@Shadow @Nullable public Level level;
@Shadow protected BlockPos worldPosition;
@Shadow @Final protected BlockPos worldPosition;
@Shadow public abstract BlockState getBlockState();
@Shadow public abstract void setChanged();
@Shadow public BlockPos getBlockPos() { return null; }
@Shadow public abstract boolean onlyOpCanSetNbt();
@Shadow protected static void setChanged(Level p_155233_, BlockPos p_155234_, BlockState p_155235_) { }
// @formatter:on
@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);
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.craftbukkit.v.block.CraftBlock;
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.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.ArrayList;
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)
public abstract class BrewingStandTileEntityMixin extends LockableTileEntityMixin {
public abstract class BrewingStandBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off
@Shadow private NonNullList<ItemStack> items;
@Shadow public int fuel;
// @formatter:on
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK;
private transient Integer arclight$fuel;
private transient boolean arclight$consume;
@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);
@Eject(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V"))
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);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
ci.cancel();
arclight$fuel = null;
} else {
arclight$consume = event.isConsuming();
arclight$fuel = event.getFuelPower();
entity.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"))
public void arclight$brewPotion(CallbackInfo ci) {
InventoryHolder owner = this.getOwner();
private static void arclight$brewPotion(Level level, BlockPos pos, NonNullList<ItemStack> p_155293_, CallbackInfo ci) {
BrewingStandBlockEntity entity = ArclightCaptures.getTickingBlockEntity();
InventoryHolder owner = entity == null ? null : ((TileEntityBridge) entity).bridge$getOwner();
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);
if (event.isCancelled()) {
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 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 net.minecraft.commands.CommandSourceStack;
@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.Shadow;
@Mixin(targets = "net/minecraft/world/level/block/entity/CommandBlockEntity$1")
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) {
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 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.event.CraftEventFactory;
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.LocalCapture;
import java.util.Iterator;
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)
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"))
public void arclight$addEntity(CallbackInfo ci, int i, int j, int k, int l, int i1, AABB bb, List<?> list,
Iterator<?> iterator, Player playerEntity) {
private static void arclight$addEntity(CallbackInfo ci, Player playerEntity) {
((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"))
public void arclight$attackReason(CallbackInfo ci) {
CraftEventFactory.blockDamage = CraftBlock.at(this.level, this.worldPosition);
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(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"))
public void arclight$attackReasonReset(CallbackInfo ci) {
private static void arclight$attackReasonReset(CallbackInfo ci) {
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.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
@ -8,12 +11,9 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.ArrayList;
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)
public abstract class DispenserTileEntityMixin extends LockableTileEntityMixin {
public abstract class DispenserBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off
@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.network.play.ServerPlayNetHandlerBridge;
@ -6,7 +6,9 @@ import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
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.state.BlockState;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.entity.CraftPlayer;
@ -19,14 +21,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(TheEndGatewayBlockEntity.class)
public abstract class EndGatewayTileEntityMixin extends TileEntityMixin {
public abstract class EndGatewayBlockEntityMixin extends BlockEntityMixin {
// @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
@Inject(method = "teleportEntity", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportToWithTicket(DDD)V"))
public void arclight$portal(Entity entityIn, CallbackInfo ci, BlockPos pos) {
@Inject(method = "teleportEntity", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPortalCooldown()V"))
private static void arclight$portal(Level level, BlockPos pos, BlockState state, Entity entityIn, TheEndGatewayBlockEntity entity, CallbackInfo ci) {
if (entityIn instanceof ServerPlayer) {
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);
@ -40,8 +42,9 @@ public abstract class EndGatewayTileEntityMixin extends TileEntityMixin {
return;
}
entityIn.setPortalCooldown();
((ServerPlayNetHandlerBridge) (((ServerPlayer) entityIn)).connection).bridge$teleport(event.getTo());
this.triggerCooldown(); // CraftBukkit - call at end of method
triggerCooldown(level, pos, state, entity);
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.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.craftbukkit.v.entity.CraftHumanEntity;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.ArrayList;
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)
public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
public abstract class HopperBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off
@Shadow private NonNullList<ItemStack> items;
@Shadow public abstract void setCooldown(int ticks);
@Shadow public abstract void setItem(int index, ItemStack stack);
// @formatter:on
public List<HumanEntity> transaction = new ArrayList<>();
private int maxStack = MAX_STACK;
private static transient boolean arclight$moveItem;
@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;"))
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) {
@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) {
HopperBlockEntity entity = ArclightCaptures.getTickingBlockEntity();
CraftItemStack original = CraftItemStack.asCraftMirror(stack);
Inventory destinationInventory;
@ -67,26 +60,19 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
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);
if (arclight$moveItem = event.isCancelled()) {
this.setCooldown(8); // Delay hopper checks
if (event.isCancelled()) {
entity.setCooldown(((WorldBridge) level).bridge$spigotConfig().hopperTransfer); // Delay hopper checks
cir.setReturnValue(false);
return null;
}
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;"))
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);
Inventory sourceInventory;
@ -99,18 +85,20 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, original.clone(), ((IInventoryBridge) destination).getOwnerInventory(), false);
Bukkit.getPluginManager().callEvent(event);
if (arclight$moveItem = event.isCancelled()) {
if (event.isCancelled()) {
inv.setItem(index, origin);
if (destination instanceof HopperBlockEntity) {
((HopperBlockEntity) destination).setCooldown(8); // Delay hopper checks
} else if (destination instanceof MinecartHopper) {
((MinecartHopper) destination).setCooldown(4); // Delay hopper minecart checks
}
cir.setReturnValue(false);
return null;
}
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) {
InventoryPickupItemEvent event = new InventoryPickupItemEvent(((IInventoryBridge) inventory).getOwnerInventory(), (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity());
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.entity.EntityBridge;
@ -33,7 +33,7 @@ import javax.annotation.Nullable;
import java.util.UUID;
@Mixin(LecternBlockEntity.class)
public abstract class LecternTileEntityMixin extends TileEntityMixin implements CommandSource, ICommandSourceBridge {
public abstract class LecternBlockEntityMixin extends BlockEntityMixin implements CommandSource, ICommandSourceBridge {
// @formatter:off
@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.tileentity.TileEntityBridge;
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.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 io.izzel.arclight.common.bridge.tileentity.TileEntityBridge;
import java.util.ArrayList;
import java.util.Collections;
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")
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<>();
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 net.minecraft.world.Container;
@ -9,7 +9,7 @@ import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(BaseContainerBlockEntity.class)
public abstract class LockableTileEntityMixin extends TileEntityMixin implements IInventoryBridge, Container {
public abstract class LockableBlockEntityMixin extends BlockEntityMixin implements IInventoryBridge, Container {
@Override
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.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
@ -11,13 +15,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList;
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)
public abstract class ShulkerBoxTileEntityMixin extends LockableTileEntityMixin {
public abstract class ShulkerBoxBlockEntityMixin extends LockableBlockEntityMixin {
// @formatter:off
@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.entity.EntityBridge;
@ -9,7 +9,6 @@ import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
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.SignBlockEntity;
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.Inject;
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 java.util.UUID;
@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
@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);
}
@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"))
public void arclight$setColor(DyeColor newColor, CallbackInfoReturnable<Boolean> cir) {
@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(CallbackInfo ci) {
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 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.world.level.biome.Biome;
@ -8,17 +8,21 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ChunkBiomeContainer.class)
public class BiomeContainerMixin {
public class ChunkBiomeContainerMixin {
// @formatter:off
@Shadow @Final private Biome[] biomes;
@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
public void setBiome(int i, int j, int k, Biome biome) {
int l = i & ChunkBiomeContainer.HORIZONTAL_MASK;
int i2 = Mth.clamp(j, 0, ChunkBiomeContainer.VERTICAL_MASK);
int j2 = k & ChunkBiomeContainer.HORIZONTAL_MASK;
this.biomes[i2 << WIDTH_BITS + WIDTH_BITS | j2 << WIDTH_BITS | l] = biome;
int l = i & HORIZONTAL_MASK;
int i1 = Mth.clamp(j - this.quartMinY, 0, this.quartHeight);
int j1 = k & HORIZONTAL_MASK;
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.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.craftbukkit.v.CraftChunk;
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 javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
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.Map;
import java.util.function.Consumer;
@Mixin(LevelChunk.class)
public abstract class ChunkMixin implements ChunkBridge {
public abstract class LevelChunkMixin implements ChunkBridge {
// @formatter:off
@Shadow @Nullable public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving);
@Shadow @Final public Level level;
@Shadow @Final private ChunkPos chunkPos;
@Shadow private volatile boolean unsaved;
@Shadow private boolean lastSaveHadEntities;
@Shadow private long lastSaveTime;
@Shadow @Final public ClassInstanceMultiMap<Entity>[] entitySections;
@Shadow @Final private Map<BlockPos, CompoundTag> pendingBlockEntities;
// @formatter:on
public org.bukkit.Chunk bukkitChunk;
public boolean mustNotSave;
public boolean needsDecoration;
private transient boolean arclight$doPlace;
public ServerLevel $$world;
public ServerLevel $$level;
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
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"))
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));
}
@SuppressWarnings("unchecked")
public List<Entity>[] getEntitySlices() {
return Arrays.stream(this.entitySections).map(ClassInstanceMultiMap::getAllInstances).toArray(List[]::new);
@Inject(method = "<init>(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ProtoChunk;Ljava/util/function/Consumer;)V", at = @At("RETURN"))
private void arclight$init(ServerLevel p_156365_, ProtoChunk p_156366_, Consumer<LevelChunk> p_156367_, CallbackInfo ci) {
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() {
@ -169,12 +172,6 @@ public abstract class ChunkMixin implements ChunkBridge {
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"))
public boolean arclight$redirectIsRemote(Level world) {
return world.isClientSide && this.arclight$doPlace;
@ -186,6 +183,6 @@ public abstract class ChunkMixin implements ChunkBridge {
*/
@Overwrite
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 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.world.level.Level;
import net.minecraft.world.level.chunk.storage.ChunkStorage;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler;
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;
@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 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.Shadow;
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.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)
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.world.TeleporterBridge;
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.craftbukkit.v.CraftWorld;
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.List;
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)
public abstract class TeleporterMixin implements TeleporterBridge {
public abstract class PortalForcerMixin implements TeleporterBridge {
// @formatter:off
@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);
}
@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) {
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 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.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.map.CraftMapView;
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;
@ -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.CallbackInfoReturnable;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
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)
public abstract class MapDataMixin implements MapDataBridge {
// @formatter:off
@Shadow public ResourceKey<Level> dimension;
@Shadow @Final public ResourceKey<Level> dimension;
@Shadow @Final private List<MapItemSavedData.HoldingPlayer> carriedBy;
// @formatter:on
public CraftMapView mapView;
private CraftServer server;
private UUID uniqueId;
public String id;
@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.server = (CraftServer) Bukkit.getServer();
}
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@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(() -> {
long least = nbt.getLong("UUIDLeast");
long most = nbt.getLong("UUIDMost");
if (least != 0L && most != 0L) {
this.uniqueId = new UUID(most, least);
CraftWorld world = (CraftWorld) this.server.getWorld(this.uniqueId);
UUID uniqueId = new UUID(most, least);
CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId);
if (world != null) {
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
public CraftMapView bridge$getMapView() {
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.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.util.CraftChatMessage;
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.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
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.Collection;
@Mixin(MapItemSavedData.HoldingPlayer.class)
public class MapData_MapInfoMixin {
public abstract class MapData_MapInfoMixin {
// @formatter:off
@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 tick;
@Shadow @Final public Player player;
@Shadow private boolean dirtyDecorations;
@Shadow protected abstract MapItemSavedData.MapPatch createPatch();
// @formatter:on
/**
@ -41,20 +41,32 @@ public class MapData_MapInfoMixin {
*/
@Overwrite
@Nullable
public Packet<?> nextUpdatePacket(ItemStack stack) {
public Packet<?> nextUpdatePacket(int i) {
RenderData render = ((MapDataBridge) outerThis).bridge$getMapView().render(((ServerPlayerEntityBridge) this.player).bridge$getBukkitEntity()); // CraftBukkit
Collection<MapDecoration> icons = new ArrayList<>();
MapItemSavedData.MapPatch patch;
if (this.dirtyData) {
this.dirtyData = false;
var colors = outerThis.colors;
outerThis.colors = render.buffer;
patch = this.createPatch();
outerThis.colors = colors;
} else {
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())));
}
}
if (this.dirtyData) {
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);
} 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;
}
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.server.ServerWorldBridge;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
@ -20,7 +20,6 @@ import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.ForgeEventFactory;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
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.callback.CallbackInfo;
import java.util.List;
import java.util.Optional;
@Mixin(BaseSpawner.class)
public abstract class AbstractSpawnerMixin {
// @formatter:off
@Shadow public abstract Level getLevel();
@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 WeightedRandomList<SpawnData> spawnPotentials;
@Shadow public int spawnDelay;
@Shadow protected abstract void delay();
@Shadow public int spawnCount;
@Shadow public SpawnData nextSpawnData;
@Shadow public int spawnRange;
@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
@Inject(method = "setEntityId", at = @At("RETURN"))
public void arclight$clearMobs(EntityType<?> type, CallbackInfo ci) {
this.spawnPotentials.clear();
this.spawnPotentials = EMPTY_POTENTIALS;
}
/**
@ -59,99 +54,77 @@ public abstract class AbstractSpawnerMixin {
* @reason
*/
@Overwrite
public void tick() {
if (!this.isNearPlayer()) {
this.oSpin = this.spin;
} else {
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;
this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D;
} else {
public void serverTick(ServerLevel level, BlockPos pos) {
if (this.isNearPlayer(level, pos)) {
if (this.spawnDelay == -1) {
this.delay();
this.delay(level, pos);
}
if (this.spawnDelay > 0) {
--this.spawnDelay;
return;
}
} else {
boolean flag = false;
for (int i = 0; i < this.spawnCount; ++i) {
CompoundTag compoundnbt = this.nextSpawnData.getTag();
Optional<EntityType<?>> optional = EntityType.by(compoundnbt);
if (!optional.isPresent()) {
this.delay();
CompoundTag compoundtag = this.nextSpawnData.getTag();
Optional<EntityType<?>> optional = EntityType.by(compoundtag);
if (optional.isEmpty()) {
this.delay(level, pos);
return;
}
ListTag listnbt = compoundnbt.getList("Pos", 6);
int j = listnbt.size();
double d0 = j >= 1 ? listnbt.getDouble(0) : (double) blockpos.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D;
double d1 = j >= 2 ? listnbt.getDouble(1) : (double) (blockpos.getY() + world.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;
if (world.noCollision(optional.get().getAABB(d0, d1, d2))) {
ServerLevel serverworld = (ServerLevel) world;
if (SpawnPlacements.checkSpawnRules(optional.get(), serverworld, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) {
Entity entity = EntityType.loadEntityRecursive(compoundnbt, world, (p_221408_6_) -> {
p_221408_6_.moveTo(d0, d1, d2, p_221408_6_.yRot, p_221408_6_.xRot);
return p_221408_6_;
ListTag listtag = compoundtag.getList("Pos", 6);
int j = listtag.size();
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 ? listtag.getDouble(1) : (double) (pos.getY() + level.random.nextInt(3) - 1);
double d2 = j >= 3 ? listtag.getDouble(2) : (double) pos.getZ() + (level.random.nextDouble() - level.random.nextDouble()) * (double) this.spawnRange + 0.5D;
if (level.noCollision(optional.get().getAABB(d0, d1, d2)) && SpawnPlacements.checkSpawnRules(optional.get(), level, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), level.getRandom())) {
Entity entity = EntityType.loadEntityRecursive(compoundtag, level, (p_151310_) -> {
p_151310_.moveTo(d0, d1, d2, p_151310_.getYRot(), p_151310_.getXRot());
return p_151310_;
});
if (entity == null) {
this.delay();
this.delay(level, pos);
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) {
this.delay();
this.delay(level, pos);
return;
}
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob mobentity = (Mob) entity;
if (!ForgeEventFactory.canEntitySpawnSpawner(mobentity, world, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this)) {
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), level.random.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob mob) {
if (!ForgeEventFactory.canEntitySpawnSpawner(mob, level, (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 (!ForgeEventFactory.doSpecialSpawn(mob, level, (float) entity.getX(), (float) entity.getY(), (float) entity.getZ(), (BaseSpawner) (Object) this, MobSpawnType.SPAWNER))
((Mob) entity).finalizeSpawn(level, level.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, null, null);
}
if (((WorldBridge) mobentity.level).bridge$spigotConfig().nerfSpawnerMobs) {
((MobEntityBridge) mobentity).bridge$setAware(false);
if (((WorldBridge) mob.level).bridge$spigotConfig().nerfSpawnerMobs) {
((MobEntityBridge) mob).bridge$setAware(false);
}
}
if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockpos).isCancelled()) {
if (CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
Entity vehicle = entity.getVehicle();
if (vehicle != null) {
vehicle.remove();
vehicle.discard();
}
for (Entity passenger : entity.getIndirectPassengers()) {
passenger.remove();
passenger.discard();
}
continue;
}
if (!((ServerWorldBridge) serverworld).bridge$addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
this.delay();
if (!((ServerWorldBridge) level).bridge$addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
this.delay(level, pos);
return;
}
world.levelEvent(2004, blockpos, 0);
level.levelEvent(2004, pos, 0);
if (entity instanceof Mob) {
((Mob) entity).spawnAnim();
}
@ -159,10 +132,9 @@ public abstract class AbstractSpawnerMixin {
flag = true;
}
}
}
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.WorldBridge;
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.spongepowered.asm.mixin.Final;
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 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)
public abstract class WorldEntitySpawnerMixin {
@ -61,30 +62,25 @@ public abstract class WorldEntitySpawnerMixin {
boolean spawnThisTick = true;
int limit = classification.getMaxInstancesPerChunk();
switch (classification) {
case MONSTER: {
case MONSTER -> {
spawnThisTick = spawnMonsterThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getMonsterSpawnLimit();
break;
}
case CREATURE: {
case CREATURE -> {
spawnThisTick = spawnAnimalThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getAnimalSpawnLimit();
break;
}
case WATER_CREATURE: {
case WATER_CREATURE -> {
spawnThisTick = spawnWaterThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getWaterAnimalSpawnLimit();
break;
}
case AMBIENT: {
case AMBIENT -> {
spawnThisTick = spawnAmbientThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getAmbientSpawnLimit();
break;
}
case WATER_AMBIENT: {
case WATER_AMBIENT -> {
spawnThisTick = spawnWaterAmbientThisTick;
limit = ((WorldBridge) world).bridge$getWorld().getWaterAmbientSpawnLimit();
break;
}
}
if (spawnThisTick) {
@ -99,13 +95,22 @@ public abstract class WorldEntitySpawnerMixin {
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) {
((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"))
private static void arclight$worldGenSpawn(ServerLevelAccessor worldIn, Biome biomeIn, int centerX, int centerZ, Random diameterX, CallbackInfo ci) {
((IWorldWriterBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.CHUNK_GEN);
private static void arclight$worldGenSpawn(ServerLevelAccessor accessor, Biome p_151618_, ChunkPos p_151619_, Random p_151620_, CallbackInfo ci) {
((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.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.bukkit.craftbukkit.v.entity.CraftPlayer;
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.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)
public class PlayerDataMixin implements PlayerDataBridge {
@ -32,7 +32,7 @@ public class PlayerDataMixin implements PlayerDataBridge {
if (player instanceof ServerPlayer) {
CraftPlayer craftPlayer = ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity();
// 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()) {
craftPlayer.setFirstPlayed(modified);
}

View File

@ -6,9 +6,9 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.LevelStorageSource;
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.fmllegacy.FMLWorldPersistenceHook;
import net.minecraftforge.fmllegacy.MavenVersionStringHelper;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
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.MenuProvider;
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.craftbukkit.v.event.CraftEventFactory;
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) {
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.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.Overwrite;

View File

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

View File

@ -1,7 +1,9 @@
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.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.common.util.BlockSnapshot;
@ -9,15 +11,12 @@ import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.bukkit.Bukkit;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.v.CraftServer;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockMultiPlaceEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.EquipmentSlot;
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.List;
@ -27,9 +26,8 @@ public class BlockPlaceEventDispatcher {
@SubscribeEvent(receiveCanceled = true)
public void onBlockPlace(BlockEvent.EntityPlaceEvent event) {
Entity entity = event.getEntity();
if (entity instanceof ServerPlayer) {
ServerPlayer playerEntity = (ServerPlayer) entity;
Player player = ((CraftServer) Bukkit.getServer()).getPlayer(playerEntity);
if (entity instanceof ServerPlayerEntityBridge playerEntity) {
Player player = playerEntity.bridge$getBukkitEntity();
Direction direction = ArclightCaptures.getPlaceEventDirection();
if (direction != null) {
InteractionHand hand = ArclightCaptures.getPlaceEventHand(InteractionHand.MAIN_HAND);
@ -63,9 +61,8 @@ public class BlockPlaceEventDispatcher {
@SubscribeEvent(receiveCanceled = true)
public void onMultiPlace(BlockEvent.EntityMultiPlaceEvent event) {
Entity entity = event.getEntity();
if (entity instanceof ServerPlayer) {
ServerPlayer playerEntity = (ServerPlayer) entity;
Player player = ((CraftServer) Bukkit.getServer()).getPlayer(playerEntity);
if (entity instanceof ServerPlayerEntityBridge playerEntity) {
Player player = playerEntity.bridge$getBukkitEntity();
Direction direction = ArclightCaptures.getPlaceEventDirection();
if (direction != null) {
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.inventory.AbstractContainerMenu;
import net.minecraft.world.level.DataPackConfig;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.bukkit.TreeType;
import org.bukkit.block.BlockState;
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) {
throw new IllegalStateException("Recapturing " + type);
}

View File

@ -23,7 +23,6 @@ import java.net.JarURLConnection;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -97,7 +96,7 @@ public abstract class ArclightClassCache implements AutoCloseable {
String store;
Path version = basePath.resolve(".version");
if (Files.exists(version)) {
store = new String(Files.readAllBytes(version), StandardCharsets.UTF_8);
store = Files.readString(version);
} else {
store = null;
}
@ -117,7 +116,7 @@ public abstract class ArclightClassCache implements AutoCloseable {
Files.createDirectories(blob);
}
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");
}
} catch (IOException e) {

View File

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

View File

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

View File

@ -27,113 +27,31 @@
"commands.synchronization.ArgumentTypesMixin",
"fluid.FlowingFluidMixin",
"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.protocol.PacketThreadUtilMixin",
"network.SynchedEntityDataMixin",
"network.ServerHandshakeNetHandlerMixin",
"network.protocol.handshake.CHandshakePacketMixin",
"network.ServerLoginNetHandlerMixin",
"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.CCloseWindowPacketMixin",
"network.protocol.game.CPlayerTryUseItemOnBlockPacketMixin",
"network.protocol.game.CPlayerTryUseItemPacketMixin",
"network.protocol.game.SChatPacketMixin",
"network.protocol.game.SWorldBorderPacketMixin",
"network.protocol.handshake.CHandshakePacketMixin",
"network.rcon.RConConsoleSourceMixin",
"network.ServerStatusNetHandlerMixin",
"world.effect.MobEffectMixin",
"server.ServerScoreboardMixin",
"server.BootstrapMixin",
"server.CustomServerBossInfoMixin",
"server.MainMixin",
"server.MinecraftServerMixin",
"server.PlayerAdvancementsMixin",
"server.ServerFunctionManagerMixin",
"server.ServerScoreboardMixin",
"server.commands.EffectCommandMixin",
"server.commands.GameRuleCommandMixin",
"server.commands.ReloadCommandMixin",
@ -141,61 +59,39 @@
"server.commands.TeleportCommandMixin",
"server.commands.TimeCommandMixin",
"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.ServerPlayerGameModeMixin",
"server.management.PlayerListMixin",
"server.management.ServerPlayerGameModeMixin",
"server.management.UserListMixin",
"world.level.block.state.properties.IntegerPropertyMixin",
"stats.StatisticsCounterMixin",
"tileentity.AbstractFurnaceTileEntityMixin",
"tileentity.BarrelTileEntityMixin",
"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.CompoundContainerMixin",
"world.ContainerMixin",
"world.ExplosionMixin",
"world.IBlockReaderMixin",
"world.IServerWorldMixin",
"world.IWorldMixin",
"world.IWorldWriterMixin",
"world.TeleporterMixin",
"world.TrackedEntityMixin",
"world.WorldMixin",
"world.biome.BiomeContainerMixin",
"world.border.WorldBorderMixin",
"world.chunk.ChunkMixin",
"world.chunk.storage.ChunkLoaderMixin",
"world.chunk.storage.RegionFileCacheMixin",
"world.SimpleContainerMixin",
"world.damagesource.DamageSourceMixin",
"world.damagesource.IndirectEntityDamageSourceMixin",
"world.effect.MobEffectMixin",
"world.entity.AgeableMobMixin",
"world.entity.AreaEffectCloudEntityMixin",
"world.entity.ItemBaseSteeringMixin",
"world.entity.EntityMixin",
"world.entity.EntityTypeMixin",
"world.entity.ExperienceOrbMixin",
"world.entity.IAngerableMixin",
"world.entity.ItemBaseSteeringMixin",
"world.entity.LightningBoltMixin",
"world.entity.LivingEntityMixin",
"world.entity.MobMixin",
@ -222,6 +118,7 @@
"world.entity.ai.goal.SkeletonTrapGoalMixin",
"world.entity.ai.goal.TargetGoalMixin",
"world.entity.ai.goal.TemptGoalMixin",
"world.entity.ai.village.VillageSiegeMixin",
"world.entity.ambient.BatMixin",
"world.entity.animal.AbstractFishMixin",
"world.entity.animal.AnimalMixin",
@ -229,18 +126,40 @@
"world.entity.animal.Bee_HurtByOtherGoalMixin",
"world.entity.animal.BeeMixin",
"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.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.TraderLlamaEntity_FollowTraderGoalMixin",
"world.entity.boss.WitherEntityMixin",
"world.entity.boss.enderdragon.EnderCrystalMixin",
"world.entity.boss.enderdragon.EnderDragonMixin",
"world.entity.boss.enderdragon.phases.EnderDragonPhaseManagerMixin",
"world.entity.boss.wither.WitherBossMixin",
"world.entity.decoration.ArmorStandMixin",
"world.entity.decoration.ItemFrameMixin",
"world.entity.decoration.LeashFenceKnotEntityMixin",
"world.entity.decoration.PaintingMixin",
"world.entity.item.ArmorStandEntityMixin",
"world.entity.item.FallingBlockEntityMixin",
"world.entity.item.HangingEntityMixin",
"world.entity.item.ItemEntityMixin",
@ -275,70 +194,127 @@
"world.entity.npc.AbstractVillagerMixin",
"world.entity.npc.VillagerMixin",
"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.PlayerMixin",
"world.entity.player.ServerPlayerMixin",
"world.entity.projectile.AbstractArrowMixin",
"world.entity.projectile.FireballMixin",
"world.entity.projectile.ArrowEntityMixin",
"world.entity.projectile.AbstractHurtingProjectileMixin",
"world.entity.projectile.ThrownEggMixin",
"world.entity.projectile.ArrowEntityMixin",
"world.entity.projectile.EvokerFangsMixin",
"world.entity.projectile.LargeFireballMixin",
"world.entity.projectile.FireballMixin",
"world.entity.projectile.FireworkRocketEntityMixin",
"world.entity.projectile.FishingHookMixin",
"world.entity.projectile.ThrownPotionMixin",
"world.entity.projectile.LargeFireballMixin",
"world.entity.projectile.ProjectileMixin",
"world.entity.projectile.ShulkerBulletMixin",
"world.entity.projectile.SmallFireballMixin",
"world.entity.projectile.SpectralArrowMixin",
"world.entity.projectile.ThrowableItemProjectileMixin",
"world.entity.projectile.ThrowableProjectileMixin",
"world.entity.projectile.ThrownEggMixin",
"world.entity.projectile.ThrownEnderpearlMixin",
"world.entity.projectile.ThrownExperienceBottleMixin",
"world.entity.projectile.ThrownPotionMixin",
"world.entity.projectile.ThrownTridentMixin",
"world.entity.projectile.WitherSkullMixin",
"world.entity.raid.RaidManagerMixin",
"world.entity.raid.RaidMixin",
"world.entity.raider.Raider_HoldGroundAttackGoalMixin",
"world.entity.raider.RaiderMixin",
"world.entity.vehicle.AbstractMinecartContainerMixin",
"world.entity.vehicle.AbstractMinecartMixin",
"world.entity.vehicle.BoatMixin",
"world.entity.vehicle.MinecartCommandBlock_MinecartCommandBaseMixin",
"world.food.FoodDataMixin",
"world.gen.WorldGenRegionMixin",
"world.gen.feature.structure.StructureManagerMixin",
"world.gen.feature.structure.SwampHutPieceMixin",
"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.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.FrostWalkerEnchantmentMixin",
"world.level.LevelMixin",
"world.level.block.BambooBlockMixin",
"world.level.block.BambooSaplingBlockMixin",
"world.level.block.BaseFireBlockMixin",
"world.level.block.BasePressurePlateBlockMixin",
"world.level.block.BedBlockMixin",
"world.level.block.BeehiveBlockMixin",
"world.level.block.BlockMixin",
"world.level.block.BushBlockMixin",
@ -421,18 +397,44 @@
"world.level.block.WeightedPressurePlateBlockMixin",
"world.level.block.WitherRoseBlockMixin",
"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.BlockBehaviourMixin",
"world.raid.RaidManagerMixin",
"world.raid.RaidMixin",
"world.server.ChunkHolderMixin",
"world.server.ChunkManager_EntityTrackerMixin",
"world.server.ChunkManagerMixin",
"world.server.ServerChunkProvider_ChunkExecutorMixin",
"world.server.ServerChunkProviderMixin",
"world.server.ServerWorldMixin",
"world.server.TicketManagerMixin",
"world.server.TicketTypeMixin",
"world.level.block.state.properties.IntegerPropertyMixin",
"world.level.border.WorldBorderMixin",
"world.level.chunk.ChunkBiomeContainerMixin",
"world.level.chunk.LevelChunk_BoundTickingBlockEntityMixin",
"world.level.chunk.LevelChunkMixin",
"world.level.chunk.storage.ChunkLoaderMixin",
"world.level.chunk.storage.RegionFileCacheMixin",
"world.level.portal.PortalForcerMixin",
"world.level.saveddata.maps.MapData_MapInfoMixin",
"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.PatrolSpawnerMixin",
"world.spawner.PhantomSpawnerMixin",
@ -440,8 +442,6 @@
"world.spawner.WorldEntitySpawner_EntityDensityManagerMixin",
"world.spawner.WorldEntitySpawnerMixin",
"world.storage.DerivedWorldInfoMixin",
"world.storage.MapData_MapInfoMixin",
"world.storage.MapDataMixin",
"world.storage.PlayerDataMixin",
"world.storage.SaveFormat_LevelSaveMixin",
"world.storage.SaveFormatMixin",

View File

@ -23,7 +23,7 @@ apply plugin: 'maven-publish'
arclight {
mcVersion = minecraftVersion
forgeVersion = project.ext.forgeVersion
bukkitVersion = 'v1_16_R3'
bukkitVersion = 'v1_17_R1'
wipeVersion = true
reobfVersion = true
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 {
minecraft "net.minecraftforge:forge:$minecraftVersion-$forgeVersion"
implementation group: 'org.jetbrains', name: 'annotations', version: '19.0.0'
implementation 'org.spongepowered:mixin:0.8.3'
implementation(project(':arclight-common')) {
exclude module: 'forge'
}
@ -102,7 +103,7 @@ dependencies {
embed 'com.github.ArclightTeam:mixin-tools:1.0.0@jar'
embed "io.izzel:tools:$toolsVersion"
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'
}

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.DoubleList;
import net.minecraft.util.math.shapes.IDoubleListMerger;
import net.minecraft.world.phys.shapes.IndexMerger;
import org.jetbrains.annotations.NotNull;
/**
* @author jellysquid3 (LGPLv3)
*/
public class OptimizedIndirectMerger implements IDoubleListMerger {
public class OptimizedIndirectMerger implements IndexMerger {
private final double[] merged;
private final int[] indicesFirst;
@ -108,12 +108,12 @@ public class OptimizedIndirectMerger implements IDoubleListMerger {
}
@Override
public @NotNull DoubleList func_212435_a() {
public @NotNull DoubleList getList() {
return this.pairs;
}
@Override
public boolean forMergedIndexes(@NotNull IConsumer consumer) {
public boolean forMergedIndexes(@NotNull IndexConsumer consumer) {
int l = this.pairs.size() - 1;
for (int i = 0; i < l; i++) {
@ -124,4 +124,9 @@ public class OptimizedIndirectMerger implements IDoubleListMerger {
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.DataFixerBuilder;
import net.minecraft.util.SharedConstants;
import net.minecraft.util.datafix.DataFixesManager;
import net.minecraft.SharedConstants;
import net.minecraft.util.datafix.DataFixers;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DataFixesManager.class)
@Mixin(DataFixers.class)
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) {
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 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.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -11,9 +11,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class)
public abstract class MinecraftServerMixin {
@Inject(method = "func_240777_a_", cancellable = true, at = @At("HEAD"))
private static void arclight$skipConvert(SaveFormat.LevelSave levelSave, CallbackInfo ci) {
if (levelSave.isSaveFormatOutdated()) {
@Inject(method = "convertFromRegionFormatIfNeeded", cancellable = true, at = @At("HEAD"))
private static void arclight$skipConvert(LevelStorageSource.LevelStorageAccess levelSave, CallbackInfo ci) {
if (levelSave.requiresConversion()) {
throw new RuntimeException(ArclightLocale.getInstance().get("dfu-disable.map-convert"));
}
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