1.17: runs now

This commit is contained in:
IzzelAliz 2021-07-28 00:08:18 +08:00
parent e36e6d2910
commit 4924f017e3
83 changed files with 601 additions and 292 deletions

View File

@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: "${forge_gradle_version}"
classpath 'org.spongepowered:mixingradle:0.7.1-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.7.2-SNAPSHOT'
classpath "io.izzel.arclight:arclight-gradle-plugin:$agpVersion"
}
}
@ -28,7 +28,7 @@ arclight {
// packageName = 'spigot'
}
// sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '11'
java.toolchain.languageVersion = JavaLanguageVersion.of(16)
minecraft {
mappings channel: 'official', version: minecraftVersion

View File

@ -10,7 +10,6 @@ import io.izzel.arclight.common.mod.util.log.ArclightLazyLogManager;
import io.izzel.arclight.common.util.EnumTypeFactory;
import io.izzel.arclight.i18n.ArclightConfig;
import io.izzel.arclight.i18n.ArclightLocale;
import net.minecraftforge.server.ServerMain;
import java.io.InputStream;
import java.lang.reflect.Field;
@ -29,6 +28,7 @@ public abstract class ArclightMain {
public void run(String[] args) throws Throwable {
System.setProperty("java.util.logging.manager", ArclightLazyLogManager.class.getCanonicalName());
System.setProperty("log4j.jul.LoggerAdapter", "io.izzel.arclight.common.mod.util.log.ArclightLoggerAdapter");
System.setProperty("log4j.configurationFile", "arclight-log4j2.xml");
ArclightLocale.info("i18n.using-language", ArclightConfig.spec().getLocale().getCurrent(), ArclightConfig.spec().getLocale().getFallback());
this.afterSetup();
try {
@ -45,9 +45,8 @@ public abstract class ArclightMain {
}
try {
printLogo();
this.beforeStart();
this.dirtyHacks();
ServerMain.main(args);
this.beforeStart();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Fail to launch Arclight.");

View File

@ -3,6 +3,8 @@ package io.izzel.arclight.common.mixin.bukkit;
import io.izzel.arclight.common.bridge.bukkit.CraftItemStackBridge;
import io.izzel.arclight.common.bridge.bukkit.ItemMetaBridge;
import io.izzel.arclight.common.bridge.item.ItemStackBridge;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v.legacy.CraftLegacy;
@ -15,8 +17,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Objects;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
@Mixin(value = CraftItemStack.class, remap = false)
public abstract class CraftItemStackMixin implements CraftItemStackBridge {
@ -40,7 +40,7 @@ public abstract class CraftItemStackMixin implements CraftItemStackBridge {
}
// check when update
@Inject(method = "setItemMeta(Lnet/minecraft/world/item/ItemStack;Lorg/bukkit/inventory/meta/ItemMeta;)Z", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/item/ItemStack;func_77973_b()Lnet/minecraft/world/item/Item;"))
@Inject(method = "setItemMeta(Lnet/minecraft/world/item/ItemStack;Lorg/bukkit/inventory/meta/ItemMeta;)Z", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/item/ItemStack;m_41720_()Lnet/minecraft/world/item/Item;"))
private static void arclight$setCaps(ItemStack item, ItemMeta itemMeta, CallbackInfoReturnable<Boolean> cir) {
CompoundTag forgeCaps = ((ItemMetaBridge) itemMeta).bridge$getForgeCaps();
if (forgeCaps != null) {

View File

@ -5,6 +5,7 @@ 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;
@ -36,6 +37,7 @@ 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;
@ -75,7 +77,20 @@ public abstract class CraftServerMixin implements CraftServerBridge {
this.playerList = (DedicatedPlayerList) playerList;
}
@Inject(method = "unloadWorld(Lorg/bukkit/World;Z)Z", require = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getChunkSource()Lnet/minecraft/server/level/ServerChunkCache;"))
/**
* @author IzzelAliz
* @reason
*/
@Overwrite(remap = false)
public ConsoleReader getReader() {
try {
return new ConsoleReader();
} catch (IOException e) {
return null;
}
}
@Inject(method = "unloadWorld(Lorg/bukkit/World;Z)Z", remap = false, require = 1, at = @At(value = "INVOKE", ordinal = 1, target = "Ljava/util/Map;remove(Ljava/lang/Object;)Ljava/lang/Object;"))
private void arclight$unloadForge(World world, boolean save, CallbackInfoReturnable<Boolean> cir) {
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(((CraftWorld) world).getHandle()));
this.console.markWorldsDirty();

View File

@ -83,7 +83,7 @@ public abstract class LavaFluidMixin {
}
}
@Eject(method = "flowInto", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/IWorld;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z"))
@Eject(method = "spreadTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/LevelAccessor;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
private boolean arclight$blockFromTo(LevelAccessor world, BlockPos pos, BlockState newState, int flags, CallbackInfo ci) {
if (!CraftEventFactory.handleBlockFormEvent(((IWorldBridge) world).bridge$getMinecraftWorld(), pos, newState, flags)) {
ci.cancel();

View File

@ -208,8 +208,8 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
class Handler extends Thread {
Handler() {
super(SidedThreadGroups.SERVER, "User Authenticator #" + UNIQUE_THREAD_ID.incrementAndGet());
Handler(int i) {
super(SidedThreadGroups.SERVER, "User Authenticator #" + i);
}
public void run() {
@ -249,12 +249,12 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
return server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null;
}
}
Thread thread = new Handler();
Thread thread = new Handler(UNIQUE_THREAD_ID.incrementAndGet());
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
thread.start();
}
private void arclight$preLogin() throws Exception {
void arclight$preLogin() throws Exception {
String playerName = gameProfile.getName();
InetAddress address = ((InetSocketAddress) connection.getRemoteAddress()).getAddress();
UUID uniqueId = gameProfile.getId();

View File

@ -62,8 +62,10 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge {
@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;
private void arclight$outOfBound(BlockPos pos, CallbackInfo ci, LevelChunk chunk, int i) {
if (i < 0 || i >= this.changedBlocksPerSection.length) {
ci.cancel();
}
}
@Inject(method = "updateFutures", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 0),

View File

@ -35,7 +35,7 @@ public abstract class TicketManagerMixin implements TicketManagerBridge {
// @formatter:on
@Inject(method = "removePlayer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", remap = false, target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;remove(Ljava/lang/Object;)Z"))
private void arclight$remove(SectionPos p_140829_, ServerPlayer p_140830_, CallbackInfo ci, ObjectSet<?> set) {
private void arclight$remove(SectionPos p_140829_, ServerPlayer p_140830_, CallbackInfo ci, long l, ObjectSet<?> set) {
if (set == null) {
ci.cancel();
}

View File

@ -100,10 +100,14 @@ import java.util.UUID;
public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, ICommandSourceBridge {
// @formatter:off
@Shadow public float yRot;
@Shadow private float yRot;
@Shadow public Level level;
@Shadow protected int boardingCooldown;
@Shadow public float xRot;
@Shadow private float xRot;
@Shadow public abstract float getYRot();
@Shadow public abstract float getXRot();
@Shadow public abstract void setYRot(float p_146923_);
@Shadow public abstract void setXRot(float p_146927_);
@Shadow public int remainingFireTicks;
@Shadow public abstract Pose getPose();
@Shadow public abstract String getScoreboardName();
@ -244,7 +248,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
}
public float getBukkitYaw() {
return yRot;
return getYRot();
}
@Override
@ -468,11 +472,11 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Inject(method = "saveWithoutId", at = @At(value = "INVOKE_ASSIGN", ordinal = 1, target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;"))
public void arclight$writeWithoutTypeId$InfiniteValueCheck(CompoundTag compound, CallbackInfoReturnable<CompoundTag> cir) {
if (Float.isNaN(this.yRot)) {
if (Float.isNaN(this.getYRot())) {
this.yRot = 0;
}
if (Float.isNaN(this.xRot)) {
if (Float.isNaN(this.getXRot())) {
this.xRot = 0;
}
}
@ -823,7 +827,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
} else {
ServerLevel world = ((PortalInfoBridge) portalinfo).bridge$getWorld() == null ? server : ((PortalInfoBridge) portalinfo).bridge$getWorld();
this.unRide();
Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, (ServerLevel) this.level, server, this.yRot, spawnPortal -> { //Forge: Start vanilla logic
Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, (ServerLevel) this.level, server, this.getYRot(), spawnPortal -> { //Forge: Start vanilla logic
this.level.getProfiler().popPush("reloading");
Entity entity = this.getType().create(world);
if (entity != null) {
@ -908,7 +912,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
}
ArclightCaptures.captureCraftPortalEvent(event);
return PortalShape.createPortalInfo(worldFinal, result, direction$axis, vector3d, this.getDimensions(this.getPose()), this.getDeltaMovement(), this.yRot, this.xRot);
return PortalShape.createPortalInfo(worldFinal, result, direction$axis, vector3d, this.getDimensions(this.getPose()), this.getDeltaMovement(), this.getYRot(), this.getXRot());
}).orElse(null);
}
} else {
@ -925,7 +929,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
}
blockpos = new BlockPos(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
PortalInfo portalInfo = new PortalInfo(new Vec3((double) blockpos.getX() + 0.5D, blockpos.getY(), (double) blockpos.getZ() + 0.5D), this.getDeltaMovement(), this.yRot, this.xRot);
PortalInfo portalInfo = new PortalInfo(new Vec3((double) blockpos.getX() + 0.5D, blockpos.getY(), (double) blockpos.getZ() + 0.5D), this.getDeltaMovement(), this.getYRot(), this.getXRot());
((PortalInfoBridge) portalInfo).bridge$setWorld(((CraftWorld) event.getTo().getWorld()).getHandle());
((PortalInfoBridge) portalInfo).bridge$setPortalEventInfo(event);
return portalInfo;

View File

@ -387,13 +387,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
}
@Eject(method = "onLivingFall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
private boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
boolean ret = livingEntity.hurt(source, amount);
cir.setReturnValue(ret);
return ret;
}
@Override
public boolean bridge$canPickUpLoot() {
return bukkitPickUpLoot;
@ -622,7 +615,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
d1 = (Math.random() - Math.random()) * 0.01D;
}
this.hurtDir = (float) (Mth.atan2(d0, d1) * (double) (180F / (float) Math.PI) - (double) this.yRot);
this.hurtDir = (float) (Mth.atan2(d0, d1) * (double) (180F / (float) Math.PI) - (double) this.getYRot());
this.knockback(0.4F, d1, d0);
} else {
this.hurtDir = (float) ((int) (Math.random() * 2.0D) * 180);
@ -926,7 +919,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
@Inject(method = "createWitherRose", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private void arclight$witherRoseDrop(LivingEntity livingEntity, CallbackInfo ci, ItemEntity itemEntity) {
private void arclight$witherRoseDrop(LivingEntity livingEntity, CallbackInfo ci, boolean flag, ItemEntity itemEntity) {
org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) (((EntityBridge) itemEntity).bridge$getBukkitEntity()));
CraftEventFactory.callEvent(event);
if (event.isCancelled()) {

View File

@ -25,7 +25,7 @@ public class SkeletonTrapGoalMixin {
@Shadow @Final private SkeletonHorse horse;
// @formatter:on
@Inject(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;func_242417_l(Lnet/minecraft/world/entity/Entity;)V"),
@Inject(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"),
slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/horse/SkeletonTrapGoal;createHorse(Lnet/minecraft/world/DifficultyInstance;)Lnet/minecraft/world/entity/animal/horse/AbstractHorse;")))
private void arclight$thunder(CallbackInfo ci) {
((WorldBridge) this.horse.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.TRAP);
@ -37,7 +37,7 @@ public class SkeletonTrapGoalMixin {
return true;
}
@Inject(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;func_242417_l(Lnet/minecraft/world/entity/Entity;)V"),
@Inject(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"),
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/horse/SkeletonTrapGoal;createHorse(Lnet/minecraft/world/DifficultyInstance;)Lnet/minecraft/world/entity/animal/horse/AbstractHorse;")))
private void arclight$jockey(CallbackInfo ci) {
((WorldBridge) this.horse.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.JOCKEY);

View File

@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(targets = "net.minecraft.world.entity.animal.Bee.BeeGrowCropGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Bee$BeeGrowCropGoal")
public class Bee_GrowCropGoalMixin {
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_28021_"}, remap = false)

View File

@ -9,7 +9,7 @@ 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.entity.animal.Bee.BeeHurtByOtherGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Bee$BeeHurtByOtherGoal")
public class Bee_HurtByOtherGoalMixin {
@Inject(method = "alertOther", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V"))

View File

@ -29,7 +29,9 @@ public interface BucketableMixin {
* @reason
*/
@Overwrite
static <T extends LivingEntity & Bucketable> Optional<InteractionResult> bucketMobPickup(Player player, InteractionHand hand, T entity) {
static <T extends LivingEntity & Bucketable> Optional<InteractionResult> bucketMobPickup(Player player, InteractionHand hand, LivingEntity livingEntity) {
@SuppressWarnings("unchecked")
T entity = (T) livingEntity;
ItemStack itemstack = player.getItemInHand(hand);
if (itemstack.getItem() == Items.WATER_BUCKET && entity.isAlive()) {
// entity.playSound(entity.getPickupSound(), 1.0F, 1.0F);

View File

@ -9,7 +9,7 @@ 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.entity.animal.Dolphin.DolphinSwimWithPlayerGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Dolphin$DolphinSwimWithPlayerGoal")
public class DolphinEntity_SwimWithPlayerGoalMixin {
// @formatter:off

View File

@ -18,7 +18,7 @@ import org.bukkit.event.entity.EntityBreedEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(targets = "net.minecraft.world.entity.animal.Fox.FoxBreedGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Fox$FoxBreedGoal")
public abstract class Fox_BreedGoalMixin extends BreedGoal {
public Fox_BreedGoalMixin(Animal animal, double speedIn) {

View File

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

View File

@ -9,7 +9,7 @@ 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.entity.animal.Panda.PandaHurtByTargetGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Panda$PandaHurtByTargetGoal")
public class Panda_HurtByTargetGoalMixin {
@Inject(method = "alertOther", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V"))

View File

@ -1,6 +1,5 @@
package io.izzel.arclight.common.mixin.core.world.entity.animal;
import io.izzel.arclight.common.mixin.core.world.entity.animal.AnimalMixin;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.animal.Parrot;
@ -21,7 +20,7 @@ public abstract class ParrotMixin extends AnimalMixin {
bridge$pushEffectCause(EntityPotionEffectEvent.Cause.FOOD);
}
@Redirect(method = "hurt", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/entity/animal/Parrot;setOrderedToSit(Z)V"))
@Redirect(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Parrot;setOrderedToSit(Z)V"))
private void arclight$handledInSuper(Parrot parrotEntity, boolean p_233687_1_) {
}

View File

@ -16,15 +16,15 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(targets = "net.minecraft.world.entity.animal.Rabbit.RaidGardenGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Rabbit$RaidGardenGoal")
public class Rabbit_RaidGardenGoalMixin {
@Shadow @Final private Rabbit rabbit;
@Inject(method = "tick", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"))
private void arclight$entityChangeBlock(CallbackInfo ci, Level world, BlockPos blockPos, BlockState blockState, Block block, Integer integer) {
if (integer == 0) {
private void arclight$entityChangeBlock(CallbackInfo ci, Level world, BlockPos blockPos, BlockState blockState, Block block, int i) {
if (i == 0) {
if (CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockPos, Blocks.AIR.defaultBlockState()).isCancelled()) {
ci.cancel();
}
@ -32,7 +32,7 @@ public class Rabbit_RaidGardenGoalMixin {
if (CraftEventFactory.callEntityChangeBlockEvent(
this.rabbit,
blockPos,
blockState.setValue(CarrotBlock.AGE, integer - 1)
blockState.setValue(CarrotBlock.AGE, i - 1)
).isCancelled()) {
ci.cancel();
}

View File

@ -16,7 +16,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(targets = "net.minecraft.world.entity.animal.Turtle.TurtleLayEggGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.Turtle$TurtleLayEggGoal")
public abstract class Turtle_LayEggGoalMixin extends MoveToBlockGoal {
@Shadow @Final private Turtle turtle;

View File

@ -8,7 +8,7 @@ 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.entity.animal.horse.TraderLlama.TraderLlamaDefendWanderingTraderGoal")
@Mixin(targets = "net.minecraft.world.entity.animal.horse.TraderLlama$TraderLlamaDefendWanderingTraderGoal")
public class TraderLlamaEntity_FollowTraderGoalMixin extends TargetGoalMixin {
@Inject(method = "start", at = @At("HEAD"))

View File

@ -46,7 +46,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin {
@Override
public float getBukkitYaw() {
return this.yRot;
return this.getYRot();
}
@Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V"))

View File

@ -27,12 +27,12 @@ public abstract class FallingBlockEntityMixin extends EntityMixin {
}
}
@Inject(method = "causeFallDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
@Inject(method = "causeFallDamage", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V"))
private void arclight$damageSource(float distance, float damageMultiplier, DamageSource source, CallbackInfoReturnable<Boolean> cir) {
CraftEventFactory.entityDamage = (FallingBlockEntity) (Object) this;
}
@Inject(method = "causeFallDamage", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
@Inject(method = "causeFallDamage", at = @At(value = "INVOKE", remap = false, shift = At.Shift.AFTER, target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V"))
private void arclight$damageSourceReset(float distance, float damageMultiplier, DamageSource source, CallbackInfoReturnable<Boolean> cir) {
CraftEventFactory.entityDamage = null;
}

View File

@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Random;
@Mixin(targets = "net.minecraft.world.entity.monster.EnderMan.EndermanLeaveBlockGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.EnderMan$EndermanLeaveBlockGoal")
public class EnderMan_EndermanLeaveBlockGoalMixin {
// @formatter:off

View File

@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Random;
@Mixin(targets = "net.minecraft.world.entity.monster.EnderMan.EndermanTakeBlockGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.EnderMan$EndermanTakeBlockGoal")
public class EnderMan_EndermanTakeBlockGoalMixin {
// @formatter:off

View File

@ -10,7 +10,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.monster.Ghast;
import net.minecraft.world.level.Level;
@Mixin(targets = "net.minecraft.world.entity.monster.Ghast.GhastShootFireballGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Ghast$GhastShootFireballGoal")
public abstract class Ghast_GhastShootFireballGoalMixin {
@Shadow @Final private Ghast ghast;

View File

@ -9,7 +9,7 @@ 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.entity.monster.Illusioner.IllusionerBlindnessSpellGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Illusioner$IllusionerBlindnessSpellGoal")
public class Illusioner_BlindnessSpellGoalMixin {
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_32941_"}, remap = false)

View File

@ -9,7 +9,7 @@ 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.entity.monster.Illusioner.IllusionerMirrorSpellGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Illusioner$IllusionerMirrorSpellGoal")
public class Illusioner_MirrorSpellGoalMixin {
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_32955_"}, remap = false)

View File

@ -9,13 +9,14 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(targets = "net.minecraft.world.entity.monster.Phantom.PhantomAttackPlayerTargetGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Phantom$PhantomAttackPlayerTargetGoal")
public abstract class Phantom_AttackPlayerTargetGoalMixin {
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_33191_"}, remap = false)
private Phantom outerThis;
@Inject(method = "canContinueToUse", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/entity/monster/Phantom$PhantomAttackPlayerTargetGoal;canAttack(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/ai/targeting/TargetingConditions;)Z"))
// canUse setTarget
@Inject(method = "m_8036_()Z", remap = false, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Phantom;m_6710_(Lnet/minecraft/world/entity/LivingEntity;)V"))
private void arclight$reason(CallbackInfoReturnable<Boolean> cir) {
((MobEntityBridge) outerThis).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true);
}

View File

@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(targets = "net.minecraft.world.entity.monster.Silverfish.SilverfishMergeWithStoneGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Silverfish$SilverfishMergeWithStoneGoal")
public abstract class Silverfish_MergeWithStoneGoalMixin extends RandomStrollGoal {
public Silverfish_MergeWithStoneGoalMixin(PathfinderMob creatureIn, double speedIn) {

View File

@ -18,7 +18,7 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.Random;
@Mixin(targets = "net.minecraft.world.entity.monster.Silverfish.SilverfishWakeUpFriendsGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Silverfish$SilverfishWakeUpFriendsGoal")
public abstract class Silverfish_WakeUpFriendsGoalMixin extends Goal {
@Shadow private int lookForFriends;

View File

@ -12,8 +12,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class SpellcastingIllager_UseSpellGoalMixin {
// @formatter:off
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_33774_"}, remap = false) private SpellcasterIllager outerThis;
@Shadow protected abstract SpellcasterIllager.IllagerSpell getSpell();
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_33776_"}, remap = false) private SpellcasterIllager outerThis;
@Shadow(aliases = "m_7269_") protected abstract SpellcasterIllager.IllagerSpell getSpell();
// @formatter:on
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/SpellcasterIllager$SpellcasterUseSpellGoal;performSpellCasting()V"))

View File

@ -9,7 +9,7 @@ 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.entity.monster.Vex.VexCopyOwnerTargetGoal")
@Mixin(targets = "net.minecraft.world.entity.monster.Vex$VexCopyOwnerTargetGoal")
public abstract class Vex_CopyOwnerTargetGoalMixin {
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_34052_"}, remap = false)

View File

@ -65,7 +65,7 @@ public abstract class ZombieMixin extends PathfinderMobMixin {
}
}
@Eject(method = "onKillEntity", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/entity/merchant/villager/VillagerEntity;func_233656_b_(Lnet/minecraft/entity/EntityType;Z)Lnet/minecraft/entity/MobEntity;"))
@Eject(method = "killed", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;convertTo(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;"))
private <T extends Mob> T arclight$transform(Villager villagerEntity, EntityType<T> entityType, boolean flag, CallbackInfo ci) {
((WorldBridge) villagerEntity.level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.INFECTION);
((MobEntityBridge) villagerEntity).bridge$pushTransformReason(EntityTransformEvent.TransformReason.INFECTION);

View File

@ -30,7 +30,7 @@ public abstract class ZombieVillagerMixin extends ZombieMixin {
bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONVERSION);
}
@Eject(method = "cureZombie", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/entity/monster/ZombieVillagerEntity;func_233656_b_(Lnet/minecraft/entity/EntityType;Z)Lnet/minecraft/entity/MobEntity;"))
@Eject(method = "finishConversion", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/ZombieVillager;convertTo(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;"))
private <T extends Mob> T arclight$cure(net.minecraft.world.entity.monster.ZombieVillager zombieVillagerEntity, EntityType<T> entityType, boolean flag, CallbackInfo ci) {
T t = this.a(entityType, flag, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED);
if (t == null) {

View File

@ -2,7 +2,6 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.entity.MobEntityBridge;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.attributes.Attributes;
@ -12,12 +11,11 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.PigZombie;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.entity.PigZombieAngerEvent;
import org.jetbrains.annotations.Nullable;
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.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import java.util.UUID;
@ -26,8 +24,7 @@ public abstract class ZombifiedPiglinMixin extends ZombieMixin {
// @formatter:off
@Shadow public abstract UUID getPersistentAngerTarget();
@Shadow public abstract void setPersistentAngerTarget(@Nullable UUID target);
@Shadow public abstract void setRemainingPersistentAngerTime(int time);
@Shadow public abstract int getRemainingPersistentAngerTime();
// @formatter:on
/**
@ -50,15 +47,14 @@ public abstract class ZombifiedPiglinMixin extends ZombieMixin {
}
}
@Eject(method = "func_230258_H__", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombifiedPiglinEntity;setAngerTime(I)V"))
private void arclight$pigAngry(ZombifiedPiglin piglinEntity, int time, CallbackInfo ci) {
@ModifyArg(method = "startPersistentAngerTimer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/ZombifiedPiglin;setRemainingPersistentAngerTime(I)V"))
private int arclight$pigAngry(int time) {
Entity entity = ((ServerLevel) this.level).getEntity(this.getPersistentAngerTarget());
PigZombieAngerEvent event = new PigZombieAngerEvent((PigZombie) this.getBukkitEntity(), entity == null ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), time);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
this.setPersistentAngerTarget(null);
ci.cancel();
return this.getRemainingPersistentAngerTime();
}
this.setRemainingPersistentAngerTime(event.getNewAnger());
return event.getNewAnger();
}
}

View File

@ -319,9 +319,9 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
if (flag6) {
if (i > 0) {
if (entity instanceof LivingEntity) {
((LivingEntity) entity).knockback(i * 0.5f, Mth.sin(this.yRot * 0.017453292f), -Mth.cos(this.yRot * 0.017453292f));
((LivingEntity) entity).knockback(i * 0.5f, Mth.sin(this.getYRot() * 0.017453292f), -Mth.cos(this.getYRot() * 0.017453292f));
} else {
entity.push(-Mth.sin(this.yRot * 0.017453292f) * i * 0.5f, 0.1, Mth.cos(this.yRot * 0.017453292f) * i * 0.5f);
entity.push(-Mth.sin(this.getYRot() * 0.017453292f) * i * 0.5f, 0.1, Mth.cos(this.getYRot() * 0.017453292f) * i * 0.5f);
}
this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6));
this.setSprinting(false);
@ -331,7 +331,7 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt
final List<LivingEntity> list = this.level.getEntitiesOfClass(LivingEntity.class, entity.getBoundingBox().inflate(1.0, 0.25, 1.0));
for (final LivingEntity entityliving : list) {
if (entityliving != (Object) this && entityliving != entity && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr(entityliving) < 9.0 && entityliving.hurt(((DamageSourceBridge) DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this)).bridge$sweep(), f5)) {
entityliving.knockback(0.4f, Mth.sin(this.yRot * 0.017453292f), -Mth.cos(this.yRot * 0.017453292f));
entityliving.knockback(0.4f, Mth.sin(this.getYRot() * 0.017453292f), -Mth.cos(this.getYRot() * 0.017453292f));
}
}
this.level.playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0f, 1.0f);

View File

@ -488,7 +488,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
PortalInfo portalinfo = teleporter.getPortalInfo((ServerPlayer) (Object) this, server, this::findDimensionEntryPoint);
ServerLevel[] exitWorld = new ServerLevel[]{server};
if (portalinfo != null) {
Entity e = teleporter.placeEntity((ServerPlayer) (Object) this, serverworld, exitWorld[0], this.yRot, spawnPortal -> {//Forge: Start vanilla logic
Entity e = teleporter.placeEntity((ServerPlayer) (Object) this, serverworld, exitWorld[0], this.getYRot(), spawnPortal -> {//Forge: Start vanilla logic
serverworld.getProfiler().push("moving");
if (((PortalInfoBridge) portalinfo).bridge$getWorld() != null) {
@ -568,7 +568,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
@Override
protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, BlockPos exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) {
Location enter = this.getBukkitEntity().getLocation();
Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ(), this.yRot, this.xRot);
Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ(), this.getYRot(), this.getXRot());
PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, 128, true, creationRadius);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) {
@ -602,7 +602,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla
if (this.bedBlocked(blockposition, enumdirection)) {
return Either.left(Player.BedSleepingProblem.OBSTRUCTED);
}
this.setRespawnPosition(this.level.dimension(), blockposition, this.yRot, false, true);
this.setRespawnPosition(this.level.dimension(), blockposition, this.getYRot(), false, true);
if (this.level.isDay()) {
return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW);
}

View File

@ -24,7 +24,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(net.minecraft.world.entity.projectile.AbstractArrow.class)
public abstract class AbstractArrowMixin extends ProjectileMixin {
@ -37,8 +36,8 @@ public abstract class AbstractArrowMixin extends ProjectileMixin {
@Shadow protected abstract ItemStack getPickupItem();
// @formatter:on
@Inject(method = "tick", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;hasImpulse:Z"))
private void arclight$hitEvent(CallbackInfo ci, HitResult hitResult) {
@Redirect(method = "tick", at = @At(value = "INVOKE", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;onHit(Lnet/minecraft/world/phys/HitResult;)V"))
private void arclight$hitEvent(net.minecraft.world.entity.projectile.AbstractArrow abstractArrow, HitResult hitResult) {
this.preOnHit(hitResult);
}

View File

@ -46,7 +46,7 @@ public abstract class ThrownEggMixin extends ThrowableProjectileMixin {
}
if (hatching) {
for (int i = 0; i < b0; ++i) {
Entity entity = ((WorldBridge) this.level).bridge$getWorld().createEntity(new Location(((WorldBridge) this.level).bridge$getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0f), hatchingType.getEntityClass());
Entity entity = ((WorldBridge) this.level).bridge$getWorld().createEntity(new Location(((WorldBridge) this.level).bridge$getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0f), hatchingType.getEntityClass());
if (((EntityBridge) entity).bridge$getBukkitEntity() instanceof Ageable) {
((Ageable) ((EntityBridge) entity).bridge$getBukkitEntity()).setBaby();
}

View File

@ -6,6 +6,7 @@ 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 net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -15,6 +16,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
import java.util.Map;
@Mixin(Raids.class)
@ -26,7 +28,7 @@ public class RaidManagerMixin {
@Inject(method = "createOrExtendRaid", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;absorbBadOmen(Lnet/minecraft/world/entity/player/Player;)V"))
public void arclight$raidTrigger(ServerPlayer playerEntity, CallbackInfoReturnable<Raid> cir,
DimensionType dimensionType, BlockPos pos, BlockPos pos1, Raid raid) {
DimensionType dimensionType, BlockPos pos, BlockPos pos1, List<?> list, int i, Vec3 vec, Raid raid) {
if (!CraftEventFactory.callRaidTriggerEvent(raid, playerEntity)) {
playerEntity.removeEffect(MobEffects.BAD_OMEN);
this.raidMap.remove(raid.getId(), raid);

View File

@ -134,8 +134,8 @@ public abstract class AbstractMinecartMixin extends EntityMixin {
double prevX = this.getX();
double prevY = this.getY();
double prevZ = this.getZ();
float prevYaw = this.yRot;
float prevPitch = this.xRot;
float prevYaw = this.getYRot();
float prevPitch = this.getXRot();
if (this.getHurtTime() > 0) {
this.setHurtTime(this.getHurtTime() - 1);
}
@ -150,15 +150,15 @@ public abstract class AbstractMinecartMixin extends EntityMixin {
double d0 = this.getX() + (this.lx - this.getX()) / this.lSteps;
double d2 = this.getY() + (this.ly - this.getY()) / this.lSteps;
double d3 = this.getZ() + (this.lz - this.getZ()) / this.lSteps;
double d4 = Mth.wrapDegrees(this.lyr - this.yRot);
this.yRot += (float) (d4 / this.lSteps);
this.xRot += (float) ((this.lxr - this.xRot) / this.lSteps);
double d4 = Mth.wrapDegrees(this.lyr - this.getYRot());
this.setYRot(this.getYRot() + (float) (d4 / this.lSteps));
this.setXRot(this.getXRot() + (float) ((this.lxr - this.getXRot()) / this.lSteps));
--this.lSteps;
this.setPos(d0, d2, d3);
this.setRot(this.yRot, this.xRot);
this.setRot(this.getYRot(), this.getXRot());
} else {
this.setPos(this.getX(), this.getY(), this.getZ());
this.setRot(this.yRot, this.xRot);
this.setRot(this.getYRot(), this.getXRot());
}
} else {
/*
@ -186,24 +186,24 @@ public abstract class AbstractMinecartMixin extends EntityMixin {
this.comeOffTrack();
}
this.checkInsideBlocks();
this.xRot = 0.0f;
this.setXRot(0.f);
double d5 = this.xo - this.getX();
double d6 = this.zo - this.getZ();
if (d5 * d5 + d6 * d6 > 0.001) {
this.yRot = (float) (Mth.atan2(d6, d5) * 180.0 / 3.141592653589793);
this.setYRot((float) (Mth.atan2(d6, d5) * 180.0 / 3.141592653589793));
if (this.flipped) {
this.yRot += 180.0f;
this.setYRot(this.getYRot() + 180.0f);
}
}
double d7 = Mth.wrapDegrees(this.yRot - this.yRotO);
double d7 = Mth.wrapDegrees(this.getYRot() - this.yRotO);
if (d7 < -170.0 || d7 >= 170.0) {
this.yRot += 180.0f;
this.setYRot(this.getYRot() + 180.0f);
this.flipped = !this.flipped;
}
this.setRot(this.yRot, this.xRot);
this.setRot(this.getYRot(), this.getXRot());
org.bukkit.World bworld = ((WorldBridge) this.level).bridge$getWorld();
Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch);
Location to = new Location(bworld, this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot);
Location to = new Location(bworld, this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
Vehicle vehicle = (Vehicle) this.getBukkitEntity();
Bukkit.getPluginManager().callEvent(new VehicleUpdateEvent(vehicle));
if (!from.equals(to)) {

View File

@ -80,7 +80,7 @@ public abstract class BoatMixin extends EntityMixin {
@Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/Boat;tickBubbleColumn()V"))
private void arclight$updateVehicle(CallbackInfo ci) {
final org.bukkit.World bworld = ((WorldBridge) this.level).bridge$getWorld();
final Location to = new Location(bworld, this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot);
final Location to = new Location(bworld, this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
final Vehicle vehicle = (Vehicle) this.getBukkitEntity();
Bukkit.getPluginManager().callEvent(new VehicleUpdateEvent(vehicle));
if (this.lastLocation != null && !this.lastLocation.equals(to)) {

View File

@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.Shadow;
@Mixin(MinecartCommandBlock.MinecartCommandBase.class)
public abstract class MinecartCommandBlock_MinecartCommandBaseMixin implements ICommandSourceBridge {
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "field_210168_a"}, remap = false)
@SuppressWarnings("target") @Shadow(aliases = {"this$0", "f_38537_"}, remap = false)
private MinecartCommandBlock outerThis;
public CommandSender getBukkitSender(CommandSourceStack wrapper) {

View File

@ -16,7 +16,6 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BucketPickup;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v.util.DummyGeneratorAccess;
@ -39,11 +38,11 @@ public abstract class BucketItemMixin {
// @formatter:on
@Inject(method = "use", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/BucketPickup;pickupBlock(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/world/item/ItemStack;"))
private void arclight$bucketFill(Level worldIn, Player playerIn, InteractionHand handIn, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, ItemStack stack, HitResult result) {
private void arclight$bucketFill(Level worldIn, Player playerIn, InteractionHand handIn, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, ItemStack stack, BlockHitResult result) {
BlockPos pos = ((BlockHitResult) result).getBlockPos();
BlockState state = worldIn.getBlockState(pos);
ItemStack dummyFluid = ((BucketPickup) state.getBlock()).pickupBlock(DummyGeneratorAccess.INSTANCE, pos, state);
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) worldIn, playerIn, pos, pos, ((BlockHitResult) result).getDirection(), stack, dummyFluid.getItem());
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) worldIn, playerIn, pos, pos, result.getDirection(), stack, dummyFluid.getItem());
if (event.isCancelled()) {
((ServerPlayer) playerIn).connection.send(new ClientboundBlockUpdatePacket(worldIn, pos));
((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().updateInventory();
@ -54,10 +53,9 @@ public abstract class BucketItemMixin {
}
@Inject(method = "use", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/BucketItem;emptyContents(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/phys/BlockHitResult;)Z"))
private void arclight$capture(Level worldIn, Player playerIn, InteractionHand handIn, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, ItemStack stack, HitResult result) {
BlockHitResult blockRayTraceResult = (BlockHitResult) result;
arclight$direction = blockRayTraceResult.getDirection();
arclight$click = blockRayTraceResult.getBlockPos();
private void arclight$capture(Level worldIn, Player playerIn, InteractionHand handIn, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, ItemStack stack, BlockHitResult result) {
arclight$direction = result.getDirection();
arclight$click = result.getBlockPos();
arclight$stack = stack;
}

View File

@ -35,7 +35,7 @@ public class CrossbowItemMixin {
private static transient boolean arclight$capturedBoolean;
@Eject(method = "fireProjectile", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
@Eject(method = "shootProjectile", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private static boolean arclight$addEntity(Level world, Entity entityIn, CallbackInfo ci, Level worldIn, LivingEntity shooter) {
if (arclight$capturedBoolean) {
if (!world.addFreshEntity(entityIn)) {

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.item;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.mixin.Eject;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.LivingEntity;
@ -24,10 +25,10 @@ public class DyeItemMixin {
@Shadow @Final private DyeColor dyeColor;
// @formatter:on
@Eject(method = "itemInteractionForEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/SheepEntity;setFleeceColor(Lnet/minecraft/item/DyeColor;)V"))
@Eject(method = "interactLivingEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Sheep;setColor(Lnet/minecraft/world/item/DyeColor;)V"))
private void arclight$sheepDyeWool(net.minecraft.world.entity.animal.Sheep sheepEntity, DyeColor color, CallbackInfoReturnable<Boolean> cir, ItemStack stack, Player playerIn, LivingEntity target, InteractionHand hand) {
byte bColor = (byte) this.dyeColor.getId();
SheepDyeWoolEvent event = new SheepDyeWoolEvent((Sheep) ((LivingEntityBridge) target).bridge$getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor));
SheepDyeWoolEvent event = new SheepDyeWoolEvent((Sheep) ((LivingEntityBridge) target).bridge$getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
cir.setReturnValue(false);

View File

@ -30,7 +30,7 @@ public abstract class EggItemMixin extends Item {
private void arclight$muteSound(Level world, Player player, double x, double y, double z, SoundEvent soundIn, SoundSource category, float volume, float pitch) {
}
@Eject(method = "onItemRightClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
@Eject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private boolean arclight$updateIfFail(Level world, Entity entityIn, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, Level worldIn, Player playerIn, @NotNull InteractionHand handIn) {
if (!worldIn.addFreshEntity(entityIn)) {
if (playerIn instanceof ServerPlayerEntityBridge) {

View File

@ -16,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(EnderEyeItem.class)
public class EnderEyeItemMixin {
@Eject(method = "onItemRightClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
@Eject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private boolean arclight$returnIfFail(Level world, Entity entityIn, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir, Level worldIn, Player playerIn, InteractionHand handIn) {
if (!world.addFreshEntity(entityIn)) {
cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.FAIL, playerIn.getItemInHand(handIn)));

View File

@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(MinecartItem.class)
public class MinecartItemMixin {
@Eject(method = "onItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
@Eject(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
private boolean arclight$entityPlace(Level world, Entity entityIn, CallbackInfoReturnable<InteractionResult> cir, UseOnContext context) {
if (CraftEventFactory.callEntityPlaceEvent(context, entityIn).isCancelled()) {
cir.setReturnValue(InteractionResult.FAIL);

View File

@ -30,7 +30,7 @@ public class TridentItemMixin {
if (j != 0) stack.hurtAndBreak(amount, entityIn, onBroken);
}
@Eject(method = "onPlayerStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
@Eject(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"))
public boolean arclight$addEntity(Level world, Entity entityIn, CallbackInfo ci, ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) {
if (!world.addFreshEntity(entityIn)) {
if (entityLiving instanceof ServerPlayer) {

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.level.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BasePressurePlateBlock;
import net.minecraft.world.level.block.state.BlockState;
@ -23,7 +24,7 @@ public abstract class BasePressurePlateBlockMixin {
// @formatter:on
@Redirect(method = "checkPressed", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/BasePressurePlateBlock;getSignalStrength(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)I"))
public int arclight$blockRedstone(BasePressurePlateBlock abstractPressurePlateBlock, Level worldIn, BlockPos pos, Level world, BlockPos blockPos, BlockState state, int oldRedstoneStrength) {
private int arclight$blockRedstone(BasePressurePlateBlock abstractPressurePlateBlock, Level worldIn, BlockPos pos, Entity entity, Level world, BlockPos blockPos, BlockState state, int oldRedstoneStrength) {
int newStrength = this.getSignalStrength(worldIn, pos);
boolean flag = oldRedstoneStrength > 0;
boolean flag1 = newStrength > 0;

View File

@ -16,8 +16,8 @@ public class ChestBlock2Mixin {
* @author IzzelAliz
* @reason
*/
@Overwrite
public Optional<MenuProvider> acceptDouble(final ChestBlockEntity p_225539_1_, final ChestBlockEntity p_225539_2_) {
@Overwrite(remap = false)
public Optional<MenuProvider> m_6959_(final ChestBlockEntity p_225539_1_, final ChestBlockEntity p_225539_2_) {
final CompoundContainer iinventory = new CompoundContainer(p_225539_1_, p_225539_2_);
return Optional.ofNullable(ChestBlockDoubleInventoryHacks.create(p_225539_1_, p_225539_2_, iinventory));
}

View File

@ -36,7 +36,7 @@ public abstract class ComposterBlockMixin {
// @formatter:on
@SuppressWarnings("UnresolvedMixinReference")
@Redirect(method = "getContainer", at = @At(value = "NEW", target = "()Lnet/minecraft/block/ComposterBlock$EmptyInventory;"))
@Redirect(method = "getContainer", at = @At(value = "NEW", target = "()Lnet/minecraft/world/level/block/ComposterBlock$EmptyContainer;"))
public ComposterBlock.EmptyContainer arclight$newEmpty(BlockState blockState, LevelAccessor world, BlockPos blockPos) {
ComposterBlock.EmptyContainer inventory = new ComposterBlock.EmptyContainer();
((IInventoryBridge) inventory).setOwner(new CraftBlockInventoryHolder(world, blockPos, inventory));

View File

@ -40,12 +40,12 @@ public class LayeredCauldronBlockMixin {
}
@Redirect(method = "handlePrecipitation", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z"))
private static boolean arclight$precipitation(Level level, BlockPos pos, BlockState state, BlockState old) {
private boolean arclight$precipitation(Level level, BlockPos pos, BlockState state, BlockState old) {
return CauldronHooks.changeLevel(old, level, pos, state, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL);
}
@Eject(method = "receiveStalactiteDrip", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z"))
private static boolean arclight$drip(Level level, BlockPos pos, BlockState state, BlockState old, CallbackInfo ci) {
private boolean arclight$drip(Level level, BlockPos pos, BlockState state, CallbackInfo ci, BlockState old) {
if (CauldronHooks.changeLevel(old, level, pos, state, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) {
return true;
} else {

View File

@ -80,7 +80,8 @@ public abstract class AbstractFurnaceBlockEntityMixin extends LockableBlockEntit
}
@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) {
private static void arclight$startSmelt(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity furnace, CallbackInfo ci,
boolean flag, boolean flag1, ItemStack stack, Recipe<?> recipe) {
if (recipe != null && furnace.cookingProgress == 0) {
CraftItemStack source = CraftItemStack.asCraftMirror(furnace.getItem(0));
CookingRecipe<?> cookingRecipe = (CookingRecipe<?>) ((IRecipeBridge) recipe).bridge$toBukkitRecipe();

View File

@ -2,6 +2,7 @@ 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.effect.MobEffectInstance;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
@ -12,17 +13,18 @@ import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
@Mixin(ConduitBlockEntity.class)
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"))
private static void arclight$addEntity(CallbackInfo ci, Player playerEntity) {
((PlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONDUIT);
@Redirect(method = "applyEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z"))
private static boolean arclight$addEntity(Player player, MobEffectInstance eff) {
((PlayerEntityBridge) player).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONDUIT);
return player.addEffect(eff);
}
@Inject(method = "updateDestroyTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))

View File

@ -30,7 +30,6 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList;
@ -70,7 +69,7 @@ public abstract class HopperBlockEntityMixin extends LockableBlockEntityMixin {
return HopperBlockEntity.addItem(source, destination, CraftItemStack.asNMSCopy(event.getItem()), direction);
}
@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;"))
@Eject(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, CallbackInfoReturnable<Boolean> cir, Hopper hopper, Container inv, int index) {
ItemStack origin = inv.getItem(index).copy();
CraftItemStack original = CraftItemStack.asCraftMirror(stack);

View File

@ -32,7 +32,7 @@ public abstract class RegionFileCacheMixin implements RegionFileCacheBridge {
@Inject(method = "getRegionFile", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(value = "NEW", target = "net/minecraft/world/level/chunk/storage/RegionFile"))
private void arclight$retIfSearch(ChunkPos pos, CallbackInfoReturnable<RegionFile> cir, long l, File file) {
private void arclight$retIfSearch(ChunkPos pos, CallbackInfoReturnable<RegionFile> cir, long l, RegionFile rf, File file) {
if (arclight$existOnly && !file.exists()) cir.setReturnValue(null);
}

View File

@ -31,7 +31,7 @@ public abstract class LootTableMixin implements LootTableBridge {
@Shadow protected abstract void shuffleAndSplitItems(List<ItemStack> stacks, int emptySlotsCount, Random rand);
// @formatter:on
@Eject(method = "fillInventory", at = @At(value = "INVOKE", target = "Lnet/minecraft/loot/LootTable;generate(Lnet/minecraft/loot/LootContext;)Ljava/util/List;"))
@Eject(method = "fill", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/loot/LootTable;getRandomItems(Lnet/minecraft/world/level/storage/loot/LootContext;)Ljava/util/List;"))
private List<ItemStack> arclight$nonPluginEvent(LootTable lootTable, LootContext context, CallbackInfo ci, Container inv) {
List<ItemStack> list = lootTable.getRandomItems(context);
if (!context.hasParam(LootContextParams.ORIGIN) && !context.hasParam(LootContextParams.THIS_ENTITY)) {

View File

@ -1,40 +0,0 @@
package io.izzel.arclight.common.mod;
import com.google.common.collect.ImmutableList;
import net.minecraftforge.fml.loading.moddiscovery.AbstractJarFileLocator;
import net.minecraftforge.forgespi.locating.IModFile;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
public abstract class ArclightLocator extends AbstractJarFileLocator {
private final IModFile arclight;
public ArclightLocator() {
this.arclight = loadJars();
}
protected abstract IModFile loadJars();
@Override
public List<IModFile> scanMods() {
return ImmutableList.of(arclight);
}
@Override
public String name() {
return "arclight";
}
@Override
public void initArguments(Map<String, ?> arguments) {
}
@Override
public Stream<Path> scanCandidates() {
return Stream.empty();
}
}

View File

@ -27,10 +27,10 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
private final Map<String, Map.Entry<List<FieldNode>, List<MethodNode>>> accessTransformer =
ImmutableMap.<String, Map.Entry<List<FieldNode>, List<MethodNode>>>builder()
.put("net.minecraft.world.World",
.put("net.minecraft.world.level.Level",
Maps.immutableEntry(
ImmutableList.of(
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "lastPhysicsProblem", "Lnet/minecraft/util/math/BlockPos;", null, null)
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "lastPhysicsProblem", "Lnet/minecraft/core/BlockPos;", null, null)
),
ImmutableList.of()
))
@ -43,63 +43,46 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getServer", "()Lnet/minecraft/server/MinecraftServer;", null, null)
)
))
.put("net.minecraft.world.server.TicketType",
.put("net.minecraft.server.level.TicketType",
Maps.immutableEntry(
ImmutableList.of(
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, "PLUGIN",
"Lnet/minecraft/world/server/TicketType;", null, null),
"Lnet/minecraft/server/level/TicketType;", null, null),
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, "PLUGIN_TICKET",
"Lnet/minecraft/world/server/TicketType;", null, null)
"Lnet/minecraft/server/level/TicketType;", null, null)
),
ImmutableList.of()
))
.put("net.minecraft.loot.LootParameters",
.put("net.minecraft.world.level.storage.loot.parameters.LootContextParams",
Maps.immutableEntry(
ImmutableList.of(
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, "LOOTING_MOD",
"Lnet/minecraft/loot/LootParameter;", null, null)
"Lnet/minecraft/world/level/storage/loot/parameters/LootContextParam;", null, null)
),
ImmutableList.of()
))
.put("net.minecraft.item.BlockItem",
.put("net.minecraft.world.item.BlockItem",
Maps.immutableEntry(
ImmutableList.of(),
ImmutableList.of(
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getBlockState", "(Lnet/minecraft/block/BlockState;Lnet/minecraft/nbt/CompoundNBT;)Lnet/minecraft/block/BlockState;", null, null)
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "getBlockState", "(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/level/block/state/BlockState;", null, null)
)
))
.put("net.minecraft.inventory.container.WorkbenchContainer",
.put("net.minecraft.world.entity.decoration.HangingEntity",
Maps.immutableEntry(
ImmutableList.of(),
ImmutableList.of(
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "a", "(ILnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/inventory/CraftingInventory;Lnet/minecraft/inventory/CraftResultInventory;Lnet/minecraft/inventory/container/Container;)V", null, null)
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "calculateBoundingBox", "(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;II)Lnet/minecraft/world/phys/AABB;", null, null)
)
))
.put("net.minecraft.entity.item.HangingEntity",
.put("net.minecraft.world.entity.decoration.ItemFrame",
Maps.immutableEntry(
ImmutableList.of(),
ImmutableList.of(
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "calculateBoundingBox", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;II)Lnet/minecraft/util/math/AxisAlignedBB;", null, null)
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "calculateBoundingBox", "(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;II)Lnet/minecraft/world/phys/AABB;", null, null)
)
))
.put("net.minecraft.entity.item.ItemFrameEntity",
Maps.immutableEntry(
ImmutableList.of(),
ImmutableList.of(
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "calculateBoundingBox", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;II)Lnet/minecraft/util/math/AxisAlignedBB;", null, null)
)
))
.put("net.minecraft.tileentity.SkullTileEntity",
Maps.immutableEntry(
ImmutableList.of(
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "executor", "Ljava/util/concurrent/ExecutorService;", null, null),
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "skinCache", "Lcom/google/common/cache/LoadingCache;", null, null)
),
ImmutableList.of(
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "b", "(Lcom/mojang/authlib/GameProfile;Lcom/google/common/base/Predicate;Z)Ljava/util/concurrent/Future;", null, null)
)
))
.put("net.minecraft.command.impl.ReloadCommand",
.put("net.minecraft.server.commands.ReloadCommand",
Maps.immutableEntry(
ImmutableList.of(),
ImmutableList.of(
@ -110,30 +93,26 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
// damn spigot
private final Map<String, Map<String, String>> fieldRenames = ImmutableMap.<String, Map<String, String>>builder()
.put("net.minecraft.world.chunk.Chunk", ImmutableMap.of("$$world", "field_76637_e"))
.put("net.minecraft.world.server.ServerWorld", ImmutableMap.of("$$worldDataServer", "field_241103_E_"))
.put("net.minecraft.world.level.chunk.LevelChunk", ImmutableMap.of("$$level", "f_62776_"))
.put("net.minecraft.server.level.ServerLevel", ImmutableMap.of("$$worldDataServer", "f_8549_"))
.build();
private final Set<String> modifyConstructor = ImmutableSet.<String>builder()
.add("net.minecraft.world.World")
.add("net.minecraft.world.server.ServerWorld")
.add("net.minecraft.world.ServerMultiWorld")
.add("net.minecraft.inventory.Inventory")
.add("net.minecraft.block.ComposterBlock")
.add("net.minecraft.block.ComposterBlock$EmptyInventory")
.add("net.minecraft.util.FoodStats")
.add("net.minecraft.inventory.CraftingInventory")
.add("net.minecraft.inventory.EnderChestInventory")
.add("net.minecraft.world.server.TicketManager")
.add("net.minecraft.item.MerchantOffer")
.add("net.minecraft.inventory.container.LecternContainer")
.add("net.minecraft.world.TrackedEntity")
.add("net.minecraft.util.math.shapes.IndirectMerger")
.add("net.minecraft.network.play.client.CCloseWindowPacket")
.add("net.minecraft.world.dimension.DimensionType")
.add("net.minecraft.util.text.Color")
.add("net.minecraft.command.Commands")
.add("net.minecraft.world.storage.SaveFormat$LevelSave")
.add("net.minecraft.world.level.Level")
.add("net.minecraft.server.level.ServerLevel")
.add("net.minecraft.world.SimpleContainer")
.add("net.minecraft.world.level.block.ComposterBlock")
.add("net.minecraft.world.level.block.ComposterBlock$EmptyContainer")
.add("net.minecraft.world.food.FoodData")
.add("net.minecraft.world.inventory.CraftingContainer")
.add("net.minecraft.world.inventory.PlayerEnderChestContainer")
.add("net.minecraft.world.item.trading.MerchantOffer")
.add("net.minecraft.world.inventory.LecternMenu")
.add("net.minecraft.server.level.ServerEntity")
.add("net.minecraft.network.protocol.game.ServerboundContainerClosePacket")
.add("net.minecraft.network.chat.TextColor")
.add("net.minecraft.commands.Commands")
.add("net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess")
.build();
@Override

View File

@ -8,6 +8,7 @@
"injectors": {
"defaultRequire": 1
},
"compatibilityLevel": "JAVA_11",
"mixins": [
"Arclight_ForgeEventMixin"
]

View File

@ -9,13 +9,13 @@
"injectors": {
"defaultRequire": 1
},
"compatibilityLevel": "JAVA_11",
"mixins": [
"BukkitCommandWrapperMixin",
"ColouredConsoleSenderMixin",
"CraftAbstractVillagerMixin",
"CraftBlockMixin",
"CraftBlockStateMixin",
"CraftChunkMixin",
"CraftConsoleCommandSenderMixin",
"CraftEntityMixin",
"CraftEventFactoryMixin",

View File

@ -14,6 +14,7 @@
"conformVisibility": true
},
"mixinPriority": 500,
"compatibilityLevel": "JAVA_11",
"mixins": [
"advancements.AdvancementMixin",
"commands.CommandNodeMixin",

View File

@ -8,6 +8,7 @@
"injectors": {
"defaultRequire": 1
},
"compatibilityLevel": "JAVA_11",
"mixins": [
"FMLWorldPersistenceHookMixin",
"ForgeEventFactoryMixin",

View File

@ -7,17 +7,22 @@ buildscript {
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: "${forge_gradle_version}"
classpath 'org.spongepowered:mixingradle:0.7.1-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.7.2-SNAPSHOT'
classpath "io.izzel.arclight:arclight-gradle-plugin:$agpVersion"
}
}
plugins {
id 'org.javamodularity.moduleplugin' version '1.8.7' apply false
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.spongepowered.mixin'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'io.izzel.arclight'
apply plugin: 'maven-publish'
apply plugin: 'org.javamodularity.moduleplugin'
arclight {
mcVersion = minecraftVersion
@ -31,8 +36,6 @@ arclight {
archivesBaseName = archivesBaseName + '-' + minecraftVersion
// sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '11'
sourceSets {
applaunch {
java {
@ -40,8 +43,17 @@ sourceSets {
runtimeClasspath += main.output
}
}
module {
java {
compileClasspath += main.output
compileClasspath += main.compileClasspath
runtimeClasspath += main.output
}
}
}
java.toolchain.languageVersion = JavaLanguageVersion.of(16)
configurations {
embed
implementation.extendsFrom(embed)
@ -64,11 +76,10 @@ repositories {
maven { url = 'https://maven.izzel.io/releases' }
}
def embedLibs = [/*'org.spongepowered:mixin:0.8.1',*/ 'org.ow2.asm:asm-util:9.0',
'org.ow2.asm:asm-analysis:9.0', 'org.yaml:snakeyaml:1.27',
def embedLibs = ['org.spongepowered:mixin:0.8.3.2', 'org.yaml:snakeyaml:1.28',
'org.xerial:sqlite-jdbc:3.34.0', 'mysql:mysql-connector-java:5.1.49',
'commons-lang:commons-lang:2.6', 'com.googlecode.json-simple:json-simple:1.1.1',
'org.apache.logging.log4j:log4j-jul:2.11.2', 'net.md-5:SpecialSource:1.9.0',
/*'commons-lang:commons-lang:2.6',*/ 'com.googlecode.json-simple:json-simple:1.1.1',
'org.apache.logging.log4j:log4j-jul:2.11.2', 'net.md-5:SpecialSource:1.10.0',
'org.jline:jline-terminal-jansi:3.12.1', 'org.fusesource.jansi:jansi:1.18',
'org.jline:jline-terminal:3.12.1', 'org.jline:jline-reader:3.12.1',
'jline:jline:2.12.1', 'org.apache.maven:maven-resolver-provider:3.8.1',
@ -80,12 +91,12 @@ def embedLibs = [/*'org.spongepowered:mixin:0.8.1',*/ 'org.ow2.asm:asm-util:9.0'
'org.apache.maven.resolver:maven-resolver-spi:1.6.2', 'org.apache.maven.resolver:maven-resolver-util:1.6.2',
'org.apache.maven.resolver:maven-resolver-impl:1.6.2', 'org.apache.httpcomponents:httpclient:4.5.12',
'org.apache.httpcomponents:httpcore:4.4.13', 'commons-codec:commons-codec:1.11',
'org.slf4j:jcl-over-slf4j:1.7.30']
'org.slf4j:jcl-over-slf4j:1.7.30', 'org.apache.logging.log4j:log4j-slf4j18-impl:2.14.1']
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 'org.spongepowered:mixin:0.8.3'
implementation(project(':arclight-common')) {
exclude module: 'forge'
}
@ -94,14 +105,12 @@ dependencies {
for (def lib : embedLibs) {
arclight lib
}
embed('org.apache.logging.log4j:log4j-slf4j-impl:2.8.1') {
exclude module: 'log4j-api'
}
embed 'net.md-5:bungeecord-chat:1.16-R0.4@jar'
embed "org.spigotmc:spigot-api:$minecraftVersion-R0.1-SNAPSHOT@jar"
embed 'com.github.ArclightTeam:mixin-tools:1.0.0@jar'
embed 'io.izzel.arclight:mixin-tools:1.0.1'
embed "io.izzel:tools:$toolsVersion"
embed "io.izzel.arclight:arclight-api:$apiVersion"
embed 'commons-lang:commons-lang:2.6@jar'
annotationProcessor 'org.spongepowered:mixin:0.8.3:processor'
annotationProcessor 'com.github.ArclightTeam:mixin-tools:1.0.0'
}
@ -128,20 +137,26 @@ jar {
manifest.attributes 'Implementation-Version': "arclight-$minecraftVersion-${project.version}-${getGitHash()}"
manifest.attributes 'Implementation-Vendor': 'Arclight Team'
manifest.attributes 'Implementation-Timestamp': new Date().format("yyyy-MM-dd HH:mm:ss")
manifest.attributes 'Add-Opens': 'java.base/sun.security.util java.base/java.util.jar'
manifest.attributes 'Add-Exports': 'java.base/sun.security.util'
manifest.attributes 'Automatic-Module-Name': 'arclight.boot'
from(configurations.embed.collect { it.isDirectory() ? it : zipTree(it) }) {
exclude "META-INF/MANIFEST.MF"
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
exclude "LICENSE.txt"
exclude "META-INF/services/**"
exclude "org/apache/commons/lang/enum/**"
}
from(project(':arclight-common').tasks.jar.outputs.files.collect { it.isDirectory() ? it : zipTree(it) })
from sourceSets.applaunch.output.classesDirs
from sourceSets.module.output.classesDirs
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
tasks.generateArclightMeta.doLast {
new File(project.buildDir, "arclight_cache/meta/META-INF/services").deleteDir()
}
remapSpigotJar {
includes.add('net/minecraft/block/ChestBlock$DoubleInventory')
includes.add('net/minecraft/tileentity/LecternTileEntity$LecternInventory')
@ -152,6 +167,7 @@ mixin {
}
compileJava {
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_16
options.compilerArgs << '-XDignore.symbol.file' << '-XDenableSunApiLintControl'
options.encoding = 'UTF-8'
}
@ -160,19 +176,23 @@ compileApplaunchJava {
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_7
}
compileModuleJava {
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_16
}
task srgJar(type: Jar) {
from(tasks.jar.outputs.files.collect { it.isDirectory() ? it : zipTree(it) }) {
include 'io/izzel/**'
exclude 'io/izzel/arclight/common/mixin/**'
}
classifier = 'srg'
archiveClassifier.set('srg')
}
task spigotJar(type: Jar) {
with tasks.srgJar
doLast {
def task = tasks.create('renameSpigotJar', net.minecraftforge.gradle.userdev.tasks.RenameJarInPlace)
task.input = archivePath
task.input = archiveFile.get().asFile
task.hasLog = false
task.mappings = project(':arclight-common').file('build/arclight_cache/tmp_srg/bukkit_srg.srg')
def args = task.args.toList()
@ -180,7 +200,7 @@ task spigotJar(type: Jar) {
task.setArgs(args)
task.apply()
}
classifier = 'spigot'
archiveClassifier.set('spigot')
}
task sourceJar(type: Jar) {

View File

@ -2,8 +2,8 @@ package io.izzel.arclight.server;
public class Launcher {
private static final int MIN_CLASS_VERSION = 52;
private static final int MIN_JAVA_VERSION = 8;
private static final int MIN_CLASS_VERSION = 60;
private static final int MIN_JAVA_VERSION = 16;
public static void main(String[] args) throws Throwable {
int javaVersion = (int) Float.parseFloat(System.getProperty("java.class.version"));

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.impl;
import cpw.mods.modlauncher.TransformingClassLoader;
import io.izzel.arclight.common.mod.ArclightConnector;
import io.izzel.arclight.i18n.ArclightConfig;
import org.spongepowered.asm.mixin.Mixins;
@ -9,7 +10,9 @@ public class ArclightConnector_Forge extends ArclightConnector {
@Override
public void connect() {
injectMcl();
super.connect();
if (true) return;
Mixins.addConfiguration("mixins.arclight.impl.forge.optimization.json");
if (ArclightConfig.spec().getOptimization().isRemoveStream()) {
Mixins.addConfiguration("mixins.arclight.impl.forge.optimization.stream.json");
@ -19,4 +22,9 @@ public class ArclightConnector_Forge extends ArclightConnector {
}
LOGGER.info("mixin-load.optimization");
}
private void injectMcl() {
var loader = (TransformingClassLoader) getClass().getClassLoader();
}
}

View File

@ -1,22 +0,0 @@
package io.izzel.arclight.impl;
import io.izzel.arclight.common.mod.ArclightLocator;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.forgespi.locating.IModFile;
import java.io.File;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.stream.Stream;
public class ArclightLocator_Forge extends ArclightLocator {
@Override
protected IModFile loadJars() {
try {
return ModFile.newFMLInstance(this, new File(ArclightLocator.class.getProtectionDomain().getCodeSource().getLocation().toURI()).toPath());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,17 +1,37 @@
package io.izzel.arclight.server;
import io.izzel.arclight.api.ArclightVersion;
import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.common.ArclightMain;
import io.izzel.arclight.forgeinstaller.ForgeInstaller;
import java.io.File;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
public class Main_Forge {
public static void main(String[] args) throws Throwable {
new ArclightMain() {
private Map.Entry<String, List<String>> install;
@Override
protected void afterSetup() throws Throwable {
ArclightVersion.setVersion(ArclightVersion.v1_16_4);
ForgeInstaller.install();
ArclightVersion.setVersion(ArclightVersion.v1_17_R1);
install = ForgeInstaller.install();
}
@Override
protected void beforeStart() throws Throwable {
var path = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getCanonicalPath();
System.setProperty("arclight.selfPath", path);
var cl = Class.forName(install.getKey());
var handle = Unsafe.lookup().findStatic(cl, "main", MethodType.methodType(void.class, String[].class));
var target = Stream.concat(install.getValue().stream(), Arrays.stream(args)).toArray(String[]::new);
handle.invoke((Object) target);
}
}.run(args);
}

View File

@ -1 +1 @@
io.izzel.arclight.impl.ArclightLocator_Forge
io.izzel.arclight.boot.ArclightLocator_Forge

View File

@ -3,6 +3,7 @@
"package": "io.izzel.arclight.impl.mixin.optimization.dfu",
"target": "@env(DEFAULT)",
"refmap": "mixins.arclight.impl.forge.refmap.json",
"compatibilityLevel": "JAVA_11",
"mixins": [
"CraftMagicNumbersMixin",
"DataFixerUpperMixin",

View File

@ -3,6 +3,7 @@
"package": "io.izzel.arclight.impl.mixin.optimization.general",
"target": "@env(DEFAULT)",
"refmap": "mixins.arclight.impl.forge.refmap.json",
"compatibilityLevel": "JAVA_11",
"mixins": [
"ClassInheritanceMultiMapMixin",
"EntityDataManagerMixin_Optimize",

View File

@ -3,6 +3,7 @@
"package": "io.izzel.arclight.impl.mixin.optimization.stream",
"target": "@env(DEFAULT)",
"refmap": "mixins.arclight.impl.forge.refmap.json",
"compatibilityLevel": "JAVA_11",
"mixins": [
"GoalSelectorMixin",
"ITaskQueue_PriorityMixin"

View File

@ -1,6 +1,6 @@
{
"pack": {
"description": "Arclight resources",
"pack_format": 6
"pack_format": 7
}
}

View File

@ -0,0 +1,96 @@
package io.izzel.arclight.boot;
import cpw.mods.jarhandling.JarMetadata;
import cpw.mods.jarhandling.SecureJar;
import cpw.mods.jarhandling.impl.SimpleJarMetadata;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.forgespi.locating.IModLocator;
import java.io.File;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import static java.lang.Class.forName;
public class ArclightLocator_Forge implements IModLocator {
private final IModFile arclight;
public ArclightLocator_Forge() {
this.arclight = loadJar();
}
@Override
public List<IModFile> scanMods() {
return List.of(arclight);
}
@Override
public String name() {
return "arclight";
}
@Override
public void scanFile(IModFile file, Consumer<Path> pathConsumer) {
final Function<Path, SecureJar.Status> status = p -> file.getSecureJar().verifyPath(p);
try (Stream<Path> files = Files.find(file.getSecureJar().getRootPath(), Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) {
file.setSecurityStatus(files.peek(pathConsumer).map(status).reduce((s1, s2) -> SecureJar.Status.values()[Math.min(s1.ordinal(), s2.ordinal())]).orElse(SecureJar.Status.INVALID));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void initArguments(Map<String, ?> arguments) {
}
@Override
public boolean isValid(IModFile modFile) {
return true;
}
protected IModFile loadJar() {
try {
var module = getClass().getModule();
for (var m : module.getLayer().modules()) {
module.addReads(m);
}
for (var layer : module.getLayer().parents()) {
layer.modules().forEach(module::addReads);
}
var cl = forName("net.minecraftforge.fml.loading.moddiscovery.ModFile");
var lookup = MethodHandles.lookup();
var handle = lookup.findStatic(cl, "newFMLInstance", MethodType.methodType(cl, IModLocator.class, SecureJar.class));
var path = new File(System.getProperty("arclight.selfPath")).toPath();
return (IModFile) handle.invoke(this, SecureJar.from(this::excludePackages, path));
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private static final Set<String> EXCLUDES = Set.of(
"com.google",
"io.izzel.arclight.boot",
"javax",
"org.slf4j",
"org.apache.logging.slf4j"
);
private JarMetadata excludePackages(SecureJar secureJar) {
secureJar.getPackages().removeIf(it -> EXCLUDES.stream().anyMatch(it::startsWith));
return new SimpleJarMetadata("arclight", null, secureJar.getPackages(),
List.of(new SecureJar.Provider(
"cpw.mods.modlauncher.serviceapi.ILaunchPluginService",
List.of("io.izzel.arclight.common.asm.ArclightImplementer")
)));
}
}

View File

@ -0,0 +1,10 @@
import io.izzel.arclight.boot.ArclightLocator_Forge;
open module arclight.boot {
requires net.minecraftforge.forgespi;
requires cpw.mods.securejarhandler;
requires jdk.unsupported;
exports io.izzel.arclight.boot;
uses net.minecraftforge.forgespi.locating.IModLocator;
provides net.minecraftforge.forgespi.locating.IModLocator with ArclightLocator_Forge;
}

View File

@ -1,9 +1,9 @@
allprojects {
group 'io.izzel.arclight'
version '1.0.20'
version '1.0.0-SNAPSHOT'
ext {
agpVersion = '1.18'
agpVersion = '1.20'
minecraftVersion = '1.17.1'
forgeVersion = '37.0.1'
apiVersion = '1.0.+'

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.forgeinstaller;
import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.i18n.LocalizedException;
import javax.net.ssl.SSLException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@ -52,12 +53,12 @@ public class FileDownloader implements Supplier<Path> {
URL url = new URL(this.url);
try (InputStream stream = redirect(url)) {
Files.copy(stream, path, StandardCopyOption.REPLACE_EXISTING);
} catch (SocketTimeoutException e) {
} catch (SocketTimeoutException | SSLException e) {
throw LocalizedException.checked("downloader.timeout", e, url);
}
if (Files.exists(path)) {
String hash = Util.hash(path);
if (hash.equals(this.hash)) return path;
if (hash.equalsIgnoreCase(this.hash)) return path;
else {
Files.delete(path);
throw LocalizedException.checked("downloader.hash-not-match", this.hash, hash, url);

View File

@ -14,6 +14,14 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
@ -23,41 +31,43 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessControlContext;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ForgeInstaller {
private static final MethodHandles.Lookup IMPL_LOOKUP = Unsafe.lookup();
private static final String[] MAVEN_REPO = {
"https://arclight.mcxk.net/"
};
private static final String INSTALLER_URL = "https://arclight.mcxk.net/net/minecraftforge/forge/%s-%s/forge-%s-%s-installer.jar";
private static final String SERVER_URL = "https://arclight.mcxk.net/net/minecraft/server/minecraft_server.%s.jar";
private static final Map<String, String> VERSION_HASH = ImmutableMap.of(
"1.14.4", "3dc3d84a581f14691199cf6831b71ed1296a9fdf",
"1.15.2", "bb2b6b1aefcd70dfd1892149ac3a215f6c636b07",
"1.16.3", "f02f4473dbf152c23d7d484952121db0b36698cb",
"1.16.4", "35139deedbd5182953cf1caa23835da59ca3d7cd",
"1.16.5", "1b557e7b033b583cd9f66746b7a9ab1ec1673ced"
"1.17.1", "A16D67E5807F57FC4E550299CF20226194497DC2"
);
public static void install() throws Throwable {
public static Map.Entry<String, List<String>> install() throws Throwable {
InputStream stream = ForgeInstaller.class.getResourceAsStream("/META-INF/installer.json");
InstallInfo installInfo = new Gson().fromJson(new InputStreamReader(stream), InstallInfo.class);
List<Supplier<Path>> suppliers = checkMavenNoSource(installInfo.libraries);
Path path = Paths.get(String.format("forge-%s-%s.jar", installInfo.installer.minecraft, installInfo.installer.forge));
Path path = Paths.get("libraries", "net", "minecraftforge", "forge", installInfo.installer.minecraft + "-" + installInfo.installer.forge, "win_args.txt");
if (!suppliers.isEmpty() || !Files.exists(path)) {
ArclightLocale.info("downloader.info2");
ExecutorService pool = Executors.newFixedThreadPool(8);
@ -84,7 +94,7 @@ public class ForgeInstaller {
handleFutures(array);
pool.shutdownNow();
}
classpath(path, installInfo);
return classpath(path, installInfo);
}
private static Function<Supplier<Path>, CompletableFuture<Path>> reportSupply(ExecutorService service) {
@ -115,7 +125,7 @@ public class ForgeInstaller {
});
CompletableFuture<?> serverFuture = reportSupply(pool).apply(
new FileDownloader(String.format(SERVER_URL, info.installer.minecraft),
String.format("minecraft_server.%s.jar", info.installer.minecraft), VERSION_HASH.get(info.installer.minecraft))
String.format("libraries/net/minecraft/server/%1$s/minecraft_server.%1$s.jar", info.installer.minecraft), VERSION_HASH.get(info.installer.minecraft))
);
return new CompletableFuture<?>[]{installerFuture, serverFuture};
}
@ -180,7 +190,66 @@ public class ForgeInstaller {
return incomplete;
}
private static void classpath(Path path, InstallInfo installInfo) throws Throwable {
private static Map.Entry<String, List<String>> classpath(Path path, InstallInfo installInfo) throws Throwable {
boolean jvmArgs = true;
String mainClass = null;
List<String> userArgs = new ArrayList<>();
List<String> opens = new ArrayList<>();
List<String> exports = new ArrayList<>();
List<String> ignores = new ArrayList<>();
List<String> merges = new ArrayList<>();
var self = new File(ForgeInstaller.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getCanonicalPath();
for (String arg : Files.lines(path).collect(Collectors.toList())) {
if (jvmArgs && arg.startsWith("-")) {
if (arg.startsWith("-p ")) {
addModules(arg.substring(2).trim());
} else if (arg.startsWith("--add-opens ")) {
opens.add(arg.substring("--add-opens ".length()).trim());
} else if (arg.startsWith("--add-exports ")) {
exports.add(arg.substring("--add-exports ".length()).trim());
} else if (arg.startsWith("-D")) {
var split = arg.substring(2).split("=", 2);
if (split[0].equals("legacyClassPath")) {
for (String lib : split[1].split(File.pathSeparator)) {
addToPath(Paths.get(lib), ignores.stream().anyMatch(lib::contains));
}
split[1] =
Stream.concat(
Stream.concat(Stream.of(split[1]), installInfo.libraries.keySet().stream()
.map(it -> Paths.get("libraries", Util.mavenToPath(it)))
.peek(it -> {
var name = it.getFileName().toString();
if (name.contains("maven-model")) {
merges.add(name);
}
})
.map(Path::toString)),
Stream.of(self)
).collect(Collectors.joining(File.pathSeparator));
} else if (split[0].equals("ignoreList")) {
ignores.addAll(Arrays.asList(split[1].split(",")));
}
System.setProperty(split[0], split[1]);
}
} else {
if (jvmArgs) {
jvmArgs = false;
mainClass = arg;
} else {
userArgs.addAll(Arrays.asList(arg.split(" ")));
}
}
}
var merge = String.join(",", merges);
var mergeModules = System.getProperty("mergeModules");
if (mergeModules != null) {
System.setProperty("mergeModules", mergeModules + ";" + merge);
} else {
System.setProperty("mergeModules", merge);
}
addOpens(opens);
addExports(exports);
/*
JarFile jarFile = new JarFile(path.toFile());
Manifest manifest = jarFile.getManifest();
String[] split = manifest.getMainAttributes().getValue("Class-Path").split(" ");
@ -190,11 +259,15 @@ public class ForgeInstaller {
for (String library : installInfo.libraries.keySet()) {
addToPath(Paths.get("libraries", Util.mavenToPath(library)));
}
addToPath(path);
addToPath(path);*/
for (String library : installInfo.libraries.keySet()) {
addToPath(Paths.get("libraries", Util.mavenToPath(library)), false);
}
return Map.entry(Objects.requireNonNull(mainClass, "No main class found"), userArgs);
}
private static void addToPath(Path path) throws Throwable {
ClassLoader loader = ForgeInstaller.class.getClassLoader();
private static void addToPath(Path path, boolean boot) throws Throwable {
ClassLoader loader = boot ? ClassLoader.getPlatformClassLoader() : ForgeInstaller.class.getClassLoader();
Field ucpField;
try {
ucpField = loader.getClass().getDeclaredField("ucp");
@ -203,7 +276,151 @@ public class ForgeInstaller {
}
long offset = Unsafe.objectFieldOffset(ucpField);
Object ucp = Unsafe.getObject(loader, offset);
if (ucp == null) {
var cl = Class.forName("jdk.internal.loader.URLClassPath");
var handle = Unsafe.lookup().findConstructor(cl, MethodType.methodType(void.class, URL[].class, AccessControlContext.class));
ucp = handle.invoke(new URL[]{}, (AccessControlContext) null);
Unsafe.putObjectVolatile(loader, offset, ucp);
}
Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
Unsafe.lookup().unreflect(method).invoke(ucp, path.toUri().toURL());
}
public static void addExports(List<String> exports) throws Throwable {
MethodHandle implAddExportsMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddExports", MethodType.methodType(void.class, String.class, Module.class));
MethodHandle implAddExportsToAllUnnamedMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddExportsToAllUnnamed", MethodType.methodType(void.class, String.class));
addExtra(exports, implAddExportsMH, implAddExportsToAllUnnamedMH);
}
public static void addOpens(List<String> opens) throws Throwable {
MethodHandle implAddOpensMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddOpens", MethodType.methodType(void.class, String.class, Module.class));
MethodHandle implAddOpensToAllUnnamedMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddOpensToAllUnnamed", MethodType.methodType(void.class, String.class));
addExtra(opens, implAddOpensMH, implAddOpensToAllUnnamedMH);
}
private static ParserData parseModuleExtra(String extra) {
String[] all = extra.split("=", 2);
if (all.length < 2) {
return null;
}
String[] source = all[0].split("/", 2);
if (source.length < 2) {
return null;
}
return new ParserData(source[0], source[1], all[1]);
}
private static class ParserData {
final String module;
final String packages;
final String target;
ParserData(String module, String packages, String target) {
this.module = module;
this.packages = packages;
this.target = target;
}
}
private static void addExtra(List<String> extras, MethodHandle implAddExtraMH, MethodHandle implAddExtraToAllUnnamedMH) {
extras.forEach(extra -> {
ParserData data = parseModuleExtra(extra);
if (data != null) {
ModuleLayer.boot().findModule(data.module).ifPresent(m -> {
try {
if ("ALL-UNNAMED".equals(data.target)) {
implAddExtraToAllUnnamedMH.invokeWithArguments(m, data.packages);
} else {
ModuleLayer.boot().findModule(data.target).ifPresent(tm -> {
try {
implAddExtraMH.invokeWithArguments(m, data.packages, tm);
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
}
});
}
@SuppressWarnings("unchecked")
private static void addModules(String modulePath) throws Throwable {
// Find all extra modules
ModuleFinder finder = ModuleFinder.of(Arrays.stream(modulePath.split(File.pathSeparator)).map(Paths::get).toArray(Path[]::new));
MethodHandle loadModuleMH = IMPL_LOOKUP.findVirtual(Class.forName("jdk.internal.loader.BuiltinClassLoader"), "loadModule", MethodType.methodType(void.class, ModuleReference.class));
// Resolve modules to a new config
Configuration config = Configuration.resolveAndBind(finder, List.of(ModuleLayer.boot().configuration()), finder, finder.findAll().stream().peek(mref -> {
try {
// Load all extra modules in system class loader (unnamed modules for now)
loadModuleMH.invokeWithArguments(ClassLoader.getSystemClassLoader(), mref);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}).map(ModuleReference::descriptor).map(ModuleDescriptor::name).collect(Collectors.toList()));
// Copy the new config graph to boot module layer config
MethodHandle graphGetter = IMPL_LOOKUP.findGetter(Configuration.class, "graph", Map.class);
HashMap<ResolvedModule, Set<ResolvedModule>> graphMap = new HashMap<>((Map<ResolvedModule, Set<ResolvedModule>>) graphGetter.invokeWithArguments(config));
MethodHandle cfSetter = IMPL_LOOKUP.findSetter(ResolvedModule.class, "cf", Configuration.class);
// Reset all extra resolved modules config to boot module layer config
graphMap.forEach((k, v) -> {
try {
cfSetter.invokeWithArguments(k, ModuleLayer.boot().configuration());
v.forEach(m -> {
try {
cfSetter.invokeWithArguments(m, ModuleLayer.boot().configuration());
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
});
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
});
graphMap.putAll((Map<ResolvedModule, Set<ResolvedModule>>) graphGetter.invokeWithArguments(ModuleLayer.boot().configuration()));
IMPL_LOOKUP.findSetter(Configuration.class, "graph", Map.class).invokeWithArguments(ModuleLayer.boot().configuration(), new HashMap<>(graphMap));
// Reset boot module layer resolved modules as new config resolved modules to prepare define modules
Set<ResolvedModule> oldBootModules = ModuleLayer.boot().configuration().modules();
MethodHandle modulesSetter = IMPL_LOOKUP.findSetter(Configuration.class, "modules", Set.class);
HashSet<ResolvedModule> modulesSet = new HashSet<>(config.modules());
modulesSetter.invokeWithArguments(ModuleLayer.boot().configuration(), new HashSet<>(modulesSet));
// Prepare to add all of the new config "nameToModule" to boot module layer config
MethodHandle nameToModuleGetter = IMPL_LOOKUP.findGetter(Configuration.class, "nameToModule", Map.class);
HashMap<String, ResolvedModule> nameToModuleMap = new HashMap<>((Map<String, ResolvedModule>) nameToModuleGetter.invokeWithArguments(ModuleLayer.boot().configuration()));
nameToModuleMap.putAll((Map<String, ResolvedModule>) nameToModuleGetter.invokeWithArguments(config));
IMPL_LOOKUP.findSetter(Configuration.class, "nameToModule", Map.class).invokeWithArguments(ModuleLayer.boot().configuration(), new HashMap<>(nameToModuleMap));
// Define all extra modules and add all of the new config "nameToModule" to boot module layer config
((Map<String, Module>) IMPL_LOOKUP.findGetter(ModuleLayer.class, "nameToModule", Map.class).invokeWithArguments(ModuleLayer.boot())).putAll((Map<String, Module>) IMPL_LOOKUP.findStatic(Module.class, "defineModules", MethodType.methodType(Map.class, Configuration.class, Function.class, ModuleLayer.class)).invokeWithArguments(ModuleLayer.boot().configuration(), (Function<String, ClassLoader>) name -> ClassLoader.getSystemClassLoader(), ModuleLayer.boot()));
// Add all of resolved modules
modulesSet.addAll(oldBootModules);
modulesSetter.invokeWithArguments(ModuleLayer.boot().configuration(), new HashSet<>(modulesSet));
// Reset cache of boot module layer
IMPL_LOOKUP.findSetter(ModuleLayer.class, "modules", Set.class).invokeWithArguments(ModuleLayer.boot(), null);
IMPL_LOOKUP.findSetter(ModuleLayer.class, "servicesCatalog", Class.forName("jdk.internal.module.ServicesCatalog")).invokeWithArguments(ModuleLayer.boot(), null);
// Add reads from extra modules to jdk modules
MethodHandle implAddReadsMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddReads", MethodType.methodType(void.class, Module.class));
config.modules().forEach(rm -> ModuleLayer.boot().findModule(rm.name()).ifPresent(m -> oldBootModules.forEach(brm -> ModuleLayer.boot().findModule(brm.name()).ifPresent(bm -> {
try {
implAddReadsMH.invokeWithArguments(m, bm);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}))));
}
}