Port mod from Fabric

This commit is contained in:
Octol1ttle 2024-01-16 22:27:14 +05:00
parent 76d4b44153
commit ae6d9095e3
Signed by: Octol1ttle
GPG key ID: B77C34313AEE1FFF
26 changed files with 936 additions and 9 deletions

View file

@ -1,6 +1,6 @@
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.3-SNAPSHOT" apply false
id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false
}
architectury {

View file

@ -12,6 +12,8 @@ dependencies {
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
// Remove the next line if you don't want to depend on the API
modApi "dev.architectury:architectury:${rootProject.architectury_version}"
compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.3"))
}
publishing {

View file

@ -1,7 +1,16 @@
package ru.octol1ttle.knockdowns.common;
import ru.octol1ttle.knockdowns.common.events.KnockdownsClientEvents;
import ru.octol1ttle.knockdowns.common.events.KnockdownsEvents;
import ru.octol1ttle.knockdowns.common.registries.KnockdownsSoundEvents;
public class KnockdownsCommon {
public static final String MOD_ID = "knockdowns";
public static void init() {
KnockdownsSoundEvents.register();
KnockdownsNetwork.registerPackets();
KnockdownsClientEvents.registerCallbacks();
KnockdownsEvents.registerCallbacks();
}
}

View file

@ -0,0 +1,90 @@
package ru.octol1ttle.knockdowns.common;
import dev.architectury.networking.NetworkChannel;
import dev.architectury.networking.NetworkManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.packet.Packet;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.EntityTrackingListener;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
import net.minecraft.util.Identifier;
import ru.octol1ttle.knockdowns.common.packets.KnockedDownStatusPacket;
import ru.octol1ttle.knockdowns.common.packets.PlayKnockedDownSoundS2CPacket;
import ru.octol1ttle.knockdowns.common.packets.ReviveStatusPacket;
public class KnockdownsNetwork {
private static final NetworkChannel CHANNEL = NetworkChannel.create(new Identifier(KnockdownsCommon.MOD_ID, "main"));
public static void registerPackets() {
CHANNEL.register(KnockedDownStatusPacket.SendS2C.class, KnockedDownStatusPacket.SendS2C::encode, KnockedDownStatusPacket.SendS2C::new, KnockedDownStatusPacket.SendS2C::apply);
CHANNEL.register(KnockedDownStatusPacket.RequestC2S.class, KnockedDownStatusPacket.RequestC2S::encode, KnockedDownStatusPacket.RequestC2S::new, KnockedDownStatusPacket.RequestC2S::apply);
CHANNEL.register(PlayKnockedDownSoundS2CPacket.class, PlayKnockedDownSoundS2CPacket::encode, PlayKnockedDownSoundS2CPacket::new, PlayKnockedDownSoundS2CPacket::apply);
CHANNEL.register(ReviveStatusPacket.SendS2C.class, ReviveStatusPacket.SendS2C::encode, ReviveStatusPacket.SendS2C::new, ReviveStatusPacket.SendS2C::apply);
CHANNEL.register(ReviveStatusPacket.SendC2S.class, ReviveStatusPacket.SendC2S::encode, ReviveStatusPacket.SendC2S::new, ReviveStatusPacket.SendC2S::apply);
CHANNEL.register(ReviveStatusPacket.RequestC2S.class, ReviveStatusPacket.RequestC2S::encode, ReviveStatusPacket.RequestC2S::new, ReviveStatusPacket.RequestC2S::apply);
CHANNEL.register(ReviveStatusPacket.RevivedC2S.class, ReviveStatusPacket.RevivedC2S::encode, ReviveStatusPacket.RevivedC2S::new, ReviveStatusPacket.RevivedC2S::apply);
}
public static <T> void sendToServer(T message) {
if (CHANNEL.canServerReceive(message.getClass())) {
CHANNEL.sendToServer(message);
}
}
public static <T> void sendToPlayer(PlayerEntity player, T message) {
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
Class<?> messageClass = message.getClass();
sendToPlayer(player, packet, messageClass);
}
public static void sendToPlayer(PlayerEntity player, Packet<?> packet, Class<?> messageClass) {
if (!(player instanceof ServerPlayerEntity serverPlayer)) {
throw new IllegalArgumentException("Cannot send to client players");
}
if (CHANNEL.canPlayerReceive(serverPlayer, messageClass)) {
serverPlayer.networkHandler.sendPacket(packet);
}
}
// TODO: PR to Architectury API
public static <T> void sendToListeners(Entity entity, T message) {
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
Class<?> messageClass = message.getClass();
sendToListeners(entity, packet, messageClass);
}
private static void sendToListeners(Entity entity, Packet<?> packet, Class<?> messageClass) {
ServerChunkManager chunkManager = (ServerChunkManager) entity.getWorld().getChunkManager();
ThreadedAnvilChunkStorage.EntityTracker entityTracker = chunkManager.threadedAnvilChunkStorage.entityTrackers.get(entity.getId());
for (EntityTrackingListener listener : entityTracker.listeners) {
sendToPlayer(listener.getPlayer(), packet, messageClass);
}
}
public static <T> void sendToListenersAndSelf(PlayerEntity player, T message) {
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
Class<?> messageClass = message.getClass();
sendToPlayer(player, packet, messageClass);
sendToListeners(player, packet, messageClass);
}
public static <T> void sendToWorld(ServerWorld world, T message) {
Packet<?> packet = CHANNEL.toPacket(NetworkManager.Side.S2C, message);
Class<?> messageClass = message.getClass();
sendToWorld(world, packet, messageClass);
}
private static void sendToWorld(ServerWorld world, Packet<?> packet, Class<?> messageClass) {
for (ServerPlayerEntity player : world.getPlayers()) {
sendToPlayer(player, packet, messageClass);
}
}
}

View file

@ -0,0 +1,15 @@
package ru.octol1ttle.knockdowns.common.api;
import java.util.UUID;
public interface IKnockableDown {
boolean knockdowns$isKnockedDown();
void knockdowns$setKnockedDown(boolean knockedDown);
boolean knockdowns$isBeingRevived();
void knockdowns$setBeingRevived(boolean beingRevived);
UUID knockdowns$getUuid();
}

View file

@ -0,0 +1,105 @@
package ru.octol1ttle.knockdowns.common.events;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.client.ClientGuiEvent;
import dev.architectury.event.events.client.ClientPlayerEvent;
import dev.architectury.event.events.client.ClientTickEvent;
import dev.architectury.event.events.common.InteractionEvent;
import java.util.UUID;
import net.minecraft.SharedConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import ru.octol1ttle.knockdowns.common.KnockdownsNetwork;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
import ru.octol1ttle.knockdowns.common.packets.KnockedDownStatusPacket;
import ru.octol1ttle.knockdowns.common.packets.ReviveStatusPacket;
public class KnockdownsClientEvents {
private static final int REVIVAL_WAIT_TIME = 10 * SharedConstants.TICKS_PER_SECOND;
private static IKnockableDown reviving = null;
private static int revivalTimer = -1;
public static void registerCallbacks() {
registerOnEntityLoad();
registerOnEntityUse();
registerOnWorldTick();
registerOnHudRender();
}
private static void registerOnEntityLoad() {
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> {
UUID playerUuid = player.getUuid();
KnockdownsNetwork.sendToServer(new KnockedDownStatusPacket.RequestC2S(playerUuid));
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.RequestC2S(playerUuid));
});
}
private static void registerOnEntityUse() {
InteractionEvent.INTERACT_ENTITY.register((player, entity, hand) -> {
if (!(entity instanceof IKnockableDown knockableEntity) || !knockableEntity.knockdowns$isKnockedDown()
|| knockableEntity.knockdowns$isBeingRevived()) {
return EventResult.pass();
}
IKnockableDown self = (IKnockableDown) player;
if (self.knockdowns$isKnockedDown()) {
return EventResult.interruptFalse();
}
knockableEntity.knockdowns$setBeingRevived(true);
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.SendC2S(entity.getUuid(), true));
reviving = knockableEntity;
revivalTimer = REVIVAL_WAIT_TIME;
return EventResult.interruptTrue();
});
}
private static void registerOnWorldTick() {
ClientTickEvent.ClientLevel.CLIENT_LEVEL_POST.register(world -> {
boolean revived = false;
revivalTimer--;
if (revivalTimer <= 0) {
revivalTimer = -1;
revived = true;
}
if (reviving == null) {
return;
}
HitResult crosshairTarget = MinecraftClient.getInstance().crosshairTarget;
if (revived || crosshairTarget == null || crosshairTarget.getType() != HitResult.Type.ENTITY
|| !((EntityHitResult) crosshairTarget).getEntity().getUuid().equals(reviving.knockdowns$getUuid())) {
reviving.knockdowns$setBeingRevived(false);
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.SendC2S(reviving.knockdowns$getUuid(), false));
if (revived) {
reviving.knockdowns$setKnockedDown(false);
KnockdownsNetwork.sendToServer(new ReviveStatusPacket.RevivedC2S(reviving.knockdowns$getUuid()));
}
reviving = null;
revivalTimer = -1;
}
});
}
private static void registerOnHudRender() {
ClientGuiEvent.RENDER_HUD.register((drawContext, tickDelta) -> {
if (revivalTimer == -1) {
return;
}
TextRenderer renderer = MinecraftClient.getInstance().textRenderer;
String text = String.format("%.1f", revivalTimer / (float) SharedConstants.TICKS_PER_SECOND);
int x = (drawContext.getScaledWindowWidth() - renderer.getWidth(text)) / 2;
drawContext.drawTextWithShadow(renderer, text, x, drawContext.getScaledWindowHeight() / 2 + 15, 0xFFFFFF);
});
}
}

View file

@ -0,0 +1,87 @@
package ru.octol1ttle.knockdowns.common.events;
import dev.architectury.event.CompoundEventResult;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.common.EntityEvent;
import dev.architectury.event.events.common.InteractionEvent;
import dev.architectury.event.events.common.PlayerEvent;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableTextContent;
import net.minecraft.util.Hand;
import net.minecraft.world.GameRules;
import ru.octol1ttle.knockdowns.common.KnockdownsNetwork;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
import ru.octol1ttle.knockdowns.common.packets.KnockedDownStatusPacket;
import ru.octol1ttle.knockdowns.common.packets.PlayKnockedDownSoundS2CPacket;
public class KnockdownsEvents {
public static void registerCallbacks() {
registerOnLivingDeath();
registerOnPlayerInteractions();
}
private static void registerOnLivingDeath() {
EntityEvent.LIVING_DEATH.register((entity, source) -> {
if (!(entity instanceof IKnockableDown knockableDown) || knockableDown.knockdowns$isKnockedDown()) {
return EventResult.pass();
}
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) entity;
// TODO: timer
if (!serverPlayer.getWorld().getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) {
serverPlayer.getInventory().dropAll();
}
entity.setHealth(1.0f);
entity.setInvulnerable(true);
entity.setGlowing(true);
entity.setAir(entity.getMaxAir());
entity.extinguish();
entity.setFrozenTicks(0);
entity.setOnFire(false);
entity.clearStatusEffects();
knockableDown.knockdowns$setKnockedDown(true);
KnockdownsNetwork.sendToListenersAndSelf(serverPlayer, new KnockedDownStatusPacket.SendS2C(serverPlayer.getUuid(), true));
KnockdownsNetwork.sendToWorld(serverPlayer.getServerWorld(), new PlayKnockedDownSoundS2CPacket(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ()));
TranslatableTextContent content = (TranslatableTextContent) entity.getDamageTracker().getDeathMessage().getContent();
Text replaced = Text.translatableWithFallback(content.getKey().replace("death.", "knockdown."), content.getKey(), content.getArgs());
MinecraftServer server = serverPlayer.getServer();
if (server != null) {
server.getPlayerManager().broadcast(replaced, false);
}
return EventResult.interruptFalse();
});
}
private static void registerOnPlayerInteractions() {
InteractionEvent.LEFT_CLICK_BLOCK.register((player, hand, pos, direction) -> {
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
return EventResult.interruptFalse();
}
return EventResult.pass();
});
PlayerEvent.ATTACK_ENTITY.register((player, world, hand, entity, hitResult) -> {
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
return EventResult.interruptFalse();
}
return EventResult.pass();
});
InteractionEvent.RIGHT_CLICK_ITEM.register((player, hand) -> {
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
return CompoundEventResult.interruptFalse(hand == Hand.MAIN_HAND ? player.getMainHandStack() : player.getOffHandStack());
}
return CompoundEventResult.pass();
});
InteractionEvent.RIGHT_CLICK_BLOCK.register((player, hand, pos, direction) -> {
if (player instanceof IKnockableDown && ((IKnockableDown) player).knockdowns$isKnockedDown()) {
return EventResult.interruptFalse();
}
return EventResult.pass();
});
}
}

View file

@ -0,0 +1,71 @@
package ru.octol1ttle.knockdowns.common.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import java.util.UUID;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin implements IKnockableDown {
@Unique
private boolean knockedDown;
@Unique
private boolean beingRevived;
@ModifyExpressionValue(method = "updatePose", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;isSwimming()Z"))
private boolean enterSwimmingIfKnockedDown(boolean original) {
PlayerEntity player = (PlayerEntity)(Object)this;
if (!(player instanceof IKnockableDown knockableDown)) {
throw new IllegalStateException();
}
return original || knockableDown.knockdowns$isKnockedDown();
}
@ModifyReturnValue(method = "canFoodHeal", at = @At("RETURN"))
private boolean dontHealIfKnockedDown(boolean original) {
return original && !this.knockdowns$isKnockedDown();
}
@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
public void readKnockedDownFromNbt(NbtCompound nbt, CallbackInfo ci) {
this.knockedDown = nbt.getBoolean("KnockedDown");
}
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
public void writeKnockedDownToNbt(NbtCompound nbt, CallbackInfo ci) {
nbt.putBoolean("KnockedDown", this.knockedDown);
}
@Override
public boolean knockdowns$isKnockedDown() {
return knockedDown;
}
@Override
public void knockdowns$setKnockedDown(boolean knockedDown) {
this.knockedDown = knockedDown;
}
@Override
public boolean knockdowns$isBeingRevived() {
return beingRevived;
}
@Override
public void knockdowns$setBeingRevived(boolean beingRevived) {
this.beingRevived = beingRevived;
}
@Override
public UUID knockdowns$getUuid() {
return ((PlayerEntity)(Object)this).getUuid();
}
}

View file

@ -0,0 +1,16 @@
package ru.octol1ttle.knockdowns.common.mixin.client;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import net.minecraft.client.network.ClientPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
@Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin {
@ModifyReturnValue(method = "shouldSlowDown", at = @At("RETURN"))
private boolean shouldSlowDown(boolean original) {
IKnockableDown self = (IKnockableDown) this;
return original || self.knockdowns$isKnockedDown();
}
}

View file

@ -0,0 +1,19 @@
package ru.octol1ttle.knockdowns.common.packets;
import dev.architectury.networking.NetworkManager;
import java.util.function.Supplier;
import net.minecraft.network.PacketByteBuf;
public abstract class KnockdownsPacket {
public KnockdownsPacket(PacketByteBuf buf) {
// Decode data into a message
}
public KnockdownsPacket(/* args here */) {
// Message creation
}
public abstract void encode(PacketByteBuf buf);
public abstract void apply(Supplier<NetworkManager.PacketContext> contextSupplier);
}

View file

@ -0,0 +1,69 @@
package ru.octol1ttle.knockdowns.common.packets;
import dev.architectury.networking.NetworkManager;
import java.util.UUID;
import java.util.function.Supplier;
import net.minecraft.network.PacketByteBuf;
import ru.octol1ttle.knockdowns.common.KnockdownsNetwork;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
public class KnockedDownStatusPacket {
public static class SendS2C extends KnockdownsPacket {
private final UUID playerUuid;
private final boolean knockedDown;
public SendS2C(PacketByteBuf buf) {
this(buf.readUuid(), buf.readBoolean());
}
public SendS2C(UUID playerUuid, boolean knockedDown) {
this.playerUuid = playerUuid;
this.knockedDown = knockedDown;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeUuid(this.playerUuid);
buf.writeBoolean(this.knockedDown);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> {
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
if (knockableDown != null) {
knockableDown.knockdowns$setKnockedDown(this.knockedDown);
}
});
}
}
public static class RequestC2S extends KnockdownsPacket {
private final UUID playerUuid;
public RequestC2S(PacketByteBuf buf) {
this(buf.readUuid());
}
public RequestC2S(UUID playerUuid) {
this.playerUuid = playerUuid;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeUuid(this.playerUuid);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> {
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
if (knockableDown != null) {
KnockdownsNetwork.sendToPlayer(context.getPlayer(), new SendS2C(this.playerUuid, knockableDown.knockdowns$isKnockedDown()));
}
});
}
}
}

View file

@ -0,0 +1,40 @@
package ru.octol1ttle.knockdowns.common.packets;
import dev.architectury.networking.NetworkManager;
import java.util.function.Supplier;
import net.minecraft.client.MinecraftClient;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Vec3d;
import ru.octol1ttle.knockdowns.common.registries.KnockdownsSoundEvents;
import ru.octol1ttle.knockdowns.common.registries.KnockedDownSoundInstance;
public class PlayKnockedDownSoundS2CPacket extends KnockdownsPacket {
private final double x;
private final double y;
private final double z;
public PlayKnockedDownSoundS2CPacket(PacketByteBuf buf) {
this(buf.readDouble(), buf.readDouble(), buf.readDouble());
}
public PlayKnockedDownSoundS2CPacket(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeDouble(this.x);
buf.writeDouble(this.y);
buf.writeDouble(this.z);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> MinecraftClient.getInstance().getSoundManager().play(
new KnockedDownSoundInstance(KnockdownsSoundEvents.KNOCKED_DOWN.get(), new Vec3d(this.x, this.y, this.z))
));
}
}

View file

@ -0,0 +1,138 @@
package ru.octol1ttle.knockdowns.common.packets;
import dev.architectury.networking.NetworkManager;
import java.util.UUID;
import java.util.function.Supplier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf;
import ru.octol1ttle.knockdowns.common.KnockdownsNetwork;
import ru.octol1ttle.knockdowns.common.api.IKnockableDown;
public class ReviveStatusPacket {
public static class SendS2C extends KnockdownsPacket {
private final UUID playerUuid;
private final boolean beingRevived;
public SendS2C(PacketByteBuf buf) {
this(buf.readUuid(), buf.readBoolean());
}
public SendS2C(UUID playerUuid, boolean beingRevived) {
this.playerUuid = playerUuid;
this.beingRevived = beingRevived;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeUuid(this.playerUuid);
buf.writeBoolean(this.beingRevived);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> {
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
if (knockableDown != null) {
knockableDown.knockdowns$setBeingRevived(this.beingRevived);
}
});
}
}
public static class SendC2S extends KnockdownsPacket {
private final UUID playerUuid;
private final boolean beingRevived;
public SendC2S(PacketByteBuf buf) {
this(buf.readUuid(), buf.readBoolean());
}
public SendC2S(UUID playerUuid, boolean beingRevived) {
this.playerUuid = playerUuid;
this.beingRevived = beingRevived;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeUuid(this.playerUuid);
buf.writeBoolean(this.beingRevived);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> {
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
if (knockableDown != null) {
knockableDown.knockdowns$setBeingRevived(this.beingRevived);
KnockdownsNetwork.sendToListenersAndSelf(context.getPlayer(), new ReviveStatusPacket.SendS2C(this.playerUuid, this.beingRevived));
}
});
}
}
public static class RequestC2S extends KnockdownsPacket {
private final UUID playerUuid;
public RequestC2S(PacketByteBuf buf) {
this(buf.readUuid());
}
public RequestC2S(UUID playerUuid) {
this.playerUuid = playerUuid;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeUuid(this.playerUuid);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> {
IKnockableDown knockableDown = (IKnockableDown) context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
if (knockableDown != null) {
KnockdownsNetwork.sendToPlayer(context.getPlayer(), new ReviveStatusPacket.SendS2C(this.playerUuid, knockableDown.knockdowns$isBeingRevived()));
}
});
}
}
public static class RevivedC2S extends KnockdownsPacket {
private final UUID playerUuid;
public RevivedC2S(PacketByteBuf buf) {
this(buf.readUuid());
}
public RevivedC2S(UUID playerUuid) {
this.playerUuid = playerUuid;
}
@Override
public void encode(PacketByteBuf buf) {
buf.writeUuid(this.playerUuid);
}
@Override
public void apply(Supplier<NetworkManager.PacketContext> contextSupplier) {
NetworkManager.PacketContext context = contextSupplier.get();
context.queue(() -> {
PlayerEntity reviving = context.getPlayer().getWorld().getPlayerByUuid(this.playerUuid);
IKnockableDown knockableDown = (IKnockableDown) reviving;
if (knockableDown == null || !knockableDown.knockdowns$isKnockedDown()) {
return;
}
reviving.setInvulnerable(false);
reviving.setGlowing(false);
reviving.setHealth(6.0f);
knockableDown.knockdowns$setKnockedDown(false);
KnockdownsNetwork.sendToListenersAndSelf(reviving, new KnockedDownStatusPacket.SendS2C(reviving.getUuid(), false));
});
}
}
}

View file

@ -0,0 +1,18 @@
package ru.octol1ttle.knockdowns.common.registries;
import dev.architectury.registry.registries.DeferredRegister;
import dev.architectury.registry.registries.RegistrySupplier;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Identifier;
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
public class KnockdownsSoundEvents {
private static final DeferredRegister<SoundEvent> SOUND_EVENTS = DeferredRegister.create(KnockdownsCommon.MOD_ID, RegistryKeys.SOUND_EVENT);
public static final RegistrySupplier<SoundEvent> KNOCKED_DOWN = SOUND_EVENTS.register(KnockdownsCommon.MOD_ID,
() -> SoundEvent.of(new Identifier(KnockdownsCommon.MOD_ID, "knocked_down")));
public static void register() {
SOUND_EVENTS.register();
}
}

View file

@ -0,0 +1,31 @@
package ru.octol1ttle.knockdowns.common.registries;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.sound.MovingSoundInstance;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
public class KnockedDownSoundInstance extends MovingSoundInstance {
private final Vec3d pos;
public KnockedDownSoundInstance(SoundEvent sound, Vec3d pos) {
super(sound, SoundCategory.MASTER, Random.create(0L));
this.pos = pos;
this.relative = true;
}
@Override
public void tick() {
ClientPlayerEntity player = MinecraftClient.getInstance().player;
if (player == null) {
throw new IllegalStateException();
}
Vec3d vec = pos.subtract(player.getPos()).normalize();
this.x = vec.x;
this.y = vec.y;
this.z = vec.z;
}
}

View file

@ -1,3 +1,102 @@
{
"item.knockdowns.example_item": "Example Item"
"knockdown.attack.anvil": "%1$s was knocked down by a falling anvil",
"knockdown.attack.anvil.player": "%1$s was knocked down by a falling anvil while fighting %2$s",
"knockdown.attack.arrow": "%1$s was knocked down due to an arrow fired by %2$s",
"knockdown.attack.arrow.item": "%1$s was knocked down due to an arrow fired by %2$s using %3$s",
"knockdown.attack.badRespawnPoint.link": "Intentional Game Design",
"knockdown.attack.badRespawnPoint.message": "%1$s was knocked down by %2$s",
"knockdown.attack.cactus": "%1$s was knocked down by a cactus",
"knockdown.attack.cactus.player": "%1$s was knocked down into a cactus while trying to escape %2$s",
"knockdown.attack.cramming": "%1$s was knocked down by squishing",
"knockdown.attack.cramming.player": "%1$s was knocked down due to being squashed by %2$s",
"knockdown.attack.dragonBreath": "%1$s was knocked down by dragon's breath",
"knockdown.attack.dragonBreath.player": "%1$s was knocked down by dragon's breath by %2$s",
"knockdown.attack.drown": "%1$s was knocked down by drowning",
"knockdown.attack.drown.player": "%1$s was knocked down by drowning while trying to escape %2$s",
"knockdown.attack.dryout": "%1$s was knocked down by dehydration",
"knockdown.attack.dryout.player": "%1$s was knocked down by dehydration while trying to escape %2$s",
"knockdown.attack.even_more_magic": "%1$s was knocked down by even more magic",
"knockdown.attack.explosion": "%1$s was knocked down due to an explosion",
"knockdown.attack.explosion.player": "%1$s was knocked down due to an explosion caused by %2$s",
"knockdown.attack.explosion.player.item": "%1$s was knocked down due to an explosion caused by %2$s using %3$s",
"knockdown.attack.fall": "%1$s was knocked down by a fall",
"knockdown.attack.fall.player": "%1$s was knocked down by a fall while trying to escape %2$s",
"knockdown.attack.fallingBlock": "%1$s was knocked down by a falling block",
"knockdown.attack.fallingBlock.player": "%1$s was knocked down by a falling block while fighting %2$s",
"knockdown.attack.fallingStalactite": "%1$s was knocked down by a falling stalactite",
"knockdown.attack.fallingStalactite.player": "%1$s was knocked down by a falling stalactite while fighting %2$s",
"knockdown.attack.fireball": "%1$s was knocked down due to a fireball fired by %2$s",
"knockdown.attack.fireball.item": "%1$s was knocked down due to a fireball fired by %2$s using %3$s",
"knockdown.attack.fireworks": "%1$s was knocked down with a bang",
"knockdown.attack.fireworks.item": "%1$s was knocked down with a bang due to a firework fired from %3$s by %2$s",
"knockdown.attack.fireworks.player": "%1$s was knocked down with a bang while fighting %2$s",
"knockdown.attack.flyIntoWall": "%1$s was knocked down by kinetic energy",
"knockdown.attack.flyIntoWall.player": "%1$s was knocked down by kinetic energy while trying to escape %2$s",
"knockdown.attack.freeze": "%1$s was knocked down by freezing",
"knockdown.attack.freeze.player": "%1$s was knocked down by freezing by %2$s",
"knockdown.attack.generic": "%1$s was knocked down",
"knockdown.attack.generic.player": "%1$s was knocked down because of %2$s",
"knockdown.attack.genericKill": "%1$s was knocked down",
"knockdown.attack.genericKill.player": "%1$s was knocked down while fighting %2$s",
"knockdown.attack.hotFloor": "%1$s was knocked down by the lava floor",
"knockdown.attack.hotFloor.player": "%1$s was knocked down by the lava floor due to %2$s",
"knockdown.attack.indirectMagic": "%1$s was knocked down by %2$s using magic",
"knockdown.attack.indirectMagic.item": "%1$s was knocked down by %2$s using %3$s",
"knockdown.attack.inFire": "%1$s was knocked down by fire",
"knockdown.attack.inFire.player": "%1$s was knocked down by fire while fighting %2$s",
"knockdown.attack.inWall": "%1$s was knocked down by suffocation",
"knockdown.attack.inWall.player": "%1$s was knocked down by suffocation while fighting %2$s",
"knockdown.attack.lava": "%1$s was knocked down by lava",
"knockdown.attack.lava.player": "%1$s was knocked down by lava while trying to escape %2$s",
"knockdown.attack.lightningBolt": "%1$s was knocked down by lightning",
"knockdown.attack.lightningBolt.player": "%1$s was knocked down by lightning while fighting %2$s",
"knockdown.attack.magic": "%1$s was knocked down by magic",
"knockdown.attack.magic.player": "%1$s was knocked down by magic while trying to escape %2$s",
"knockdown.attack.message_too_long": "Actually, the message was too long to deliver fully. Sorry! Here's a stripped version: %s",
"knockdown.attack.mob": "%1$s was knocked down by %2$s",
"knockdown.attack.mob.item": "%1$s was knocked down by %2$s using %3$s",
"knockdown.attack.onFire": "%1$s was knocked down by fire",
"knockdown.attack.onFire.item": "%1$s was knocked down by fire while fighting %2$s wielding %3$s",
"knockdown.attack.onFire.player": "%1$s was knocked down by fire while fighting %2$s",
"knockdown.attack.outOfWorld": "%1$s was knocked down by the void",
"knockdown.attack.outOfWorld.player": "%1$s was knocked down by the void while fighting %2$s",
"knockdown.attack.outsideBorder": "%1$s was knocked down by the world border",
"knockdown.attack.outsideBorder.player": "%1$s was knocked down by the world border while fighting %2$s",
"knockdown.attack.player": "%1$s was knocked down by %2$s",
"knockdown.attack.player.item": "%1$s was knocked down by %2$s using %3$s",
"knockdown.attack.sonic_boom": "%1$s was knocked down by a sonically-charged shriek",
"knockdown.attack.sonic_boom.item": "%1$s was knocked down by a sonically-charged shriek while trying to escape %2$s wielding %3$s",
"knockdown.attack.sonic_boom.player": "%1$s was knocked down by a sonically-charged shriek while trying to escape %2$s",
"knockdown.attack.stalagmite": "%1$s was knocked down by a stalagmite",
"knockdown.attack.stalagmite.player": "%1$s was knocked down by a stalagmite while fighting %2$s",
"knockdown.attack.starve": "%1$s was knocked down by starving",
"knockdown.attack.starve.player": "%1$s was knocked down by starving while fighting %2$s",
"knockdown.attack.sting": "%1$s was knocked down by stings",
"knockdown.attack.sting.item": "%1$s was knocked down by stings by %2$s using %3$s",
"knockdown.attack.sting.player": "%1$s was knocked down by stings by %2$s",
"knockdown.attack.sweetBerryBush": "%1$s was knocked down by a sweet berry bush",
"knockdown.attack.sweetBerryBush.player": "%1$s was knocked down by a sweet berry bush while trying to escape %2$s",
"knockdown.attack.thorns": "%1$s was knocked down while trying to hurt %2$s",
"knockdown.attack.thorns.item": "%1$s was knocked down by %3$s while trying to hurt %2$s",
"knockdown.attack.thrown": "%1$s was knocked down due to being thrown by %2$s",
"knockdown.attack.thrown.item": "%1$s was knocked down due to being thrown by %2$s using %3$s",
"knockdown.attack.trident": "%1$s was knocked down due to being impaled by %2$s",
"knockdown.attack.trident.item": "%1$s was knocked down due to being impaled by %2$s with %3$s",
"knockdown.attack.wither": "%1$s was knocked down by withering",
"knockdown.attack.wither.player": "%1$s was knocked down by withering while fighting %2$s",
"knockdown.attack.witherSkull": "%1$s was knocked down by a skull from %2$s",
"knockdown.attack.witherSkull.item": "%1$s was knocked down by a skull from %2$s using %3$s",
"knockdown.fell.accident.generic": "%1$s was knocked down by a fall",
"knockdown.fell.accident.ladder": "%1$s was knocked down by a fall off a ladder",
"knockdown.fell.accident.other_climbable": "%1$s was knocked down by a fall while climbing",
"knockdown.fell.accident.scaffolding": "%1$s was knocked down by a fall off scaffolding",
"knockdown.fell.accident.twisting_vines": "%1$s was knocked down by a fall off some twisting vines",
"knockdown.fell.accident.vines": "%1$s was knocked down by a fall off some vines",
"knockdown.fell.accident.weeping_vines": "%1$s was knocked down by a fall off some weeping vines",
"knockdown.fell.assist": "%1$s was doomed to get knocked down by %2$s",
"knockdown.fell.assist.item": "%1$s was doomed to get knocked down by %2$s using %3$s",
"knockdown.fell.finish": "%1$s fell too far and was knocked down by %2$s",
"knockdown.fell.finish.item": "%1$s fell too far and was knocked down by %2$s using %3$s",
"knockdown.fell.killer": "%1$s was doomed to get knocked down by a fall",
"subtitles.knockdowns.knocked_down": "Player knocked down"
}

View file

@ -0,0 +1,102 @@
{
"knockdown.attack.anvil": "%1$s был тяжело ранен упавшей наковальней",
"knockdown.attack.anvil.player": "%1$s был тяжело ранен упавшей наковальней, пока сражался с %2$s",
"knockdown.attack.arrow": "%1$s тяжело ранен стрелой %2$s",
"knockdown.attack.arrow.item": "%1$s тяжело ранен стрелой %2$s из %3$s",
"knockdown.attack.badRespawnPoint.link": "жестокими правилами игры",
"knockdown.attack.badRespawnPoint.message": "%1$s был тяжело ранен %2$s",
"knockdown.attack.cactus": "%1$s был тяжело ранен кактусом",
"knockdown.attack.cactus.player": "%1$s был тяжело ранен кактусом, спасаясь от %2$s",
"knockdown.attack.cramming": "%1$s был тяжело ранен расплющиванием",
"knockdown.attack.cramming.player": "%1$s был тяжело ранен расплющиванием %2$s",
"knockdown.attack.dragonBreath": "%1$s был тяжело ранен в драконьем дыхании",
"knockdown.attack.dragonBreath.player": "%1$s был тяжело ранен в драконьем дыхании из-за %2$s",
"knockdown.attack.drown": "%1$s был тяжело ранен утоплением",
"knockdown.attack.drown.player": "%1$s был тяжело ранен утоплением, спасаясь от %2$s",
"knockdown.attack.dryout": "%1$s был тяжело ранен обезвоживанием",
"knockdown.attack.dryout.player": "%1$s был тяжело ранен обезвоживанием, спасаясь от %2$s",
"knockdown.attack.even_more_magic": "%1$s был тяжело ранен неизведанной магией",
"knockdown.attack.explosion": "%1$s был тяжело ранен взрывом",
"knockdown.attack.explosion.player": "%1$s был тяжело ранен взрывом %2$s",
"knockdown.attack.explosion.player.item": "%1$s был тяжело ранен взрывом %2$s с помощью %3$s",
"knockdown.attack.fall": "%1$s был тяжело ранен падением",
"knockdown.attack.fall.player": "%1$s был тяжело ранен падением, спасаясь от %2$s",
"knockdown.attack.fallingBlock": "%1$s был тяжело ранен упавшим блоком",
"knockdown.attack.fallingBlock.player": "%1$s был тяжело ранен упавшим блоком, пока боролся с %2$s",
"knockdown.attack.fallingStalactite": "%1$s был тяжело ранен обрушившимся сталактитом",
"knockdown.attack.fallingStalactite.player": "%1$s был тяжело ранен обрушившимся сталактитом, пока боролся с %2$s",
"knockdown.attack.fireball": "%1$s был тяжело ранен файерболом %2$s",
"knockdown.attack.fireball.item": "%1$s был тяжело ранен файерболом %2$s с помощью %3$s",
"knockdown.attack.fireworks": "%1$s был тяжело ранен взрывом фейерверка",
"knockdown.attack.fireworks.item": "%1$s был тяжело ранен взрывом фейерверка %2$s, выпущенного из %3$s",
"knockdown.attack.fireworks.player": "%1$s был тяжело ранен взрывом фейерверка, пока боролся с %2$s",
"knockdown.attack.flyIntoWall": "%1$s был тяжело ранен кинетической энергией",
"knockdown.attack.flyIntoWall.player": "%1$s был тяжело ранен кинетической энергией, спасаясь от %2$s",
"knockdown.attack.freeze": "%1$s был тяжело ранен замерзанием",
"knockdown.attack.freeze.player": "%1$s был тяжело ранен замерзанием благодаря %2$s",
"knockdown.attack.generic": "%1$s тяжело ранен",
"knockdown.attack.generic.player": "%1$s тяжело ранен из-за %2$s",
"knockdown.attack.genericKill": "%1$s тяжело ранен",
"knockdown.attack.genericKill.player": "%1$s был тяжело ранен, пока боролся с %2$s",
"knockdown.attack.hotFloor": "%1$s был тяжело ранен, обнаружив, что пол — это лава",
"knockdown.attack.hotFloor.player": "%1$s был тяжело ранен, так как зашёл в опасную зону из-за %2$s",
"knockdown.attack.inFire": "%1$s был тяжело ранен в огне",
"knockdown.attack.inFire.player": "%1$s был тяжело ранен в огне, пока боролся с %2$s",
"knockdown.attack.inWall": "%1$s был тяжело ранен погребением заживо",
"knockdown.attack.inWall.player": "%1$s был тяжело ранен погребением заживо, пока боролся с %2$s",
"knockdown.attack.indirectMagic": "%1$s был тяжело ранен %2$s с помощью магии",
"knockdown.attack.indirectMagic.item": "%1$s был тяжело ранен %2$s с помощью %3$s",
"knockdown.attack.lava": "%1$s был тяжело ранен лавой",
"knockdown.attack.lava.player": "%1$s был тяжело ранен лавой, убегая от %2$s",
"knockdown.attack.lightningBolt": "%1$s был тяжело ранен молнией",
"knockdown.attack.lightningBolt.player": "%1$s был тяжело ранен молнией, пока сражался с %2$s",
"knockdown.attack.magic": "%1$s был тяжело ранен магией",
"knockdown.attack.magic.player": "%1$s был тяжело ранен магией, убегая от %2$s",
"knockdown.attack.message_too_long": "Сообщение слишком длинное для доставки. Извините! Вот сокращённая версия: %s",
"knockdown.attack.mob": "%1$s был тяжело ранен %2$s",
"knockdown.attack.mob.item": "%1$s был тяжело ранен %2$s с помощью %3$s",
"knockdown.attack.onFire": "%1$s был тяжело ранен огнём",
"knockdown.attack.onFire.item": "%1$s был тяжело ранен огнём, пока боролся с %2$s, с помощью %3$s",
"knockdown.attack.onFire.player": "%1$s был тяжело ранен огнём, пока боролся с %2$s",
"knockdown.attack.outOfWorld": "%1$s был тяжело ранен пустотой",
"knockdown.attack.outOfWorld.player": "%1$s был тяжело ранен пустотой, благодаря %2$s",
"knockdown.attack.outsideBorder": "%1$s был тяжело ранен пределами этого мира",
"knockdown.attack.outsideBorder.player": "%1$s был тяжело ранен пределами этого мира, пока боролся с %2$s",
"knockdown.attack.player": "%1$s был тяжело ранен %2$s",
"knockdown.attack.player.item": "%1$s был тяжело ранен %2$s с помощью %3$s",
"knockdown.attack.sonic_boom": "%1$s был тяжело ранен звуковым зарядом",
"knockdown.attack.sonic_boom.item": "%1$s был тяжело ранен звуковым ударом, спасаясь от %2$s c %3$s",
"knockdown.attack.sonic_boom.player": "%1$s был тяжело ранен звуковым ударом, спасаясь от %2$s",
"knockdown.attack.stalagmite": "%1$s был тяжело ранен сталагмитом",
"knockdown.attack.stalagmite.player": "%1$s был тяжело ранен сталагмитом, пока боролся с %2$s",
"knockdown.attack.starve": "%1$s был тяжело ранен голодом",
"knockdown.attack.starve.player": "%1$s был тяжело ранен голодом, пока боролся с %2$s",
"knockdown.attack.sting": "%1$s был тяжело ранен изжалением",
"knockdown.attack.sting.item": "%1$s был тяжело ранен изжалением %2$s с помощью %3$s",
"knockdown.attack.sting.player": "%1$s был тяжело ранен изжалением %2$s",
"knockdown.attack.sweetBerryBush": "%1$s был тяжело ранен исколением в кустах сладких ягод",
"knockdown.attack.sweetBerryBush.player": "%1$s был тяжело ранен исколением в кустах сладких ягод, спасаясь от %2$s",
"knockdown.attack.thorns": "%1$s был тяжело ранен, пытаясь навредить %2$s",
"knockdown.attack.thorns.item": "%1$s был тяжело ранен %3$s, пытаясь навредить %2$s",
"knockdown.attack.thrown": "%1$s был тяжело ранен %2$s",
"knockdown.attack.thrown.item": "%1$s был тяжело ранен %2$s с помощью %3$s",
"knockdown.attack.trident": "%1$s был тяжело ранен пронзанием %2$s",
"knockdown.attack.trident.item": "%1$s был тяжело ранен пронзанием %2$s с помощью %3$s",
"knockdown.attack.wither": "%1$s был тяжело ранен иссушением",
"knockdown.attack.wither.player": "%1$s был тяжело ранен иссушением, пока боролся с %2$s",
"knockdown.attack.witherSkull": "%1$s был тяжело ранен поражением черепом из %2$s",
"knockdown.attack.witherSkull.item": "%1$s был тяжело ранен поражением черепом из %2$s с помощью %3$s",
"knockdown.fell.accident.generic": "%1$s был тяжело ранен падением",
"knockdown.fell.accident.ladder": "%1$s был тяжело ранен падением с лестницы",
"knockdown.fell.accident.other_climbable": "%1$s был тяжело ранен падением",
"knockdown.fell.accident.scaffolding": "%1$s был тяжело ранен падением с подмосток",
"knockdown.fell.accident.twisting_vines": "%1$s был тяжело ранен падением с вьющейся лозы",
"knockdown.fell.accident.vines": "%1$s был тяжело ранен падением с лианы",
"knockdown.fell.accident.weeping_vines": "%1$s был тяжело ранен падением с плакучей лозы",
"knockdown.fell.assist": "%1$s был тяжело ранен падением благодаря %2$s",
"knockdown.fell.assist.item": "%1$s был тяжело ранен падением благодаря %2$s с помощью %3$s",
"knockdown.fell.finish": "%1$s упал с высоты и был тяжело ранен %2$s",
"knockdown.fell.finish.item": "%1$s упал с высоты и был тяжело ранен %2$s с помощью %3$s",
"knockdown.fell.killer": "%1$s был тяжело ранен падением",
"subtitles.knockdowns.knocked_down": "Игрок тяжело ранен"
}

View file

@ -0,0 +1,10 @@
{
"knocked_down": {
"subtitle": "subtitles.knockdowns.knocked_down",
"sounds": [
{
"name": "knockdowns:knocked_down"
}
]
}
}

View file

@ -1,12 +1,13 @@
{
"required": true,
"package": "net.knockdowns.mixin",
"package": "ru.octol1ttle.knockdowns.common.mixin",
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [
"ru.octol1ttle.knockdowns.mixin.MixinTitleScreen"
"client.ClientPlayerEntityMixin"
],
"mixins": [
"PlayerEntityMixin"
],
"injectors": {
"defaultRequire": 1

View file

@ -1 +1,4 @@
accessWidener v2 named
accessible field net/minecraft/server/world/ThreadedAnvilChunkStorage entityTrackers Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;
accessible field net/minecraft/server/world/ThreadedAnvilChunkStorage$EntityTracker listeners Ljava/util/Set;

View file

@ -1,6 +1,6 @@
{
"required": true,
"package": "net.knockdowns.mixin.fabric",
"package": "ru.octol1ttle.knockdowns.fabric.mixin",
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [

View file

@ -34,6 +34,8 @@ dependencies {
common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
implementation(include("io.github.llamalad7:mixinextras-forge:0.3.3"))
}
processResources {

View file

@ -1,9 +1,9 @@
package ru.octol1ttle.knockdowns.forge;
import dev.architectury.platform.forge.EventBuses;
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import ru.octol1ttle.knockdowns.common.KnockdownsCommon;
@Mod(KnockdownsCommon.MOD_ID)
public class KnockdownsForge {

View file

@ -1,6 +1,6 @@
{
"required": true,
"package": "net.knockdowns.mixin.forge",
"package": "ru.octol1ttle.knockdowns.forge.mixin",
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [

View file

@ -10,7 +10,7 @@ maven_group=ru.octol1ttle.knockdowns
architectury_version=9.1.12
fabric_api_version=0.90.4+1.20.1
fabric_loader_version=0.15.4
fabric_loader_version=0.15.5
forge_version=1.20.1-47.2.0