enchantment improvements

This commit is contained in:
lcy0x1
2024-07-18 16:49:42 +08:00
parent 526630b08c
commit 8894999249
19 changed files with 270 additions and 37 deletions

View File

@@ -10,7 +10,7 @@ neogradle.subsystems.parchment.mappingsVersion=2024.06.02
minecraft_version=1.21
minecraft_version_range=[1.21,1.22)
neo_version=21.0.38-beta
neo_version=21.0.93-beta
neo_version_range=[21.0,)
loader_version_range=[2,)
@@ -18,7 +18,7 @@ loader_version_range=[2,)
mod_id=l2core
mod_name=L2Core
mod_license=LGPL-2.1
mod_version=3.0.5-pre13
mod_version=3.0.5-pre25
mod_group_id=dev.xkmc
mod_authors=lcy0x1
mod_description=Core Library mod for all L2 mods
@@ -26,7 +26,7 @@ mod_description=Core Library mod for all L2 mods
jei_minecraft_version = 1.21-neoforge
jei_version = 19.0.0.7
registrate_version = MC1.21-1.4.1
registrate_version = MC1.21-1.4.4+fcb9a93
lljij = false
rootMod = false

View File

@@ -19,7 +19,7 @@ import java.util.function.Supplier;
public class PatchouliHelper {
public static final ProviderType<PatchouliProvider> PATCHOULI = ProviderType.register("patchouli", (p, e) -> new PatchouliProvider(p, e.getLookupProvider(), e.getGenerator()));
public static final ProviderType<PatchouliProvider> PATCHOULI = ProviderType.register("patchouli", PatchouliProvider::new);
public static ItemStack getBook(ResourceLocation book) {
return ItemStack.EMPTY; // TODO ItemModBook.forBook(book);

View File

@@ -5,6 +5,7 @@ import com.tterrag.registrate.providers.RegistrateProvider;
import dev.xkmc.l2core.serial.config.RecordDataProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.PackOutput;
import net.neoforged.fml.LogicalSide;
import java.util.concurrent.CompletableFuture;
@@ -16,8 +17,8 @@ public class PatchouliProvider extends RecordDataProvider implements RegistrateP
private BiConsumer<String, Record> map;
public PatchouliProvider(AbstractRegistrate<?> owner, CompletableFuture<HolderLookup.Provider> pvd, DataGenerator gen) {
super(gen, pvd, "Patchouli Provider");
public PatchouliProvider(AbstractRegistrate<?> owner, PackOutput output, CompletableFuture<HolderLookup.Provider> pvd) {
super(output, pvd, "Patchouli Provider");
this.owner = owner;
}

View File

@@ -1,5 +1,6 @@
package dev.xkmc.l2core.init;
import com.tterrag.registrate.providers.ProviderType;
import dev.xkmc.l2core.base.effects.ClientEffectCap;
import dev.xkmc.l2core.base.menu.base.MenuLayoutConfig;
import dev.xkmc.l2core.capability.conditionals.ConditionalData;

View File

@@ -10,16 +10,19 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.item.enchantment.Enchantment;
public class L2TagGen {
public static <T> ProviderType<RegistrateTagsProvider.IntrinsicImpl<T>> getProvider(ResourceKey<Registry<T>> id, Registry<T> reg) {
String name = id.location().getPath();
return ProviderType.register("tags/" + name,
type -> (p, e) -> new RegistrateTagsProvider.IntrinsicImpl<>(p, type, name,
e.getGenerator().getPackOutput(), id, e.getLookupProvider(),
ench -> reg.getResourceKey(ench).get(),
e.getExistingFileHelper()));
return ProviderType.registerIntrinsicTag("tags/" + name, name, id,
ench -> reg.getResourceKey(ench).orElseThrow());
}
public static <T> ProviderType<RegistrateTagsProvider.Impl<T>> getProvider(ResourceKey<Registry<T>> id) {
String name = id.location().getPath();
return ProviderType.registerDynamicTag("tags/" + name, name, id);
}
public static final ProviderType<RegistrateTagsProvider.IntrinsicImpl<MobEffect>> EFF_TAGS =
@@ -28,6 +31,9 @@ public class L2TagGen {
public static final ProviderType<RegistrateTagsProvider.IntrinsicImpl<Attribute>> ATTR_TAGS =
getProvider(Registries.ATTRIBUTE, BuiltInRegistries.ATTRIBUTE);
public static final ProviderType<RegistrateTagsProvider.Impl<Enchantment>> ENCH_TAGS =
getProvider(Registries.ENCHANTMENT);
public static final TagKey<MobEffect> TRACKED_EFFECTS = effectTag(ResourceLocation.fromNamespaceAndPath(L2Core.MODID, "tracked_effects"));
public static void onEffectTagGen(RegistrateTagsProvider.IntrinsicImpl<MobEffect> pvd) {

View File

@@ -106,14 +106,14 @@ public interface EECVal<T> extends Val<DataComponentType<List<ConditionalEffect<
}
interface Special<T> extends Val<DataComponentType<T>> {
interface Special<T> extends Val<DataComponentType<List<T>>> {
record Impl<T>(
DeferredHolder<DataComponentType<?>, DataComponentType<T>> val
DeferredHolder<DataComponentType<?>, DataComponentType<List<T>>> val
) implements Special<T> {
@Override
public DataComponentType<T> get() {
public DataComponentType<List<T>> get() {
return val.get();
}

View File

@@ -0,0 +1,7 @@
package dev.xkmc.l2core.init.reg.ench;
import net.minecraft.core.Holder;
import net.minecraft.world.item.enchantment.Enchantment;
public record EnchHolder<T>(Holder<Enchantment> holder, T val, int lv) {
}

View File

@@ -1,17 +1,18 @@
package dev.xkmc.l2core.init.reg.ench;
import com.mojang.serialization.Codec;
import com.tterrag.registrate.providers.ProviderType;
import com.tterrag.registrate.providers.RegistrateTagsProvider;
import cpw.mods.util.Lazy;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.init.L2TagGen;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
import dev.xkmc.l2core.init.reg.simple.Reg;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.tags.TagsProvider;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Unit;
import net.minecraft.world.item.enchantment.ConditionalEffect;
import net.minecraft.world.item.enchantment.Enchantment;
@@ -24,8 +25,10 @@ import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
@SuppressWarnings("unused")
public class EnchReg {
public static EnchReg of(Reg reg, L2Registrate pvd) {
@@ -33,13 +36,19 @@ public class EnchReg {
}
private final DeferredRegister<DataComponentType<?>> reg;
private final DeferredRegister<LegacyEnchantment> legacy;
private final L2Registrate pvd;
private final List<EnchVal.Impl> list = new ArrayList<>();
private EnchReg(Reg reg, L2Registrate pvd) {
this.reg = reg.make(BuiltInRegistries.ENCHANTMENT_EFFECT_COMPONENT_TYPE);
this.legacy = reg.make(L2LibReg.ENCH.get());
this.pvd = pvd;
pvd.addDataGenerator(L2TagGen.ENCH_TAGS, this::doTagGen);
var init = pvd.getDataGenInitializer();
init.add(Registries.ENCHANTMENT, this::build);
init.addDependency(ProviderType.DYNAMIC, L2TagGen.ENCH_TAGS);
}
private <T> DeferredHolder<DataComponentType<?>, DataComponentType<T>> reg(String id, Codec<T> codec) {
@@ -51,7 +60,7 @@ public class EnchReg {
}
public <T> EECVal.Special<T> special(String id, Codec<T> codec) {
return new EECVal.Special.Impl<>(reg(id, codec));
return new EECVal.Special.Impl<>(reg(id, codec.listOf()));
}
public <T> EECVal<T> eff(String id, Codec<T> codec, LootContextParamSet loot) {
@@ -65,33 +74,42 @@ public class EnchReg {
).listOf()));
}
public EnchVal ench(String id, String name, String desc, UnaryOperator<EnchVal.Builder> cons) {
private <T extends EnchVal.Impl> T enchBase(String id, String name, String desc, Function<ResourceKey<Enchantment>, T> factory) {
var key = ResourceKey.create(Registries.ENCHANTMENT, pvd.loc(id));
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id, name);
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id + ".desc", desc);
var ans = new EnchVal.Simple(key, Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location()))));
var ans = factory.apply(key);
list.add(ans);
return ans;
}
public EnchVal ench(String id, String name, String desc, UnaryOperator<EnchVal.Builder> cons) {
return enchBase(id, name, desc, key -> new EnchVal.Simple(key,
Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location())))));
}
public EnchVal.Flag enchFlag(String id, String name, String desc, UnaryOperator<EnchVal.Builder> cons) {
var key = ResourceKey.create(Registries.ENCHANTMENT, pvd.loc(id));
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id, name);
pvd.addRawLang("enchantment." + pvd.getModid() + "." + id + ".desc", desc);
var unit = unit(id);
var ans = new EnchVal.FlagImpl(unit, key, Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location()).effect(e -> e.withEffect(unit.get())))));
list.add(ans);
return ans;
return enchBase(id, name, desc, key -> new EnchVal.FlagImpl(unit, key,
Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location()).effect(e ->
e.withEffect(unit.get()))))));
}
public EnchVal enchLegacy(String id, String name, String desc, UnaryOperator<EnchVal.Builder> cons, Supplier<LegacyEnchantment> factory) {
var unit = legacy.register(id, factory);
return enchBase(id, name, desc, key -> new EnchVal.Simple(key,
Lazy.of(() -> cons.apply(new EnchVal.Builder(key.location()).effect(e ->
e.withSpecialEffect(L2LibReg.LEGACY.get(), List.of(unit.get())))))));
}
public void build(BootstrapContext<Enchantment> ctx) {
for (var e : list) ctx.register(e.id(), e.builder().get().build(ctx, e.id().location()));
}
public void doTagGen(Function<TagKey<Enchantment>, TagsProvider.TagAppender<Enchantment>> func, HolderLookup.Provider pvd) {
public void doTagGen(RegistrateTagsProvider<Enchantment> pvd) {
for (var e : list) {
for (var t : e.builder().get().tags) {
func.apply(t).add(e.id());
pvd.addTag(t).add(e.id());
}
}
}

View File

@@ -1,6 +1,69 @@
package dev.xkmc.l2core.init.reg.ench;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2serial.util.Wrappers;
import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.neoforged.neoforge.common.CommonHooks;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class LegacyEnchantment {
@Nullable
public static <T> T firstOf(Holder<Enchantment> ench, Class<T> cls) {
for (var e : ench.value().getEffects(L2LibReg.LEGACY.get())) {
if (cls.isInstance(e)) {
return Wrappers.cast(e);
}
}
return null;
}
public static <T> Optional<T> findFirst(Holder<Enchantment> ench, Class<T> cls) {
return Optional.ofNullable(firstOf(ench, cls));
}
public static <T> List<EnchHolder<T>> findAll(ItemStack stack, Class<T> cls, boolean intrinsic) {
var reg = CommonHooks.resolveLookup(Registries.ENCHANTMENT);
if (reg == null) return List.of();
List<EnchHolder<T>> ans = new ArrayList<>();
ItemEnchantments enchs = intrinsic ?
stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY) :
stack.getAllEnchantments(reg);
for (var e : enchs.entrySet()) {
var t = firstOf(e.getKey(), cls);
if (t != null) ans.add(new EnchHolder<>(e.getKey(), t, e.getIntValue()));
}
return ans;
}
public static <T> Map<T, Integer> accumulateOnEntity(LivingEntity le, Class<T> cls, boolean intrinsic) {
LinkedHashMap<T, Integer> map = new LinkedHashMap<>();
for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack stack = le.getItemBySlot(slot);
if (stack.isEmpty() || !stack.isEnchanted()) continue;
var list = findAll(stack, cls, intrinsic);
for (var e : list) {
if (e.holder().value().matchingSlot(slot)) {
map.compute(e.val(), (k, v) -> (v == null ? 0 : v) + e.lv());
}
}
}
return map;
}
public List<Component> descFull(int lv, String key, boolean alt, boolean book) {
return List.of(Component.translatable(key).withStyle(ChatFormatting.DARK_GRAY));
}
}

View File

@@ -6,13 +6,19 @@ import com.tterrag.registrate.builders.BuilderCallback;
import com.tterrag.registrate.builders.NoConfigBuilder;
import com.tterrag.registrate.providers.RegistrateLangProvider;
import com.tterrag.registrate.util.OneTimeEventReceiver;
import com.tterrag.registrate.util.RegistrateDistExecutor;
import com.tterrag.registrate.util.entry.RegistryEntry;
import com.tterrag.registrate.util.nullness.NonNullSupplier;
import com.tterrag.registrate.util.nullness.NonnullType;
import dev.xkmc.l2core.init.L2Core;
import dev.xkmc.l2core.init.reg.simple.Val;
import dev.xkmc.l2serial.serialization.custom_handler.CodecHandler;
import dev.xkmc.l2serial.util.Wrappers;
import net.minecraft.client.particle.ParticleEngine;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.core.Registry;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
@@ -25,7 +31,9 @@ import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.Potion;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
import net.neoforged.neoforge.data.loading.DatagenModLoader;
import net.neoforged.neoforge.registries.NewRegistryEvent;
import net.neoforged.neoforge.registries.RegistryBuilder;
@@ -81,6 +89,16 @@ public class L2Registrate extends AbstractRegistrate<L2Registrate> {
return new SimpleEntry<>(ans);
}
public <T extends ParticleOptions, R extends ParticleType<T>> Val<R>
particle(String name, NonNullSupplier<R> sup, NonNullSupplier<? extends ParticleSupplier<T>> pvd) {
RegistryEntry<ParticleType<?>, R> ans = entry(name, (cb) -> new NoConfigBuilder<>(this, this, name, cb,
Registries.PARTICLE_TYPE, sup)).register();
RegistrateDistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
OneTimeEventReceiver.addModListener(this, RegisterParticleProvidersEvent.class,
event -> pvd.get().register(event, ans.get())));
return new Val.Registrate<>(ans);
}
@SuppressWarnings({"unsafe"})
public <E> RegistryInstance<E> newRegistry(String id, Class<?> cls, Consumer<RegistryBuilder<E>> cons) {
ResourceKey<Registry<E>> key = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(getModid(), id));
@@ -215,4 +233,22 @@ public class L2Registrate extends AbstractRegistrate<L2Registrate> {
}
public interface ParticleSupplier<T extends ParticleOptions> {
static <T extends ParticleOptions> ParticleSupplier<T> provider(ParticleProvider<T> pvd) {
return (event, type) -> event.registerSpecial(type, pvd);
}
static <T extends ParticleOptions> ParticleSupplier<T> sprite(ParticleProvider.Sprite<T> pvd) {
return (event, type) -> event.registerSprite(type, pvd);
}
static <T extends ParticleOptions> ParticleSupplier<T> spriteSet(ParticleEngine.SpriteParticleRegistration<T> pvd) {
return (event, type) -> event.registerSpriteSet(type, pvd);
}
void register(RegisterParticleProvidersEvent event, ParticleType<T> type);
}
}

View File

@@ -11,6 +11,7 @@ import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.util.Unit;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
@@ -34,6 +35,10 @@ public record DCReg(DeferredRegister<DataComponentType<?>> reg) {
return reg(id, cdc, cdc.toNetwork(), cache);
}
public DCVal<Unit> unit(String id) {
return reg(id, Unit.CODEC, StreamCodec.unit(Unit.INSTANCE), false);
}
public DCVal<Integer> intVal(String id) {
return reg(id, Codec.INT, ByteBufCodecs.INT, false);
}

View File

@@ -19,15 +19,15 @@ public record SR<T>(DeferredRegister<T> reg) {
return new SR<>(parent.make(reg));
}
public <H extends T> Val<H> reg(String id, Supplier<H> sup) {
public <H extends T> ValImpl<T, H> reg(String id, Supplier<H> sup) {
return new ValImpl<>(reg.register(id, sup));
}
public <H extends T> Val<H> reg(String id, Function<ResourceLocation, H> sup) {
public <H extends T> ValImpl<T, H> reg(String id, Function<ResourceLocation, H> sup) {
return new ValImpl<>(reg.register(id, sup));
}
private record ValImpl<R, T extends R>(DeferredHolder<R, T> val) implements Val<T> {
public record ValImpl<R, T extends R>(DeferredHolder<R, T> val) implements Val<T> {
@Override
public T get() {

View File

@@ -1,9 +1,20 @@
package dev.xkmc.l2core.init.reg.simple;
import com.tterrag.registrate.util.entry.RegistryEntry;
import java.util.function.Supplier;
public interface Val<T> extends Supplier<T> {
T get();
record Registrate<H, T extends H>(RegistryEntry<H, T> entry) implements Val<T> {
@Override
public T get() {
return entry.get();
}
}
}

View File

@@ -0,0 +1,16 @@
package dev.xkmc.l2core.mixin;
import net.neoforged.fml.config.ConfigTracker;
import net.neoforged.fml.config.ModConfig;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.concurrent.ConcurrentHashMap;
@Mixin(ConfigTracker.class)
public interface ConfigTrackerAccessor {
@Accessor
public ConcurrentHashMap<String, ModConfig> getFileMap();
}

View File

@@ -6,6 +6,7 @@ import net.minecraft.core.HolderLookup;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider;
import net.minecraft.data.PackOutput;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -16,13 +17,13 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
public abstract class RecordDataProvider implements DataProvider {
private final DataGenerator generator;
private final PackOutput output;
private final CompletableFuture<HolderLookup.Provider> pvd;
private final String name;
private final Map<String, Record> map = new HashMap<>();
public RecordDataProvider(DataGenerator generator, CompletableFuture<HolderLookup.Provider> pvd, String name) {
this.generator = generator;
public RecordDataProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> pvd, String name) {
this.output = output;
this.pvd = pvd;
this.name = name;
}
@@ -31,7 +32,7 @@ public abstract class RecordDataProvider implements DataProvider {
public CompletableFuture<?> run(CachedOutput cache) {
return pvd.thenCompose(pvd -> {
Path folder = this.generator.getPackOutput().getOutputFolder();
Path folder = output.getOutputFolder();
this.add(this.map::put);
List<CompletableFuture<?>> list = new ArrayList<>();
this.map.forEach((k, v) -> {

View File

@@ -1,6 +1,8 @@
package dev.xkmc.l2core.serial.configval;
import dev.xkmc.l2core.mixin.ConfigTrackerAccessor;
import net.neoforged.fml.config.ConfigTracker;
import net.neoforged.neoforge.common.ModConfigSpec;
import java.util.List;
import java.util.Optional;
@@ -8,8 +10,11 @@ import java.util.Optional;
public class AbstractConfigParser {
public static Optional<Object> parse(String path, List<String> line) {
return Optional.ofNullable(ConfigTracker.INSTANCE.fileMap().get(path))
.map(file -> file.getConfigData().get(line));
var file = ((ConfigTrackerAccessor) ConfigTracker.INSTANCE).getFileMap().get(path);
if (file == null) return Optional.empty();
var spec = file.getSpec();
if (!(spec instanceof ModConfigSpec modSpec) || !modSpec.isLoaded()) return Optional.empty();
return Optional.ofNullable(modSpec.getValues().get(line));
}
}

View File

@@ -1,7 +1,11 @@
package dev.xkmc.l2core.serial.ingredients;
import dev.xkmc.l2core.init.L2LibReg;
import dev.xkmc.l2core.util.DataGenOnly;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.EnchantedBookItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
@@ -20,6 +24,12 @@ public record EnchantmentIngredient(Holder<Enchantment> enchantment, int minLeve
return new EnchantmentIngredient(ench, min).toVanilla();
}
@DataGenOnly
public static Ingredient of(HolderLookup.Provider pvd, ResourceKey<Enchantment> ench, int min) {
var holder = pvd.lookup(Registries.ENCHANTMENT).orElseThrow().getOrThrow(ench);
return of(holder, min);
}
@Override
public Stream<ItemStack> getItems() {
var ench = enchantment.value();

View File

@@ -0,0 +1,52 @@
package dev.xkmc.l2core.util;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.portal.DimensionTransition;
import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.event.entity.EntityTeleportEvent;
import java.util.Set;
public class TeleportTool {
public static void teleportHome(ServerLevel world, ServerPlayer player) {
DimensionTransition respawn = player.findRespawnPositionAndUseSpawnBlock(true, DimensionTransition.DO_NOTHING);
if (world == respawn.newLevel()) {
player.moveTo(respawn.pos(), respawn.yRot(), respawn.xRot());
} else {
var pos = respawn.pos();
performTeleport(player, respawn.newLevel(), pos.x, pos.y, pos.z, respawn.yRot(), respawn.xRot());
}
}
public static void performTeleport(Entity e, ServerLevel level, double x, double y, double z, float yaw, float pitch) {
EntityTeleportEvent.TeleportCommand event = EventHooks.onEntityTeleportCommand(e, x, y, z);
if (event.isCanceled()) return;
x = event.getTargetX();
y = event.getTargetY();
z = event.getTargetZ();
BlockPos blockpos = BlockPos.containing(x, y, z);
if (!Level.isInSpawnableBounds(blockpos)) return;
float yr = Mth.wrapDegrees(yaw);
float xr = Mth.wrapDegrees(pitch);
if (e.teleportTo(level, x, y, z, Set.of(), yr, xr)) {
if (e instanceof LivingEntity le) {
if (!le.isFallFlying()) {
e.setDeltaMovement(e.getDeltaMovement().multiply(1.0, 0.0, 1.0));
e.setOnGround(true);
}
}
if (e instanceof PathfinderMob mob) {
mob.getNavigation().stop();
}
}
}
}

View File

@@ -4,6 +4,7 @@
"package": "dev.xkmc.l2core.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"ConfigTrackerAccessor"
],
"client": [
],