add "Help Up" feature for knocked players, improve execution handling, and update mod version to 1.6.0
This commit is contained in:
+1
-1
@@ -50,7 +50,7 @@ mod_name=Knockedback
|
||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=MIT
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=1.5.3
|
||||
mod_version=1.6.0
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
|
||||
@@ -43,7 +43,8 @@ public class CarryManager {
|
||||
.filter(p -> KnockedManager.isKnocked(p)
|
||||
&& !p.getUUID().equals(carrier.getUUID())
|
||||
&& !isBeingCarried(p.getUUID())
|
||||
&& !PlayerExecutionHandler.isBeingPlayerExecuted(p.getUUID()))
|
||||
&& !PlayerExecutionHandler.isBeingPlayerExecuted(p.getUUID())
|
||||
&& !HelpUpHandler.isBeingHelped(p.getUUID()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
@@ -56,6 +57,7 @@ public class CarryManager {
|
||||
if (knocked instanceof ServerPlayer spKnocked) {
|
||||
spKnocked.connection.send(mountPacket);
|
||||
}
|
||||
KnockedbackAdvancements.recordCarry(carrier);
|
||||
carrier.sendSystemMessage(Component.translatable("message.knockedback.picked_up", knocked.getDisplayName()));
|
||||
knocked.sendSystemMessage(Component.translatable("message.knockedback.being_carried", carrier.getDisplayName()));
|
||||
}
|
||||
|
||||
@@ -8,17 +8,40 @@ import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ExecutionProgressPacket {
|
||||
public enum Action {
|
||||
NONE,
|
||||
EXECUTION,
|
||||
HELP_UP
|
||||
}
|
||||
|
||||
private final int timeLeft;
|
||||
private final int totalTicks;
|
||||
private final Action action;
|
||||
private final String targetName;
|
||||
@Nullable
|
||||
private final UUID executorId;
|
||||
|
||||
public ExecutionProgressPacket(int timeLeft, @Nullable UUID executorId) {
|
||||
this(timeLeft, PlayerExecutionHandler.getExecutionTime(), timeLeft > 0 ? Action.EXECUTION : Action.NONE, "", executorId);
|
||||
}
|
||||
|
||||
public ExecutionProgressPacket(int timeLeft, int totalTicks, Action action, @Nullable UUID executorId) {
|
||||
this(timeLeft, totalTicks, action, "", executorId);
|
||||
}
|
||||
|
||||
public ExecutionProgressPacket(int timeLeft, int totalTicks, Action action, String targetName, @Nullable UUID executorId) {
|
||||
this.timeLeft = timeLeft;
|
||||
this.totalTicks = totalTicks;
|
||||
this.action = timeLeft > 0 ? action : Action.NONE;
|
||||
this.targetName = timeLeft > 0 ? targetName : "";
|
||||
this.executorId = executorId;
|
||||
}
|
||||
|
||||
public static void encode(ExecutionProgressPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeInt(msg.timeLeft);
|
||||
buf.writeInt(msg.totalTicks);
|
||||
buf.writeEnum(msg.action);
|
||||
buf.writeUtf(msg.targetName);
|
||||
buf.writeBoolean(msg.executorId != null);
|
||||
if (msg.executorId != null) {
|
||||
buf.writeUUID(msg.executorId);
|
||||
@@ -27,13 +50,16 @@ public class ExecutionProgressPacket {
|
||||
|
||||
public static ExecutionProgressPacket decode(FriendlyByteBuf buf) {
|
||||
int timeLeft = buf.readInt();
|
||||
int totalTicks = buf.readInt();
|
||||
Action action = buf.readEnum(Action.class);
|
||||
String targetName = buf.readUtf();
|
||||
UUID executorId = buf.readBoolean() ? buf.readUUID() : null;
|
||||
return new ExecutionProgressPacket(timeLeft, executorId);
|
||||
return new ExecutionProgressPacket(timeLeft, totalTicks, action, targetName, executorId);
|
||||
}
|
||||
|
||||
public static void handle(ExecutionProgressPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
net.fretux.knockedback.client.ClientExecutionState.setExecution(msg.timeLeft, msg.executorId);
|
||||
net.fretux.knockedback.client.ClientExecutionState.setProgress(msg.timeLeft, msg.totalTicks, msg.action, msg.targetName, msg.executorId);
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
package net.fretux.knockedback;
|
||||
|
||||
import net.fretux.knockedback.config.Config;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
||||
import net.minecraftforge.event.entity.player.AttackEntityEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = KnockedBack.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||
public class HelpUpHandler {
|
||||
public static final double HELP_UP_RANGE = 2.0;
|
||||
|
||||
private static final Map<UUID, HelpUpAttempt> helpUpAttempts = new HashMap<>();
|
||||
|
||||
public static int getHelpUpTime() {
|
||||
return Config.COMMON.helpUpTime.get();
|
||||
}
|
||||
|
||||
public static boolean isBeingHelped(UUID knockedId) {
|
||||
return helpUpAttempts.containsKey(knockedId);
|
||||
}
|
||||
|
||||
public static boolean isHelping(UUID helperId) {
|
||||
return helpUpAttempts.values().stream().anyMatch(attempt -> attempt.helperId.equals(helperId));
|
||||
}
|
||||
|
||||
public static void startHelpUp(ServerPlayer helper) {
|
||||
if (!Config.COMMON.helpUpEnabled.get()) return;
|
||||
if (KnockedManager.isKnocked(helper)) {
|
||||
helper.sendSystemMessage(Component.translatable("message.knockedback.cannot_help_while_knocked"));
|
||||
return;
|
||||
}
|
||||
if (PlayerExecutionHandler.isExecuting(helper.getUUID())) return;
|
||||
if (isHelping(helper.getUUID())) return;
|
||||
Player target = findNearestKnocked(helper);
|
||||
if (target == null) return;
|
||||
UUID knockedId = target.getUUID();
|
||||
if (CarryManager.isBeingCarried(knockedId)) {
|
||||
helper.sendSystemMessage(Component.translatable("message.knockedback.cannot_help_carried_player"));
|
||||
return;
|
||||
}
|
||||
if (helpUpAttempts.containsKey(knockedId)) return;
|
||||
helpUpAttempts.put(knockedId, new HelpUpAttempt(helper.getUUID()));
|
||||
helper.sendSystemMessage(Component.translatable("message.knockedback.help_up_started", target.getDisplayName()));
|
||||
target.sendSystemMessage(Component.translatable("message.knockedback.being_helped", helper.getDisplayName()));
|
||||
}
|
||||
|
||||
public static void cancelHelpUp(UUID knockedId) {
|
||||
HelpUpAttempt attempt = helpUpAttempts.remove(knockedId);
|
||||
if (attempt == null) return;
|
||||
ServerPlayer knocked = getPlayerByUuid(knockedId);
|
||||
if (knocked != null) {
|
||||
knocked.sendSystemMessage(Component.translatable("message.knockedback.help_up_interrupted"));
|
||||
clearProgress(knocked);
|
||||
}
|
||||
ServerPlayer helper = getPlayerByUuid(attempt.helperId);
|
||||
if (helper != null) {
|
||||
helper.sendSystemMessage(Component.translatable("message.knockedback.help_up_interrupted_helper"));
|
||||
clearProgress(helper);
|
||||
}
|
||||
}
|
||||
|
||||
public static void cancelHelpUpByHelper(UUID helperId) {
|
||||
List<UUID> toCancel = helpUpAttempts.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().helperId.equals(helperId))
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
for (UUID knockedId : toCancel) {
|
||||
cancelHelpUp(knockedId);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
|
||||
if (event.side.isServer() && event.phase == TickEvent.Phase.END && event.player instanceof ServerPlayer sp && isHelping(sp.getUUID())) {
|
||||
sp.setDeltaMovement(0, 0, 0);
|
||||
sp.setSprinting(false);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onAttackEntity(AttackEntityEvent event) {
|
||||
if (event.getEntity() instanceof ServerPlayer sp && isHelping(sp.getUUID())) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLivingHurt(LivingHurtEvent event) {
|
||||
if (!(event.getEntity() instanceof ServerPlayer hurtPlayer)) return;
|
||||
cancelHelpUpByHelper(hurtPlayer.getUUID());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END || !event.side.isServer()) return;
|
||||
Map<UUID, HelpUpAttempt> updated = new HashMap<>();
|
||||
List<UUID> toCancel = new ArrayList<>();
|
||||
List<UUID> toComplete = new ArrayList<>();
|
||||
for (Map.Entry<UUID, HelpUpAttempt> entry : helpUpAttempts.entrySet()) {
|
||||
UUID knockedId = entry.getKey();
|
||||
HelpUpAttempt attempt = entry.getValue();
|
||||
ServerPlayer knocked = getPlayerByUuid(knockedId);
|
||||
ServerPlayer helper = getPlayerByUuid(attempt.helperId);
|
||||
if (knocked == null || helper == null || !KnockedManager.isKnocked(knocked)) {
|
||||
toCancel.add(knockedId);
|
||||
continue;
|
||||
}
|
||||
if (CarryManager.isBeingCarried(knockedId)
|
||||
|| PlayerExecutionHandler.isBeingPlayerExecuted(knockedId)
|
||||
|| MobKillHandler.isBeingMobExecuted(knockedId)
|
||||
|| helper.distanceTo(knocked) > HELP_UP_RANGE) {
|
||||
toCancel.add(knockedId);
|
||||
continue;
|
||||
}
|
||||
attempt.timeLeft--;
|
||||
sendProgress(helper, knocked, attempt.timeLeft);
|
||||
sendProgress(knocked, knocked, attempt.timeLeft);
|
||||
if (attempt.timeLeft <= 0) {
|
||||
toComplete.add(knockedId);
|
||||
} else {
|
||||
updated.put(knockedId, attempt);
|
||||
}
|
||||
}
|
||||
for (UUID knockedId : toCancel) {
|
||||
cancelHelpUp(knockedId);
|
||||
}
|
||||
for (UUID knockedId : toComplete) {
|
||||
HelpUpAttempt attempt = helpUpAttempts.get(knockedId);
|
||||
if (attempt == null) continue;
|
||||
ServerPlayer knocked = getPlayerByUuid(knockedId);
|
||||
ServerPlayer helper = getPlayerByUuid(attempt.helperId);
|
||||
if (knocked == null || helper == null) {
|
||||
cancelHelpUp(knockedId);
|
||||
continue;
|
||||
}
|
||||
completeHelpUp(helper, knocked);
|
||||
}
|
||||
helpUpAttempts.clear();
|
||||
helpUpAttempts.putAll(updated);
|
||||
}
|
||||
|
||||
private static void completeHelpUp(ServerPlayer helper, ServerPlayer knocked) {
|
||||
helpUpAttempts.remove(knocked.getUUID());
|
||||
KnockedManager.removeKnockedState(knocked);
|
||||
knocked.heal(Config.COMMON.helpUpHealAmount.get().floatValue());
|
||||
clearProgress(helper);
|
||||
clearProgress(knocked);
|
||||
KnockedbackAdvancements.recordHelpUp(helper);
|
||||
KnockedbackAdvancements.award(knocked, KnockedbackAdvancements.BE_HELPED_UP);
|
||||
helper.sendSystemMessage(Component.translatable("message.knockedback.you_helped_up", knocked.getDisplayName()));
|
||||
knocked.sendSystemMessage(Component.translatable("message.knockedback.you_were_helped_up", helper.getDisplayName()));
|
||||
}
|
||||
|
||||
private static void sendProgress(ServerPlayer player, ServerPlayer target, int timeLeft) {
|
||||
NetworkHandler.CHANNEL.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new ExecutionProgressPacket(timeLeft, getHelpUpTime(), ExecutionProgressPacket.Action.HELP_UP, target.getDisplayName().getString(), null)
|
||||
);
|
||||
}
|
||||
|
||||
private static void clearProgress(ServerPlayer player) {
|
||||
NetworkHandler.CHANNEL.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new ExecutionProgressPacket(0, 1, ExecutionProgressPacket.Action.NONE, null)
|
||||
);
|
||||
}
|
||||
|
||||
private static Player findNearestKnocked(ServerPlayer helper) {
|
||||
AABB box = helper.getBoundingBox().inflate(HELP_UP_RANGE);
|
||||
return helper
|
||||
.getCommandSenderWorld()
|
||||
.getEntitiesOfClass(Player.class, box).stream()
|
||||
.filter(player -> KnockedManager.isKnocked(player)
|
||||
&& !player.getUUID().equals(helper.getUUID())
|
||||
&& !CarryManager.isBeingCarried(player.getUUID())
|
||||
&& !PlayerExecutionHandler.isBeingPlayerExecuted(player.getUUID())
|
||||
&& !MobKillHandler.isBeingMobExecuted(player.getUUID())
|
||||
&& !isBeingHelped(player.getUUID()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private static ServerPlayer getPlayerByUuid(UUID uuid) {
|
||||
MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
|
||||
return NetworkHandlerHelper.getPlayerByUuid(server, uuid);
|
||||
}
|
||||
|
||||
private static class HelpUpAttempt {
|
||||
private final UUID helperId;
|
||||
private int timeLeft;
|
||||
|
||||
private HelpUpAttempt(UUID helperId) {
|
||||
this.helperId = helperId;
|
||||
this.timeLeft = getHelpUpTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.fretux.knockedback;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class HelpUpKnockedPacket {
|
||||
private final boolean helping;
|
||||
|
||||
public HelpUpKnockedPacket(boolean helping) {
|
||||
this.helping = helping;
|
||||
}
|
||||
|
||||
public static void encode(HelpUpKnockedPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(msg.helping);
|
||||
}
|
||||
|
||||
public static HelpUpKnockedPacket decode(FriendlyByteBuf buf) {
|
||||
return new HelpUpKnockedPacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static void handle(HelpUpKnockedPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerPlayer helper = ctx.get().getSender();
|
||||
if (helper == null) return;
|
||||
if (msg.helping) {
|
||||
HelpUpHandler.startHelpUp(helper);
|
||||
} else {
|
||||
HelpUpHandler.cancelHelpUpByHelper(helper.getUUID());
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,9 @@ public class KnockedManager {
|
||||
knockedEntities.put(entity.getUUID(), getKnockedDuration());
|
||||
entity.setHealth(1.0F);
|
||||
applyKnockedEffects((Player) entity);
|
||||
if (entity instanceof ServerPlayer sp) {
|
||||
KnockedbackAdvancements.recordKnocked(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +72,7 @@ public class KnockedManager {
|
||||
knockedEntities.remove(entity.getUUID());
|
||||
setGripped(entity, false);
|
||||
MobKillHandler.clearKillAttempt(entity.getUUID());
|
||||
HelpUpHandler.cancelHelpUp(entity.getUUID());
|
||||
entity.setPose(Pose.STANDING);
|
||||
if (entity instanceof ServerPlayer sp) {
|
||||
NetworkHandler.CHANNEL.send(
|
||||
@@ -118,7 +122,8 @@ public class KnockedManager {
|
||||
continue;
|
||||
}
|
||||
if (MobKillHandler.isBeingMobExecuted(playerId)
|
||||
|| PlayerExecutionHandler.isBeingPlayerExecuted(playerId)) {
|
||||
|| PlayerExecutionHandler.isBeingPlayerExecuted(playerId)
|
||||
|| HelpUpHandler.isBeingHelped(playerId)) {
|
||||
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
||||
if (p != null) {
|
||||
applyKnockedEffects(p);
|
||||
@@ -206,6 +211,8 @@ public class KnockedManager {
|
||||
knockedEntities.remove(playerId);
|
||||
grippedEntities.remove(playerId);
|
||||
MobKillHandler.clearKillAttempt(playerId);
|
||||
HelpUpHandler.cancelHelpUp(playerId);
|
||||
HelpUpHandler.cancelHelpUpByHelper(playerId);
|
||||
NetworkHandler.CHANNEL.send(
|
||||
PacketDistributor.PLAYER.with(() -> sp),
|
||||
new KnockedTimePacket(0)
|
||||
@@ -220,11 +227,17 @@ public class KnockedManager {
|
||||
);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerClone(PlayerEvent.Clone event) {
|
||||
KnockedbackAdvancements.copyCounts(event.getOriginal(), event.getEntity());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerLoggedOut(PlayerLoggedOutEvent event) {
|
||||
if (!(event.getEntity() instanceof ServerPlayer sp)) {
|
||||
return;
|
||||
}
|
||||
HelpUpHandler.cancelHelpUpByHelper(sp.getUUID());
|
||||
if (!isKnocked(sp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package net.fretux.knockedback;
|
||||
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
public class KnockedbackAdvancements {
|
||||
private static final String CRITERION = "triggered";
|
||||
private static final String DATA_KEY = KnockedBack.MOD_ID + ".advancement_counts";
|
||||
|
||||
public static final ResourceLocation KNOCKED =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "knocked");
|
||||
public static final ResourceLocation KNOCKED_10 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "knocked_10");
|
||||
public static final ResourceLocation KNOCKED_50 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "knocked_50");
|
||||
public static final ResourceLocation EXECUTE_PLAYER =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "execute_player");
|
||||
public static final ResourceLocation EXECUTE_PLAYER_10 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "execute_player_10");
|
||||
public static final ResourceLocation EXECUTE_PLAYER_100 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "execute_player_100");
|
||||
public static final ResourceLocation HELP_UP =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "help_up");
|
||||
public static final ResourceLocation HELP_UP_10 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "help_up_10");
|
||||
public static final ResourceLocation HELP_UP_50 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "help_up_50");
|
||||
public static final ResourceLocation BE_HELPED_UP =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "be_helped_up");
|
||||
public static final ResourceLocation CARRY_PLAYER =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "carry_player");
|
||||
public static final ResourceLocation CARRY_PLAYER_10 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "carry_player_10");
|
||||
public static final ResourceLocation CARRY_PLAYER_50 =
|
||||
ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "carry_player_50");
|
||||
|
||||
public static void award(ServerPlayer player, ResourceLocation advancementId) {
|
||||
MinecraftServer server = player.getServer();
|
||||
if (server == null) return;
|
||||
Advancement advancement = server.getAdvancements().getAdvancement(advancementId);
|
||||
if (advancement == null) return;
|
||||
player.getAdvancements().award(advancement, CRITERION);
|
||||
}
|
||||
|
||||
public static void recordKnocked(ServerPlayer player) {
|
||||
award(player, KNOCKED);
|
||||
int count = increment(player, "knocked");
|
||||
awardAt(player, count, 10, KNOCKED_10);
|
||||
awardAt(player, count, 50, KNOCKED_50);
|
||||
}
|
||||
|
||||
public static void recordExecution(ServerPlayer player) {
|
||||
award(player, EXECUTE_PLAYER);
|
||||
int count = increment(player, "executions");
|
||||
awardAt(player, count, 10, EXECUTE_PLAYER_10);
|
||||
awardAt(player, count, 100, EXECUTE_PLAYER_100);
|
||||
}
|
||||
|
||||
public static void recordHelpUp(ServerPlayer player) {
|
||||
award(player, HELP_UP);
|
||||
int count = increment(player, "help_ups");
|
||||
awardAt(player, count, 10, HELP_UP_10);
|
||||
awardAt(player, count, 50, HELP_UP_50);
|
||||
}
|
||||
|
||||
public static void recordCarry(ServerPlayer player) {
|
||||
award(player, CARRY_PLAYER);
|
||||
int count = increment(player, "carries");
|
||||
awardAt(player, count, 10, CARRY_PLAYER_10);
|
||||
awardAt(player, count, 50, CARRY_PLAYER_50);
|
||||
}
|
||||
|
||||
private static void awardAt(ServerPlayer player, int count, int threshold, ResourceLocation advancementId) {
|
||||
if (count >= threshold) {
|
||||
award(player, advancementId);
|
||||
}
|
||||
}
|
||||
|
||||
private static int increment(ServerPlayer player, String key) {
|
||||
CompoundTag persistentData = player.getPersistentData();
|
||||
CompoundTag counts = persistentData.getCompound(DATA_KEY);
|
||||
int count = counts.getInt(key) + 1;
|
||||
counts.putInt(key, count);
|
||||
persistentData.put(DATA_KEY, counts);
|
||||
return count;
|
||||
}
|
||||
|
||||
public static void copyCounts(Player original, Player replacement) {
|
||||
CompoundTag originalData = original.getPersistentData();
|
||||
if (originalData.contains(DATA_KEY)) {
|
||||
replacement.getPersistentData().put(DATA_KEY, originalData.getCompound(DATA_KEY).copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public class MobKillHandler {
|
||||
if (knocked instanceof ServerPlayer sp) {
|
||||
NetworkHandler.CHANNEL.send(
|
||||
PacketDistributor.PLAYER.with(() -> sp),
|
||||
new ExecutionProgressPacket(attempt.timeLeft, null)
|
||||
new ExecutionProgressPacket(attempt.timeLeft, getExecutionTime(), ExecutionProgressPacket.Action.EXECUTION, knocked.getDisplayName().getString(), null)
|
||||
);
|
||||
}
|
||||
if (attempt.timeLeft <= 0) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
|
||||
public class NetworkHandler {
|
||||
public static final String PROTOCOL_VERSION = "1";
|
||||
public static final String PROTOCOL_VERSION = "4";
|
||||
public static SimpleChannel CHANNEL;
|
||||
public static void register() {
|
||||
CHANNEL = NetworkRegistry.newSimpleChannel(ResourceLocation.fromNamespaceAndPath(KnockedBack.MOD_ID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals);
|
||||
@@ -15,5 +15,6 @@ public class NetworkHandler {
|
||||
CHANNEL.registerMessage(id++, ExecutionProgressPacket.class, ExecutionProgressPacket::encode, ExecutionProgressPacket::decode, ExecutionProgressPacket::handle);
|
||||
CHANNEL.registerMessage(id++, CarryTogglePacket.class, CarryTogglePacket::encode, CarryTogglePacket::decode, CarryTogglePacket::handle);
|
||||
CHANNEL.registerMessage(id++, GrippedStatePacket.class, GrippedStatePacket::encode, GrippedStatePacket::decode, GrippedStatePacket::handle);
|
||||
CHANNEL.registerMessage(id++, HelpUpKnockedPacket.class, HelpUpKnockedPacket::encode, HelpUpKnockedPacket::decode, HelpUpKnockedPacket::handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ public class PlayerExecutionHandler {
|
||||
executor.sendSystemMessage(Component.translatable("message.knockedback.cannot_execute_carried_player"));
|
||||
return;
|
||||
}
|
||||
if (HelpUpHandler.isBeingHelped(knockedId)) return;
|
||||
if (executionAttempts.containsKey(knockedId)) return;
|
||||
executionAttempts.put(knockedId, new PlayerExecutionAttempt(executor.getUUID()));
|
||||
executor.sendSystemMessage(Component.translatable("message.knockedback.execution_started"));
|
||||
@@ -139,6 +140,7 @@ public class PlayerExecutionHandler {
|
||||
new ExecutionProgressPacket(0, null)
|
||||
);
|
||||
}
|
||||
KnockedbackAdvancements.recordExecution(executor);
|
||||
executor.sendSystemMessage(Component.translatable("message.knockedback.you_executed", knockedPlayer.getDisplayName()));
|
||||
if (knockedPlayer instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.sendSystemMessage(Component.translatable("message.knockedback.you_were_executed", executor.getDisplayName()));
|
||||
@@ -168,11 +170,11 @@ public class PlayerExecutionHandler {
|
||||
attempt.timeLeft--;
|
||||
NetworkHandler.CHANNEL.send(
|
||||
PacketDistributor.PLAYER.with(() -> executor),
|
||||
new ExecutionProgressPacket(attempt.timeLeft, attempt.executorUuid)
|
||||
new ExecutionProgressPacket(attempt.timeLeft, getExecutionTime(), ExecutionProgressPacket.Action.EXECUTION, knocked.getDisplayName().getString(), attempt.executorUuid)
|
||||
);
|
||||
NetworkHandler.CHANNEL.send(
|
||||
PacketDistributor.PLAYER.with(() -> knocked),
|
||||
new ExecutionProgressPacket(attempt.timeLeft, attempt.executorUuid)
|
||||
new ExecutionProgressPacket(attempt.timeLeft, getExecutionTime(), ExecutionProgressPacket.Action.EXECUTION, knocked.getDisplayName().getString(), attempt.executorUuid)
|
||||
);
|
||||
if (attempt.timeLeft <= 0) {
|
||||
toExecute.add(knockedId);
|
||||
|
||||
@@ -1,27 +1,79 @@
|
||||
package net.fretux.knockedback.client;
|
||||
|
||||
import net.fretux.knockedback.ExecutionProgressPacket;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ClientExecutionState {
|
||||
private static int timeLeft = 0;
|
||||
private static int totalTicks = 1;
|
||||
private static ExecutionProgressPacket.Action action = ExecutionProgressPacket.Action.NONE;
|
||||
private static String targetName = "";
|
||||
@Nullable
|
||||
private static UUID executorId;
|
||||
|
||||
public static void setExecution(int ticks, @Nullable UUID executor) {
|
||||
timeLeft = ticks;
|
||||
executorId = ticks > 0 ? executor : null;
|
||||
setProgress(ticks, net.fretux.knockedback.PlayerExecutionHandler.getExecutionTime(), ExecutionProgressPacket.Action.EXECUTION, "", executor);
|
||||
}
|
||||
|
||||
public static void setProgress(int ticks, int total, ExecutionProgressPacket.Action progressAction, @Nullable UUID actor) {
|
||||
setProgress(ticks, total, progressAction, "", actor);
|
||||
}
|
||||
|
||||
public static void setProgress(int ticks, int total, ExecutionProgressPacket.Action progressAction, String target, @Nullable UUID actor) {
|
||||
timeLeft = Math.max(0, ticks);
|
||||
totalTicks = Math.max(1, total);
|
||||
action = timeLeft > 0 ? progressAction : ExecutionProgressPacket.Action.NONE;
|
||||
targetName = timeLeft > 0 ? target : "";
|
||||
executorId = timeLeft > 0 ? actor : null;
|
||||
}
|
||||
|
||||
public static int getTotalTicks() {
|
||||
return totalTicks;
|
||||
}
|
||||
|
||||
public static ExecutionProgressPacket.Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public static String getTargetName() {
|
||||
return targetName;
|
||||
}
|
||||
|
||||
public static boolean isHelpUp() {
|
||||
return isActive() && action == ExecutionProgressPacket.Action.HELP_UP;
|
||||
}
|
||||
|
||||
public static boolean isExecution() {
|
||||
return isActive() && action == ExecutionProgressPacket.Action.EXECUTION;
|
||||
}
|
||||
|
||||
public static boolean isActive() {
|
||||
return timeLeft > 0;
|
||||
}
|
||||
|
||||
public static boolean isExecuting() {
|
||||
return isExecution();
|
||||
}
|
||||
|
||||
public static boolean hasProgress() {
|
||||
return isActive();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
timeLeft = 0;
|
||||
totalTicks = 1;
|
||||
action = ExecutionProgressPacket.Action.NONE;
|
||||
targetName = "";
|
||||
executorId = null;
|
||||
}
|
||||
|
||||
public static int getTimeLeft() {
|
||||
return timeLeft;
|
||||
}
|
||||
|
||||
public static boolean isExecuting() {
|
||||
return timeLeft > 0;
|
||||
}
|
||||
|
||||
public static boolean isExecutor(UUID playerId) {
|
||||
return timeLeft > 0 && executorId != null && executorId.equals(playerId);
|
||||
return isExecution() && executorId != null && executorId.equals(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package net.fretux.knockedback.client;
|
||||
|
||||
import net.fretux.knockedback.CarryTogglePacket;
|
||||
import net.fretux.knockedback.ExecuteKnockedPacket;
|
||||
import net.fretux.knockedback.HelpUpKnockedPacket;
|
||||
import net.fretux.knockedback.NetworkHandler;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
@@ -27,6 +27,14 @@ public class ClientKeyHandler {
|
||||
"key.categories.knockedback"
|
||||
);
|
||||
|
||||
public static final KeyMapping HELP_UP_KEY = new KeyMapping(
|
||||
"key.knockedback.help_up",
|
||||
GLFW.GLFW_KEY_H,
|
||||
"key.categories.knockedback"
|
||||
);
|
||||
|
||||
private static boolean wasHelping;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "knockedback", value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public static class KeyMappingRegistration {
|
||||
@SubscribeEvent
|
||||
@@ -37,18 +45,29 @@ public class ClientKeyHandler {
|
||||
public static void registerCarryKey(RegisterKeyMappingsEvent e) {
|
||||
e.register(CARRY_KEY);
|
||||
}
|
||||
@SubscribeEvent
|
||||
public static void registerHelpUpKey(RegisterKeyMappingsEvent e) {
|
||||
e.register(HELP_UP_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (Minecraft.getInstance().screen != null) return;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (event.phase == TickEvent.Phase.END) {
|
||||
boolean isHelping = mc.player != null && mc.screen == null && HELP_UP_KEY.isDown();
|
||||
if (isHelping != wasHelping) {
|
||||
NetworkHandler.CHANNEL.sendToServer(new HelpUpKnockedPacket(isHelping));
|
||||
wasHelping = isHelping;
|
||||
}
|
||||
}
|
||||
if (mc.screen != null) return;
|
||||
if (EXECUTE_KEY.consumeClick()) {
|
||||
if (Minecraft.getInstance().player != null) {
|
||||
if (mc.player != null) {
|
||||
NetworkHandler.CHANNEL.sendToServer(new ExecuteKnockedPacket());
|
||||
}
|
||||
}
|
||||
if (event.phase == TickEvent.Phase.END && CARRY_KEY.consumeClick()) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.player != null && mc.screen == null) {
|
||||
NetworkHandler.CHANNEL.sendToServer(new CarryTogglePacket());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.fretux.knockedback.client;
|
||||
import net.fretux.knockedback.KnockedBack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.resources.language.I18n;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -10,22 +11,46 @@ import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = KnockedBack.MOD_ID, value = Dist.CLIENT)
|
||||
public class ExecutionProgressOverlay {
|
||||
private static final int BAR_WIDTH = 100;
|
||||
private static final int BAR_HEIGHT = 8;
|
||||
private static final int BAR_WIDTH = 132;
|
||||
private static final int BAR_HEIGHT = 9;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRender(RenderGuiOverlayEvent.Post event) {
|
||||
if (!ClientExecutionState.isExecuting()) return;
|
||||
if (!ClientExecutionState.hasProgress()) return;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
GuiGraphics gui = event.getGuiGraphics();
|
||||
int sw = mc.getWindow().getGuiScaledWidth();
|
||||
int sh = mc.getWindow().getGuiScaledHeight();
|
||||
int x = (sw - BAR_WIDTH) / 2;
|
||||
int y = (sh - BAR_HEIGHT) / 2;
|
||||
int totalTicks = net.fretux.knockedback.PlayerExecutionHandler.getExecutionTime();
|
||||
float progress = 1.0f - (ClientExecutionState.getTimeLeft() / (float) totalTicks);
|
||||
int y = (sh / 2) + 24;
|
||||
float progress = 1.0f - (ClientExecutionState.getTimeLeft() / (float) ClientExecutionState.getTotalTicks());
|
||||
progress = Math.max(0.0f, Math.min(1.0f, progress));
|
||||
int fillWidth = (int) (BAR_WIDTH * progress);
|
||||
gui.fill(x, y, x + BAR_WIDTH, y + BAR_HEIGHT, 0x80000000);
|
||||
gui.fill(x, y, x + fillWidth, y + BAR_HEIGHT, 0x80FFFFFF);
|
||||
int fillColor = ClientExecutionState.isHelpUp() ? 0xFF55D987 : 0xFFE05252;
|
||||
int fillHighlight = ClientExecutionState.isHelpUp() ? 0xFF8EF0B0 : 0xFFFF8A78;
|
||||
String targetName = ClientExecutionState.getTargetName();
|
||||
String label = targetName.isBlank()
|
||||
? I18n.get(ClientExecutionState.isHelpUp()
|
||||
? "overlay.knockedback.help_up_progress"
|
||||
: "overlay.knockedback.execution_progress")
|
||||
: I18n.get(ClientExecutionState.isHelpUp()
|
||||
? "overlay.knockedback.helping_up_target"
|
||||
: "overlay.knockedback.executing_target", targetName);
|
||||
String percent = Math.round(progress * 100.0f) + "%";
|
||||
int maxLabelWidth = BAR_WIDTH - mc.font.width(percent) - 6;
|
||||
if (mc.font.width(label) > maxLabelWidth) {
|
||||
label = mc.font.plainSubstrByWidth(label, Math.max(0, maxLabelWidth - 3)) + "...";
|
||||
}
|
||||
int labelY = y - 12;
|
||||
|
||||
gui.drawString(mc.font, label, x, labelY, 0xFFFFFFFF, true);
|
||||
gui.drawString(mc.font, percent, x + BAR_WIDTH - mc.font.width(percent), labelY, 0xFFE8E8E8, true);
|
||||
gui.fill(x - 2, y - 2, x + BAR_WIDTH + 2, y + BAR_HEIGHT + 2, 0xCC000000);
|
||||
gui.fill(x - 1, y - 1, x + BAR_WIDTH + 1, y + BAR_HEIGHT + 1, 0x99FFFFFF);
|
||||
gui.fill(x, y, x + BAR_WIDTH, y + BAR_HEIGHT, 0xDD101010);
|
||||
if (fillWidth > 0) {
|
||||
gui.fill(x, y, x + fillWidth, y + BAR_HEIGHT, fillColor);
|
||||
gui.fill(x, y, x + fillWidth, y + 2, fillHighlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,9 @@ public class Config {
|
||||
public static class Common {
|
||||
public final ForgeConfigSpec.IntValue knockedDuration;
|
||||
public final ForgeConfigSpec.IntValue executionTime;
|
||||
public final ForgeConfigSpec.IntValue helpUpTime;
|
||||
public final ForgeConfigSpec.DoubleValue helpUpHealAmount;
|
||||
public final ForgeConfigSpec.BooleanValue helpUpEnabled;
|
||||
public final ForgeConfigSpec.BooleanValue mobExecutionEnabled;
|
||||
public final ForgeConfigSpec.BooleanValue totemPreventsKnockdown;
|
||||
public final ForgeConfigSpec.ConfigValue<List<? extends String>> mobExecutionAllowlist;
|
||||
@@ -34,6 +37,18 @@ public class Config {
|
||||
.comment("How long (in ticks) it takes to execute a knocked player. Default: 60 (3 seconds).")
|
||||
.defineInRange("executionTime", 60, 20, 200);
|
||||
|
||||
helpUpEnabled = builder
|
||||
.comment("If true, players can help knocked players recover by holding the help-up key. Default: true.")
|
||||
.define("helpUpEnabled", true);
|
||||
|
||||
helpUpTime = builder
|
||||
.comment("How long (in ticks) it takes to help up a knocked player. Default: 60 (3 seconds).")
|
||||
.defineInRange("helpUpTime", 60, 20, 200);
|
||||
|
||||
helpUpHealAmount = builder
|
||||
.comment("How much health a helped-up player receives after recovery. Default: 4.0 (2 hearts).")
|
||||
.defineInRange("helpUpHealAmount", 4.0D, 1.0D, 20.0D);
|
||||
|
||||
mobExecutionEnabled = builder
|
||||
.comment("If true, mobs can execute knocked players. Default: true.")
|
||||
.define("mobExecutionEnabled", true);
|
||||
|
||||
@@ -1,23 +1,61 @@
|
||||
{
|
||||
"key.knockedback.carry": "Tragen",
|
||||
"key.knockedback.execute": "Hinrichten",
|
||||
"key.knockedback.help_up": "Aufhelfen",
|
||||
"key.categories.knockedback": "Knockedback-Steuerung",
|
||||
|
||||
"message.knockedback.cannot_carry_while_knocked": "Du kannst niemanden tragen, während du betäubt bist!",
|
||||
"message.knockedback.cannot_execute_while_knocked": "Du kannst niemanden hinrichten, während du betäubt bist!",
|
||||
"message.knockedback.cannot_carry_while_knocked": "Du kannst niemanden tragen, w\u00e4hrend du bet\u00e4ubt bist!",
|
||||
"message.knockedback.cannot_execute_while_knocked": "Du kannst niemanden hinrichten, w\u00e4hrend du bet\u00e4ubt bist!",
|
||||
"message.knockedback.cannot_execute_carried_player": "Du kannst keinen Spieler hinrichten, der getragen wird!",
|
||||
|
||||
"message.knockedback.cannot_help_while_knocked": "Du kannst niemandem aufhelfen, w\u00e4hrend du bet\u00e4ubt bist!",
|
||||
"message.knockedback.cannot_help_carried_player": "Du kannst keinem Spieler aufhelfen, der getragen wird!",
|
||||
"message.knockedback.execution_started": "Hinrichtung gestartet...",
|
||||
"message.knockedback.being_executed": "Du wirst hingerichtet!",
|
||||
"message.knockedback.execution_interrupted": "Hinrichtung abgebrochen!",
|
||||
"message.knockedback.execution_interrupted_executor": "Deine Hinrichtung wurde abgebrochen!",
|
||||
"message.knockedback.picked_up": "%1$s wurde Aufgehoben",
|
||||
"message.knockedback.being_carried": "Du wirst von %1$s getragen",
|
||||
"message.knockedback.dropped": "%1$s wurde Abgesetzt",
|
||||
"message.knockedback.been_dropped": "Du wurdest von %1$s abgesetzt",
|
||||
"message.knockedback.you_executed": "Du hast %1$s hingerichtet!",
|
||||
"message.knockedback.help_up_started": "Du hilfst %1$s auf...",
|
||||
"message.knockedback.being_helped": "%1$s hilft dir auf!",
|
||||
"message.knockedback.help_up_interrupted": "Aufhelfen abgebrochen!",
|
||||
"message.knockedback.help_up_interrupted_helper": "Dein Aufhelfen wurde abgebrochen!",
|
||||
"message.knockedback.you_helped_up": "Du hast %1$s aufgeholfen!",
|
||||
"message.knockedback.you_were_helped_up": "Dir wurde von %1$s aufgeholfen!",
|
||||
"message.knockedback.picked_up": "%1$s wurde aufgehoben",
|
||||
"message.knockedback.being_carried": "Du wirst von %1$s getragen",
|
||||
"message.knockedback.dropped": "%1$s wurde abgesetzt",
|
||||
"message.knockedback.been_dropped": "Du wurdest von %1$s abgesetzt",
|
||||
"message.knockedback.you_executed": "Du hast %1$s hingerichtet!",
|
||||
"message.knockedback.you_were_executed": "Du wurdest von %1$s hingerichtet!",
|
||||
"overlay.knockedback.execution_progress": "Hinrichten",
|
||||
"overlay.knockedback.help_up_progress": "Aufhelfen",
|
||||
"overlay.knockedback.executing_target": "%s hinrichten...",
|
||||
"overlay.knockedback.helping_up_target": "%s aufhelfen...",
|
||||
"overlay.knockedback.recovery_time": "Zeit bis Erholung: %s s",
|
||||
"death.attack.knockedback_execution": "%1$s wurde gnadenlos hingerichtet!"
|
||||
"death.attack.knockedback_execution": "%1$s wurde gnadenlos hingerichtet!",
|
||||
"advancements.knockedback.root.title": "Knocked Back",
|
||||
"advancements.knockedback.root.description": "\u00dcberlebe, rette andere oder beende den Kampf, w\u00e4hrend der Tod wartet.",
|
||||
"advancements.knockedback.knocked.title": "Noch nicht tot",
|
||||
"advancements.knockedback.knocked.description": "Werde bet\u00e4ubt.",
|
||||
"advancements.knockedback.knocked_10.title": "Hart im Nehmen",
|
||||
"advancements.knockedback.knocked_10.description": "Werde 10-mal bet\u00e4ubt.",
|
||||
"advancements.knockedback.knocked_50.title": "Bleibt nicht liegen",
|
||||
"advancements.knockedback.knocked_50.description": "Werde 50-mal bet\u00e4ubt.",
|
||||
"advancements.knockedback.execute_player.title": "Gnadensto\u00df",
|
||||
"advancements.knockedback.execute_player.description": "Richte einen bet\u00e4ubten Spieler hin.",
|
||||
"advancements.knockedback.execute_player_10.title": "Keine offenen Enden",
|
||||
"advancements.knockedback.execute_player_10.description": "Richte 10 bet\u00e4ubte Spieler hin.",
|
||||
"advancements.knockedback.execute_player_100.title": "Gnadenlos",
|
||||
"advancements.knockedback.execute_player_100.description": "Richte 100 bet\u00e4ubte Spieler hin.",
|
||||
"advancements.knockedback.help_up.title": "Feldsanit\u00e4ter",
|
||||
"advancements.knockedback.help_up.description": "Hilf einem bet\u00e4ubten Spieler wieder auf die Beine.",
|
||||
"advancements.knockedback.help_up_10.title": "Kampfsanit\u00e4ter",
|
||||
"advancements.knockedback.help_up_10.description": "Hilf 10 bet\u00e4ubten Spielern auf.",
|
||||
"advancements.knockedback.help_up_50.title": "Schutzengel",
|
||||
"advancements.knockedback.help_up_50.description": "Hilf 50 bet\u00e4ubten Spielern auf.",
|
||||
"advancements.knockedback.be_helped_up.title": "Zweiter Atem",
|
||||
"advancements.knockedback.be_helped_up.description": "Lass dir von einem anderen Spieler aufhelfen.",
|
||||
"advancements.knockedback.carry_player.title": "Niemand bleibt zur\u00fcck",
|
||||
"advancements.knockedback.carry_player.description": "Trage einen bet\u00e4ubten Spieler aus der Gefahr.",
|
||||
"advancements.knockedback.carry_player_10.title": "Evakuierungsteam",
|
||||
"advancements.knockedback.carry_player_10.description": "Trage 10 bet\u00e4ubte Spieler.",
|
||||
"advancements.knockedback.carry_player_50.title": "Bergungsexperte",
|
||||
"advancements.knockedback.carry_player_50.description": "Trage 50 bet\u00e4ubte Spieler."
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"key.knockedback.carry": "Carry",
|
||||
"key.knockedback.execute": "Execute",
|
||||
"key.knockedback.help_up": "Help Up",
|
||||
"key.categories.knockedback": "Knockedback Controls",
|
||||
"message.knockedback.cannot_carry_while_knocked": "You cannot carry others while you are knocked!",
|
||||
"message.knockedback.cannot_execute_while_knocked": "You cannot execute others while you are knocked!",
|
||||
"message.knockedback.cannot_execute_carried_player": "You cannot execute a player who is being carried!",
|
||||
"message.knockedback.cannot_help_while_knocked": "You cannot help others while you are knocked!",
|
||||
"message.knockedback.cannot_help_carried_player": "You cannot help up a player who is being carried!",
|
||||
"message.knockedback.picked_up": "Picked up %s",
|
||||
"message.knockedback.being_carried": "You are being carried by %s",
|
||||
"message.knockedback.dropped": "Dropped %s",
|
||||
@@ -13,8 +16,46 @@
|
||||
"message.knockedback.being_executed": "You're being executed!",
|
||||
"message.knockedback.execution_interrupted": "Execution interrupted!",
|
||||
"message.knockedback.execution_interrupted_executor": "Your execution was interrupted!",
|
||||
"message.knockedback.help_up_started": "Helping up %s...",
|
||||
"message.knockedback.being_helped": "%s is helping you up!",
|
||||
"message.knockedback.help_up_interrupted": "Help interrupted!",
|
||||
"message.knockedback.help_up_interrupted_helper": "Your help-up was interrupted!",
|
||||
"message.knockedback.you_helped_up": "You helped up %s!",
|
||||
"message.knockedback.you_were_helped_up": "You were helped up by %s!",
|
||||
"message.knockedback.you_executed": "You executed %s!",
|
||||
"message.knockedback.you_were_executed": "You were executed by %s!",
|
||||
"overlay.knockedback.execution_progress": "Executing",
|
||||
"overlay.knockedback.help_up_progress": "Helping up",
|
||||
"overlay.knockedback.executing_target": "Executing %s...",
|
||||
"overlay.knockedback.helping_up_target": "Helping up %s...",
|
||||
"overlay.knockedback.recovery_time": "Time until recovery: %s s",
|
||||
"death.attack.knockedback_execution": "%1$s was executed mercilessly."
|
||||
"death.attack.knockedback_execution": "%1$s was executed mercilessly.",
|
||||
"advancements.knockedback.root.title": "Knocked Back",
|
||||
"advancements.knockedback.root.description": "Survive, rescue, or finish the fight while death is waiting.",
|
||||
"advancements.knockedback.knocked.title": "Not Dead Yet",
|
||||
"advancements.knockedback.knocked.description": "Enter the knocked state.",
|
||||
"advancements.knockedback.knocked_10.title": "Built Different",
|
||||
"advancements.knockedback.knocked_10.description": "Enter the knocked state 10 times.",
|
||||
"advancements.knockedback.knocked_50.title": "Refuses to Stay Down",
|
||||
"advancements.knockedback.knocked_50.description": "Enter the knocked state 50 times.",
|
||||
"advancements.knockedback.execute_player.title": "Coup de Grace",
|
||||
"advancements.knockedback.execute_player.description": "Execute a knocked player.",
|
||||
"advancements.knockedback.execute_player_10.title": "No Loose Ends",
|
||||
"advancements.knockedback.execute_player_10.description": "Execute 10 knocked players.",
|
||||
"advancements.knockedback.execute_player_100.title": "Merciless",
|
||||
"advancements.knockedback.execute_player_100.description": "Execute 100 knocked players.",
|
||||
"advancements.knockedback.help_up.title": "Field Medic",
|
||||
"advancements.knockedback.help_up.description": "Help a knocked player back onto their feet.",
|
||||
"advancements.knockedback.help_up_10.title": "Combat Medic",
|
||||
"advancements.knockedback.help_up_10.description": "Help up 10 knocked players.",
|
||||
"advancements.knockedback.help_up_50.title": "Guardian Angel",
|
||||
"advancements.knockedback.help_up_50.description": "Help up 50 knocked players.",
|
||||
"advancements.knockedback.be_helped_up.title": "Second Wind",
|
||||
"advancements.knockedback.be_helped_up.description": "Get helped up by another player.",
|
||||
"advancements.knockedback.carry_player.title": "No One Left Behind",
|
||||
"advancements.knockedback.carry_player.description": "Carry a knocked player out of danger.",
|
||||
"advancements.knockedback.carry_player_10.title": "Evac Team",
|
||||
"advancements.knockedback.carry_player_10.description": "Carry 10 knocked players.",
|
||||
"advancements.knockedback.carry_player_50.title": "Extraction Expert",
|
||||
"advancements.knockedback.carry_player_50.description": "Carry 50 knocked players."
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"parent": "knockedback:knocked",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:honey_bottle"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.be_helped_up.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.be_helped_up.description"
|
||||
},
|
||||
"frame": "task",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": false
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"parent": "knockedback:knocked",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:lead"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.carry_player.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.carry_player.description"
|
||||
},
|
||||
"frame": "task",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": false
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:carry_player",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:saddle"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.carry_player_10.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.carry_player_10.description"
|
||||
},
|
||||
"frame": "goal",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:carry_player_10",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:elytra"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.carry_player_50.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.carry_player_50.description"
|
||||
},
|
||||
"frame": "challenge",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 150
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:knocked",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:iron_sword"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.execute_player.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.execute_player.description"
|
||||
},
|
||||
"frame": "challenge",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 25
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:execute_player",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:diamond_sword"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.execute_player_10.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.execute_player_10.description"
|
||||
},
|
||||
"frame": "goal",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:execute_player_10",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:netherite_sword"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.execute_player_100.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.execute_player_100.description"
|
||||
},
|
||||
"frame": "challenge",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 250
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"parent": "knockedback:knocked",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:golden_apple"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.help_up.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.help_up.description"
|
||||
},
|
||||
"frame": "goal",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:help_up",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:glistering_melon_slice"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.help_up_10.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.help_up_10.description"
|
||||
},
|
||||
"frame": "goal",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:help_up_10",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:enchanted_golden_apple"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.help_up_50.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.help_up_50.description"
|
||||
},
|
||||
"frame": "challenge",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 150
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"parent": "knockedback:root",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:redstone"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.knocked.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.knocked.description"
|
||||
},
|
||||
"frame": "task",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": false
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:knocked",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:shield"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.knocked_10.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.knocked_10.description"
|
||||
},
|
||||
"frame": "goal",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parent": "knockedback:knocked_10",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:netherite_chestplate"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.knocked_50.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.knocked_50.description"
|
||||
},
|
||||
"frame": "challenge",
|
||||
"show_toast": true,
|
||||
"announce_to_chat": true
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:impossible"
|
||||
}
|
||||
},
|
||||
"rewards": {
|
||||
"experience": 150
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "minecraft:totem_of_undying"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.knockedback.root.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.knockedback.root.description"
|
||||
},
|
||||
"background": "minecraft:textures/gui/advancements/backgrounds/adventure.png",
|
||||
"frame": "task",
|
||||
"show_toast": false,
|
||||
"announce_to_chat": false
|
||||
},
|
||||
"criteria": {
|
||||
"triggered": {
|
||||
"trigger": "minecraft:tick"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user