Merge branch 'master' into experimental
This commit is contained in:
commit
f2e2132bb0
94 changed files with 1078 additions and 270 deletions
|
@ -0,0 +1,26 @@
|
|||
package ru.betterend.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.client.model.ArmorStandArmorModel;
|
||||
import net.minecraft.client.renderer.entity.ArmorStandRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import net.minecraft.world.entity.decoration.ArmorStand;
|
||||
import ru.betterend.client.render.ArmoredElytraLayer;
|
||||
|
||||
@Mixin(ArmorStandRenderer.class)
|
||||
public abstract class ArmorStandRendererMixin extends LivingEntityRenderer<ArmorStand, ArmorStandArmorModel> {
|
||||
|
||||
public ArmorStandRendererMixin(EntityRenderDispatcher entityRenderDispatcher, ArmorStandArmorModel entityModel, float f) {
|
||||
super(entityRenderDispatcher, entityModel, f);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
public void be_addCustomLayer(EntityRenderDispatcher entityRenderDispatcher, CallbackInfo info) {
|
||||
addLayer(new ArmoredElytraLayer<>(this));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package ru.betterend.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import ru.betterend.client.render.ArmoredElytraLayer;
|
||||
|
||||
@Mixin(HumanoidMobRenderer.class)
|
||||
public abstract class HumanoidMobRendererMixin<T extends Mob, M extends HumanoidModel<T>> extends MobRenderer<T, M> {
|
||||
|
||||
public HumanoidMobRendererMixin(EntityRenderDispatcher entityRenderDispatcher, M entityModel, float f) {
|
||||
super(entityRenderDispatcher, entityModel, f);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
public void be_addCustomLayer(EntityRenderDispatcher entityRenderDispatcher, M humanoidModel, float f, float g, float h, float i, CallbackInfo info) {
|
||||
addLayer(new ArmoredElytraLayer<>(this));
|
||||
}
|
||||
}
|
|
@ -21,6 +21,6 @@ public abstract class PlayerRendererMixin extends LivingEntityRenderer<AbstractC
|
|||
|
||||
@Inject(method = "<init>(Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;Z)V", at = @At("TAIL"))
|
||||
public void be_addCustomLayer(EntityRenderDispatcher entityRenderDispatcher, boolean bl, CallbackInfo info) {
|
||||
addLayer(new ArmoredElytraLayer<>(PlayerRenderer.class.cast(this)));
|
||||
addLayer(new ArmoredElytraLayer<>(this));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
|
||||
@Mixin(ArmorItem.class)
|
||||
public interface ArmorItemAccessor {
|
||||
@Accessor("ARMOR_MODIFIER_UUID_PER_SLOT")
|
||||
UUID[] be_getModifiers();
|
||||
|
||||
@Accessor("defaultModifiers")
|
||||
Multimap<Attribute, AttributeModifier> be_getDefaultModifiers();
|
||||
|
||||
@Accessor("defaultModifiers")
|
||||
void be_setDefaultModifiers(Multimap<Attribute, AttributeModifier> attributeModifiers);
|
||||
}
|
|
@ -1,13 +1,17 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.BitStorage;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.interfaces.IBiomeArray;
|
||||
|
||||
@Mixin(ChunkBiomeContainer.class)
|
||||
|
@ -34,6 +38,42 @@ public class ChunkBiomeContainerMixin implements IBiomeArray {
|
|||
int biomeY = pos.getY() >> 2;
|
||||
int biomeZ = pos.getZ() >> 2;
|
||||
int index = be_getArrayIndex(biomeX, biomeY, biomeZ);
|
||||
|
||||
if (BetterEnd.hasHydrogen()) {
|
||||
try {
|
||||
ChunkBiomeContainer self = (ChunkBiomeContainer) (Object) this;
|
||||
BitStorage storage = be_getHydrogenStorage(self);
|
||||
Biome[] palette = be_getHydrogenPalette(self);
|
||||
int paletteIndex = be_getHydrogenPaletteIndex(biome, palette);
|
||||
if (paletteIndex == -1) {
|
||||
Biome[] newPalette = new Biome[palette.length + 1];
|
||||
System.arraycopy(palette, 0, newPalette, 0, palette.length);
|
||||
paletteIndex = palette.length;
|
||||
palette = newPalette;
|
||||
palette[paletteIndex] = biome;
|
||||
be_setHydrogenPalette(self, palette);
|
||||
}
|
||||
try {
|
||||
storage.set(index, paletteIndex);
|
||||
}
|
||||
catch (Exception e) {
|
||||
int size = storage.getSize();
|
||||
int bits = Mth.ceillog2(palette.length);
|
||||
BitStorage newStorage = new BitStorage(bits, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
newStorage.set(i, storage.get(i));
|
||||
}
|
||||
storage = newStorage;
|
||||
storage.set(index, paletteIndex);
|
||||
be_setHydrogenStorage(self, storage);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
BetterEnd.LOGGER.warning(e.getLocalizedMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
biomes[index] = biome;
|
||||
}
|
||||
|
||||
|
@ -43,4 +83,37 @@ public class ChunkBiomeContainerMixin implements IBiomeArray {
|
|||
int k = biomeZ & HORIZONTAL_MASK;
|
||||
return j << WIDTH_BITS + WIDTH_BITS | k << WIDTH_BITS | i;
|
||||
}
|
||||
|
||||
private Field be_getField(String name) throws Exception {
|
||||
Field field = ChunkBiomeContainer.class.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
|
||||
private BitStorage be_getHydrogenStorage(ChunkBiomeContainer container) throws Exception {
|
||||
return (BitStorage) be_getField("intArray").get(container);
|
||||
}
|
||||
|
||||
private Biome[] be_getHydrogenPalette(ChunkBiomeContainer container) throws Exception {
|
||||
return (Biome[]) be_getField("palette").get(container);
|
||||
}
|
||||
|
||||
private int be_getHydrogenPaletteIndex(Biome biome, Biome[] palette) {
|
||||
int index = -1;
|
||||
for (int i = 0; i < palette.length; i++) {
|
||||
if (palette[i] == biome) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private void be_setHydrogenPalette(ChunkBiomeContainer container, Biome[] palette) throws Exception {
|
||||
be_getField("palette").set(container, palette);
|
||||
}
|
||||
|
||||
private void be_setHydrogenStorage(ChunkBiomeContainer container, BitStorage storage) throws Exception {
|
||||
be_getField("intArray").set(container, storage);
|
||||
}
|
||||
}
|
||||
|
|
100
src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java
Normal file
100
src/main/java/ru/betterend/mixin/common/EndDragonFightMixin.java
Normal file
|
@ -0,0 +1,100 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.pattern.BlockPattern;
|
||||
import net.minecraft.world.level.dimension.end.DragonRespawnAnimation;
|
||||
import net.minecraft.world.level.dimension.end.EndDragonFight;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import ru.betterend.util.BlocksHelper;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(EndDragonFight.class)
|
||||
public class EndDragonFightMixin {
|
||||
@Shadow
|
||||
private DragonRespawnAnimation respawnStage;
|
||||
@Shadow
|
||||
private boolean dragonKilled;
|
||||
@Shadow
|
||||
private BlockPos portalLocation;
|
||||
@Final
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
@Final
|
||||
@Shadow
|
||||
private ServerLevel level;
|
||||
|
||||
@Shadow
|
||||
private BlockPattern.BlockPatternMatch findExitPortal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Shadow
|
||||
private void spawnExitPortal(boolean bl) {}
|
||||
|
||||
@Shadow
|
||||
private void respawnDragon(List<EndCrystal> list) {}
|
||||
|
||||
@Inject(method = "tryRespawn", at = @At("HEAD"), cancellable = true)
|
||||
private void be_tryRespawnDragon(CallbackInfo info) {
|
||||
if (GeneratorOptions.replacePortal() && GeneratorOptions.hasDragonFights() && this.dragonKilled && this.respawnStage == null) {
|
||||
BlockPos blockPos = portalLocation;
|
||||
if (blockPos == null) {
|
||||
LOGGER.debug("Tried to respawn, but need to find the portal first.");
|
||||
BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal();
|
||||
if (blockPatternMatch == null) {
|
||||
LOGGER.debug("Couldn't find a portal, so we made one.");
|
||||
spawnExitPortal(true);
|
||||
}
|
||||
else {
|
||||
LOGGER.debug("Found the exit portal & temporarily using it.");
|
||||
}
|
||||
|
||||
blockPos = portalLocation;
|
||||
}
|
||||
|
||||
List<EndCrystal> crystals = Lists.newArrayList();
|
||||
BlockPos center = GeneratorOptions.getPortalPos().above(5);
|
||||
for (Direction dir : BlocksHelper.HORIZONTAL) {
|
||||
BlockPos central = center.relative(dir, 4);
|
||||
List<EndCrystal> crystalList = level.getEntitiesOfClass(EndCrystal.class, new AABB(central.below(10).south().west(), central.above(10).north().east()));
|
||||
|
||||
int count = crystalList.size();
|
||||
for (int n = 0; n < count; n++) {
|
||||
EndCrystal crystal = crystalList.get(n);
|
||||
if (!level.getBlockState(crystal.blockPosition().below()).is(Blocks.BEDROCK)) {
|
||||
crystalList.remove(n);
|
||||
count--;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
if (crystalList.isEmpty()) {
|
||||
info.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
crystals.addAll(crystalList);
|
||||
}
|
||||
|
||||
LOGGER.debug("Found all crystals, respawning dragon.");
|
||||
respawnDragon(crystals);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.feature.EndPodiumFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
@ -40,7 +41,7 @@ public class EndPodiumFeatureMixin {
|
|||
blockPos = be_updatePos(blockPos, world);
|
||||
StructureTemplate structure = StructureHelper.readStructure(BetterEnd.makeID(active ? "portal/end_portal_active" : "portal/end_portal_inactive"));
|
||||
BlockPos size = structure.getSize();
|
||||
blockPos = blockPos.offset(-(size.getX() >> 1), -3, -(size.getZ() >> 1));
|
||||
blockPos = blockPos.offset(-(size.getX() >> 1), -1, -(size.getZ() >> 1));
|
||||
structure.placeInWorldChunk(world, blockPos, new StructurePlaceSettings(), random);
|
||||
info.setReturnValue(true);
|
||||
info.cancel();
|
||||
|
@ -56,7 +57,7 @@ public class EndPodiumFeatureMixin {
|
|||
if (GeneratorOptions.useNewGenerator()) {
|
||||
BlockPos pos = GeneratorOptions.getPortalPos();
|
||||
if (pos.equals(BlockPos.ZERO)) {
|
||||
int y = world.getChunk(blockPos).getHeight(Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ());
|
||||
int y = world.getChunk(0, 0, ChunkStatus.FULL).getHeight(Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ());
|
||||
if (y < 1) {
|
||||
y = 65;
|
||||
}
|
||||
|
|
43
src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java
Normal file
43
src/main/java/ru/betterend/mixin/common/EndSpikeMixin.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.levelgen.feature.SpikeFeature.EndSpike;
|
||||
import ru.betterend.util.WorldDataUtil;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(EndSpike.class)
|
||||
public class EndSpikeMixin {
|
||||
@Final
|
||||
@Shadow
|
||||
private int height;
|
||||
|
||||
@Inject(method = "getHeight", at = @At("HEAD"), cancellable = true)
|
||||
private void be_getSpikeHeight(CallbackInfoReturnable<Integer> info) {
|
||||
if (!GeneratorOptions.isDirectSpikeHeight()) {
|
||||
int x = getCenterX();
|
||||
int z = getCenterZ();
|
||||
String pillarID = String.format("%d_%d", x, z);
|
||||
CompoundTag pillar = WorldDataUtil.getCompoundTag("pillars");
|
||||
int minY = pillar.contains(pillarID) ? pillar.getInt(pillarID) : 65;
|
||||
int maxY = minY + height - 54;
|
||||
info.setReturnValue(maxY);
|
||||
}
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public int getCenterX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Shadow
|
||||
public int getCenterZ() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,22 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.*;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeMap;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.item.ElytraItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
@ -10,26 +25,12 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.MoverType;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.item.ElytraItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import ru.betterend.interfaces.MobEffectApplier;
|
||||
import ru.betterend.item.ArmoredElytra;
|
||||
import ru.betterend.item.CrystaliteArmor;
|
||||
import ru.betterend.registry.EndAttributes;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class LivingEntityMixin extends Entity {
|
||||
|
@ -56,8 +57,38 @@ public abstract class LivingEntityMixin extends Entity {
|
|||
@Shadow
|
||||
public abstract boolean isFallFlying();
|
||||
|
||||
@Shadow
|
||||
public abstract AttributeMap getAttributes();
|
||||
|
||||
private Entity lastAttacker;
|
||||
|
||||
@Inject(method = "createLivingAttributes", at = @At("RETURN"), cancellable = true)
|
||||
private static void be_addLivingAttributes(CallbackInfoReturnable<AttributeSupplier.Builder> info) {
|
||||
EndAttributes.addLivingEntityAttributes(info.getReturnValue());
|
||||
}
|
||||
|
||||
@Inject(method = "tickEffects", at = @At("HEAD"))
|
||||
protected void be_applyEffects(CallbackInfo info) {
|
||||
if (!level.isClientSide()) {
|
||||
LivingEntity owner = LivingEntity.class.cast(this);
|
||||
if (CrystaliteArmor.hasFullSet(owner)) {
|
||||
CrystaliteArmor.applySetEffect(owner);
|
||||
}
|
||||
getArmorSlots().forEach(itemStack -> {
|
||||
if (itemStack.getItem() instanceof MobEffectApplier) {
|
||||
((MobEffectApplier) itemStack.getItem()).applyEffect(owner);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "canBeAffected", at = @At("HEAD"), cancellable = true)
|
||||
public void be_canBeAffected(MobEffectInstance mobEffectInstance, CallbackInfoReturnable<Boolean> info) {
|
||||
if (mobEffectInstance.getEffect() == MobEffects.BLINDNESS && getAttributes().getValue(EndAttributes.BLINDNESS_RESISTANCE) > 0.0) {
|
||||
info.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "hurt", at = @At("HEAD"))
|
||||
public void be_hurt(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
|
||||
this.lastAttacker = source.getEntity();
|
||||
|
@ -80,9 +111,8 @@ public abstract class LivingEntityMixin extends Entity {
|
|||
if (isFlying && !onGround && !isPassenger() && !hasEffect(MobEffects.LEVITATION)) {
|
||||
if (ElytraItem.isFlyEnabled(itemStack)) {
|
||||
if ((fallFlyTicks + 1) % 20 == 0) {
|
||||
itemStack.hurtAndBreak(1, LivingEntity.class.cast(this), (livingEntity) -> {
|
||||
livingEntity.broadcastBreakEvent(EquipmentSlot.CHEST);
|
||||
});
|
||||
itemStack.hurtAndBreak(1, LivingEntity.class.cast(this),
|
||||
livingEntity -> livingEntity.broadcastBreakEvent(EquipmentSlot.CHEST));
|
||||
}
|
||||
isFlying = true;
|
||||
} else {
|
||||
|
|
|
@ -4,10 +4,12 @@ import java.io.File;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
|
@ -17,35 +19,47 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.CustomSpawner;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
import net.minecraft.world.level.storage.WritableLevelData;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.registry.EndBiomes;
|
||||
import ru.betterend.registry.EndBlocks;
|
||||
import ru.betterend.util.DataFixerUtil;
|
||||
import ru.betterend.util.WorldDataUtil;
|
||||
import ru.betterend.world.generator.GeneratorOptions;
|
||||
|
||||
@Mixin(ServerLevel.class)
|
||||
public class ServerLevelMixin {
|
||||
private static final int DEV_VERSION = be_getVersionInt("63.63.63");
|
||||
private static final int FIX_VERSION = DEV_VERSION;
|
||||
private static String lastWorld = null;
|
||||
public abstract class ServerLevelMixin extends Level {
|
||||
private static final int BE_DEV_VERSION = be_getVersionInt("63.63.63");
|
||||
private static final int BE_FIX_VERSION = BE_DEV_VERSION;
|
||||
private static String be_lastWorld = null;
|
||||
|
||||
protected ServerLevelMixin(WritableLevelData writableLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l) {
|
||||
super(writableLevelData, resourceKey, dimensionType, supplier, bl, bl2, l);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>*", at = @At("TAIL"))
|
||||
private void be_onServerWorldInit(MinecraftServer server, Executor workerExecutor, LevelStorageSource.LevelStorageAccess session, ServerLevelData properties, ResourceKey<Level> registryKey, DimensionType dimensionType, ChunkProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List<CustomSpawner> list, boolean bl, CallbackInfo info) {
|
||||
if (lastWorld != null && lastWorld.equals(session.getLevelId())) {
|
||||
if (be_lastWorld != null && be_lastWorld.equals(session.getLevelId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastWorld = session.getLevelId();
|
||||
be_lastWorld = session.getLevelId();
|
||||
|
||||
ServerLevel world = ServerLevel.class.cast(this);
|
||||
EndBiomes.onWorldLoad(world.getSeed());
|
||||
File dir = session.getDimensionPath(world.dimension());
|
||||
if (!new File(dir, "level.dat").exists()) {
|
||||
dir = dir.getParentFile();
|
||||
|
@ -53,7 +67,7 @@ public class ServerLevelMixin {
|
|||
File data = new File(dir, "data/betterend_data.nbt");
|
||||
|
||||
ModMetadata meta = FabricLoader.getInstance().getModContainer(BetterEnd.MOD_ID).get().getMetadata();
|
||||
int version = BetterEnd.isDevEnvironment() ? DEV_VERSION : be_getVersionInt(meta.getVersion().toString());
|
||||
int version = BetterEnd.isDevEnvironment() ? BE_DEV_VERSION : be_getVersionInt(meta.getVersion().toString());
|
||||
|
||||
WorldDataUtil.load(data);
|
||||
CompoundTag root = WorldDataUtil.getRootTag();
|
||||
|
@ -61,7 +75,7 @@ public class ServerLevelMixin {
|
|||
GeneratorOptions.setPortalPos(NbtUtils.readBlockPos(root.getCompound("portal")));
|
||||
|
||||
if (dataVersion < version) {
|
||||
if (version < FIX_VERSION) {
|
||||
if (version < BE_FIX_VERSION) {
|
||||
DataFixerUtil.fixData(data.getParentFile());
|
||||
}
|
||||
root.putString("version", be_getVersionString(version));
|
||||
|
@ -79,6 +93,23 @@ public class ServerLevelMixin {
|
|||
}
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "tickChunk",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z"
|
||||
)
|
||||
)
|
||||
private BlockState be_modifyTickState(BlockPos pos, BlockState state) {
|
||||
if (state.is(Blocks.ICE)) {
|
||||
ResourceLocation biome = EndBiomes.getBiomeID(getBiome(pos));
|
||||
if (biome.getNamespace().equals(BetterEnd.MOD_ID)) {
|
||||
state = EndBlocks.EMERALD_ICE.defaultBlockState();
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private static int be_getVersionInt(String version) {
|
||||
if (version.isEmpty()) {
|
||||
return 0;
|
||||
|
|
|
@ -63,6 +63,7 @@ public class SpikeFeatureMixin {
|
|||
minY = world.getChunk(x >> 4, z >> 4).getHeight(Types.WORLD_SURFACE, x & 15, z);
|
||||
}
|
||||
|
||||
GeneratorOptions.setDirectSpikeHeight();
|
||||
int maxY = minY + spike.getHeight() - 64;
|
||||
|
||||
if (GeneratorOptions.replacePillars() && be_radiusInRange(radius)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue