9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

Merge branch 'Xiao-MoMi:dev' into dev

This commit is contained in:
jhqwqmc
2025-09-20 02:20:36 +08:00
committed by GitHub
11 changed files with 132 additions and 110 deletions

View File

@@ -163,6 +163,8 @@ equipment:
humanoid-leggings: minecraft:trims/entity/humanoid_leggings/chainmail
block:
# This decides the amount of real blocks on serverside. Requires a restart to apply.
serverside-blocks: 2000
# Enables the sound system, which prevents the client from hearing some non-custom block sounds and improves the client experience.
sound-system:
enable: true
@@ -219,24 +221,7 @@ image:
chat: true
command: true
sign: true
# Allow <image:...> and <shift:...> tags in third-party plugins via packet manipulation
# ⚠️ Disable unused handlers to reduce async thread workload
intercept-packets:
system-chat: true
tab-list: true # Tab list header and footer
player-info: true # Player list in tab
set-score: true
actionbar: true
title: true
bossbar: true
container: true # GUI
team: true # Team prefix, suffix and display name
scoreboard: true
entity-name: false
armor-stand: true # Legacy Holograms
text-display: true # Modern Holograms
item: true
advancement: true
# Defines Unicode characters used for <shift:xxx> positioning
# - Must match the font defined in resource packs
# - Do NOT modify unless you understand text rendering mechanics
@@ -287,6 +272,26 @@ image:
128: '\uf844'
256: '\uf845'
network:
# Allow <image> <shift> <global> tags in third-party plugins via packet manipulation
# ⚠️ Disable unused handlers to reduce async thread workload
intercept-packets:
system-chat: true
tab-list: true # Tab list header and footer
player-info: true # Player list in tab
set-score: true
actionbar: true
title: true
bossbar: true
container: true # GUI
team: true # Team prefix, suffix and display name
scoreboard: true
entity-name: false
armor-stand: true # Legacy Holograms
text-display: true # Modern Holograms
item: true
advancement: true
recipe:
# Master switch for custom recipes
# NOTE: When enabled, plugin recipes will OVERRIDE vanilla recipes

View File

@@ -3,7 +3,6 @@ package net.momirealms.craftengine.core.entity.projectile;
import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -13,6 +12,5 @@ public record ProjectileMeta(Key item,
Vector3f scale,
Vector3f translation,
Quaternionf rotation,
double range,
@Nullable ProjectileType type) {
double range) {
}

View File

@@ -1,5 +0,0 @@
package net.momirealms.craftengine.core.entity.projectile;
public enum ProjectileType {
TRIDENT
}

View File

@@ -3,7 +3,6 @@ package net.momirealms.craftengine.core.item;
import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta;
import net.momirealms.craftengine.core.entity.projectile.ProjectileType;
import net.momirealms.craftengine.core.item.equipment.ComponentBasedEquipment;
import net.momirealms.craftengine.core.item.equipment.Equipment;
import net.momirealms.craftengine.core.item.modifier.EquippableModifier;
@@ -408,9 +407,8 @@ public class ItemSettings {
Vector3f translation = ResourceConfigUtils.getAsVector3f(args.getOrDefault("translation", "0"), "translation");
Vector3f scale = ResourceConfigUtils.getAsVector3f(args.getOrDefault("scale", "1"), "scale");
Quaternionf rotation = ResourceConfigUtils.getAsQuaternionf(ResourceConfigUtils.get(args, "rotation"), "rotation");
ProjectileType type = Optional.ofNullable(args.get("type")).map(String::valueOf).map(it -> ProjectileType.valueOf(it.toUpperCase(Locale.ENGLISH))).orElse(null);
double range = ResourceConfigUtils.getAsDouble(args.getOrDefault("range", 1), "range");
return settings -> settings.projectileMeta(new ProjectileMeta(customTridentItemId, displayType, billboard, scale, translation, rotation, range, type));
return settings -> settings.projectileMeta(new ProjectileMeta(customTridentItemId, displayType, billboard, scale, translation, rotation, range));
}));
registerFactory("helmet", (value -> {
Map<String, Object> args = MiscUtils.castToMap(value, false);

View File

@@ -0,0 +1,27 @@
package net.momirealms.craftengine.core.pack.cache;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
public class AutoIdCache {
private final Map<String, Integer> forcedIds = new HashMap<>();
private final Map<String, Integer> cachedIds = new HashMap<>();
private final BitSet occupiedIds = new BitSet();
private int currentAutoId;
public AutoIdCache(int startIndex) {
this.currentAutoId = startIndex;
}
public boolean setForcedId(final String name, int index) {
if (this.occupiedIds.get(index)) {
return false;
}
this.occupiedIds.set(index);
this.forcedIds.put(name, index);
return true;
}
}

View File

@@ -123,6 +123,7 @@ public class Config {
protected int block$predict_breaking_interval;
protected double block$extended_interaction_range;
protected boolean block$chunk_relighter;
protected int block$serverside_blocks;
protected boolean recipe$enable;
protected boolean recipe$disable_vanilla_recipes$all;
@@ -134,21 +135,22 @@ public class Config {
protected boolean image$illegal_characters_filter$anvil;
protected boolean image$illegal_characters_filter$sign;
protected boolean image$illegal_characters_filter$book;
protected boolean image$intercept_packets$system_chat;
protected boolean image$intercept_packets$tab_list;
protected boolean image$intercept_packets$actionbar;
protected boolean image$intercept_packets$title;
protected boolean image$intercept_packets$bossbar;
protected boolean image$intercept_packets$container;
protected boolean image$intercept_packets$team;
protected boolean image$intercept_packets$scoreboard;
protected boolean image$intercept_packets$entity_name;
protected boolean image$intercept_packets$text_display;
protected boolean image$intercept_packets$armor_stand;
protected boolean image$intercept_packets$player_info;
protected boolean image$intercept_packets$set_score;
protected boolean image$intercept_packets$item;
protected boolean image$intercept_packets$advancement;
protected boolean network$intercept_packets$system_chat;
protected boolean network$intercept_packets$tab_list;
protected boolean network$intercept_packets$actionbar;
protected boolean network$intercept_packets$title;
protected boolean network$intercept_packets$bossbar;
protected boolean network$intercept_packets$container;
protected boolean network$intercept_packets$team;
protected boolean network$intercept_packets$scoreboard;
protected boolean network$intercept_packets$entity_name;
protected boolean network$intercept_packets$text_display;
protected boolean network$intercept_packets$armor_stand;
protected boolean network$intercept_packets$player_info;
protected boolean network$intercept_packets$set_score;
protected boolean network$intercept_packets$item;
protected boolean network$intercept_packets$advancement;
protected boolean item$client_bound_model;
protected boolean item$non_italic_tag;
@@ -392,6 +394,7 @@ public class Config {
block$predict_breaking_interval = Math.max(config.getInt("block.predict-breaking.interval", 10), 1);
block$extended_interaction_range = Math.max(config.getDouble("block.predict-breaking.extended-interaction-range", 0.5), 0.0);
block$chunk_relighter = config.getBoolean("block.chunk-relighter", true);
block$serverside_blocks = config.getInt("block.serverside-blocks", 2000);
// recipe
recipe$enable = config.getBoolean("recipe.enable", true);
@@ -405,21 +408,22 @@ public class Config {
image$illegal_characters_filter$chat = config.getBoolean("image.illegal-characters-filter.chat", true);
image$illegal_characters_filter$command = config.getBoolean("image.illegal-characters-filter.command", true);
image$illegal_characters_filter$sign = config.getBoolean("image.illegal-characters-filter.sign", true);
image$intercept_packets$system_chat = config.getBoolean("image.intercept-packets.system-chat", true);
image$intercept_packets$tab_list = config.getBoolean("image.intercept-packets.tab-list", true);
image$intercept_packets$actionbar = config.getBoolean("image.intercept-packets.actionbar", true);
image$intercept_packets$title = config.getBoolean("image.intercept-packets.title", true);
image$intercept_packets$bossbar = config.getBoolean("image.intercept-packets.bossbar", true);
image$intercept_packets$container = config.getBoolean("image.intercept-packets.container", true);
image$intercept_packets$team = config.getBoolean("image.intercept-packets.team", true);
image$intercept_packets$scoreboard = config.getBoolean("image.intercept-packets.scoreboard", true);
image$intercept_packets$entity_name = config.getBoolean("image.intercept-packets.entity-name", false);
image$intercept_packets$text_display = config.getBoolean("image.intercept-packets.text-display", true);
image$intercept_packets$armor_stand = config.getBoolean("image.intercept-packets.armor-stand", true);
image$intercept_packets$player_info = config.getBoolean("image.intercept-packets.player-info", true);
image$intercept_packets$set_score = config.getBoolean("image.intercept-packets.set-score", true);
image$intercept_packets$item = config.getBoolean("image.intercept-packets.item", true);
image$intercept_packets$advancement = config.getBoolean("image.intercept-packets.advancement", true);
network$intercept_packets$system_chat = config.getBoolean("network.intercept-packets.system-chat", true);
network$intercept_packets$tab_list = config.getBoolean("network.intercept-packets.tab-list", true);
network$intercept_packets$actionbar = config.getBoolean("network.intercept-packets.actionbar", true);
network$intercept_packets$title = config.getBoolean("network.intercept-packets.title", true);
network$intercept_packets$bossbar = config.getBoolean("network.intercept-packets.bossbar", true);
network$intercept_packets$container = config.getBoolean("network.intercept-packets.container", true);
network$intercept_packets$team = config.getBoolean("network.intercept-packets.team", true);
network$intercept_packets$scoreboard = config.getBoolean("network.intercept-packets.scoreboard", true);
network$intercept_packets$entity_name = config.getBoolean("network.intercept-packets.entity-name", false);
network$intercept_packets$text_display = config.getBoolean("network.intercept-packets.text-display", true);
network$intercept_packets$armor_stand = config.getBoolean("network.intercept-packets.armor-stand", true);
network$intercept_packets$player_info = config.getBoolean("network.intercept-packets.player-info", true);
network$intercept_packets$set_score = config.getBoolean("network.intercept-packets.set-score", true);
network$intercept_packets$item = config.getBoolean("network.intercept-packets.item", true);
network$intercept_packets$advancement = config.getBoolean("network.intercept-packets.advancement", true);
// emoji
emoji$contexts$chat = config.getBoolean("emoji.contexts.chat", true);
@@ -477,6 +481,10 @@ public class Config {
return instance.metrics;
}
public static int serverSideBlocks() {
return instance.block$serverside_blocks;
}
public static boolean filterConfigurationPhaseDisconnect() {
return instance.filterConfigurationPhaseDisconnect;
}
@@ -729,63 +737,63 @@ public class Config {
}
public static boolean interceptSystemChat() {
return instance.image$intercept_packets$system_chat;
return instance.network$intercept_packets$system_chat;
}
public static boolean interceptTabList() {
return instance.image$intercept_packets$tab_list;
return instance.network$intercept_packets$tab_list;
}
public static boolean interceptActionBar() {
return instance.image$intercept_packets$actionbar;
return instance.network$intercept_packets$actionbar;
}
public static boolean interceptTitle() {
return instance.image$intercept_packets$title;
return instance.network$intercept_packets$title;
}
public static boolean interceptBossBar() {
return instance.image$intercept_packets$bossbar;
return instance.network$intercept_packets$bossbar;
}
public static boolean interceptContainer() {
return instance.image$intercept_packets$container;
return instance.network$intercept_packets$container;
}
public static boolean interceptTeam() {
return instance.image$intercept_packets$team;
return instance.network$intercept_packets$team;
}
public static boolean interceptEntityName() {
return instance.image$intercept_packets$entity_name;
return instance.network$intercept_packets$entity_name;
}
public static boolean interceptScoreboard() {
return instance.image$intercept_packets$scoreboard;
return instance.network$intercept_packets$scoreboard;
}
public static boolean interceptTextDisplay() {
return instance.image$intercept_packets$text_display;
return instance.network$intercept_packets$text_display;
}
public static boolean interceptArmorStand() {
return instance.image$intercept_packets$armor_stand;
return instance.network$intercept_packets$armor_stand;
}
public static boolean interceptPlayerInfo() {
return instance.image$intercept_packets$player_info;
return instance.network$intercept_packets$player_info;
}
public static boolean interceptSetScore() {
return instance.image$intercept_packets$set_score;
return instance.network$intercept_packets$set_score;
}
public static boolean interceptItem() {
return instance.image$intercept_packets$item;
return instance.network$intercept_packets$item;
}
public static boolean interceptAdvancement() {
return instance.image$intercept_packets$advancement;
return instance.network$intercept_packets$advancement;
}
public static boolean predictBreaking() {

View File

@@ -5,8 +5,6 @@ import net.momirealms.craftengine.core.plugin.context.*;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
@@ -16,12 +14,12 @@ import java.util.List;
import java.util.Map;
public class ActionBarFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final TextProvider message;
private final String message;
private final PlayerSelector<CTX> selector;
public ActionBarFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, TextProvider messages) {
public ActionBarFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, String message) {
super(predicates);
this.message = messages;
this.message = message;
this.selector = selector;
}
@@ -29,12 +27,12 @@ public class ActionBarFunction<CTX extends Context> extends AbstractConditionalF
public void runInternal(CTX ctx) {
if (this.selector == null) {
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
it.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(ctx), ctx.tagResolvers()));
it.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message, ctx.tagResolvers()));
});
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
viewer.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(relationalContext), relationalContext.tagResolvers()));
viewer.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message, relationalContext.tagResolvers()));
}
}
}
@@ -53,7 +51,7 @@ public class ActionBarFunction<CTX extends Context> extends AbstractConditionalF
@Override
public Function<CTX> create(Map<String, Object> arguments) {
String message = ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "actionbar", "message"), "warning.config.function.actionbar.missing_actionbar");
return new ActionBarFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), TextProviders.fromString(message));
return new ActionBarFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), message);
}
}
}

View File

@@ -5,8 +5,6 @@ import net.momirealms.craftengine.core.plugin.context.*;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
@@ -17,11 +15,11 @@ import java.util.List;
import java.util.Map;
public class MessageFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final List<TextProvider> messages;
private final List<String> messages;
private final PlayerSelector<CTX> selector;
private final boolean overlay;
public MessageFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, List<TextProvider> messages, boolean overlay) {
public MessageFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, List<String> messages, boolean overlay) {
super(predicates);
this.messages = messages;
this.selector = selector;
@@ -32,15 +30,15 @@ public class MessageFunction<CTX extends Context> extends AbstractConditionalFun
public void runInternal(CTX ctx) {
if (this.selector == null) {
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
for (TextProvider c : this.messages) {
it.sendMessage(AdventureHelper.miniMessage().deserialize(c.get(ctx), ctx.tagResolvers()), this.overlay);
for (String c : this.messages) {
it.sendMessage(AdventureHelper.miniMessage().deserialize(c, ctx.tagResolvers()), this.overlay);
}
});
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
for (TextProvider c : this.messages) {
viewer.sendMessage(AdventureHelper.miniMessage().deserialize(c.get(relationalContext), relationalContext.tagResolvers()), this.overlay);
for (String c : this.messages) {
viewer.sendMessage(AdventureHelper.miniMessage().deserialize(c, relationalContext.tagResolvers()), this.overlay);
}
}
}
@@ -60,7 +58,7 @@ public class MessageFunction<CTX extends Context> extends AbstractConditionalFun
@Override
public Function<CTX> create(Map<String, Object> arguments) {
Object message = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "messages", "message"), "warning.config.function.command.missing_message");
List<TextProvider> messages = MiscUtils.getAsStringList(message).stream().map(TextProviders::fromString).toList();
List<String> messages = MiscUtils.getAsStringList(message);
boolean overlay = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("overlay", false), "overlay");
return new MessageFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), messages, overlay);
}

View File

@@ -6,8 +6,6 @@ import net.momirealms.craftengine.core.plugin.context.*;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.plugin.gui.GuiType;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.AdventureHelper;
@@ -24,9 +22,9 @@ import java.util.Optional;
public class OpenWindowFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final PlayerSelector<CTX> selector;
private final GuiType guiType;
private final TextProvider optionalTitle;
private final String optionalTitle;
public OpenWindowFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, GuiType guiType, TextProvider optionalTitle) {
public OpenWindowFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, GuiType guiType, String optionalTitle) {
super(predicates);
this.selector = selector;
this.guiType = guiType;
@@ -39,7 +37,7 @@ public class OpenWindowFunction<CTX extends Context> extends AbstractConditional
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
CraftEngine.instance().guiManager().openInventory(it, this.guiType);
if (this.optionalTitle != null) {
CraftEngine.instance().guiManager().updateInventoryTitle(it, AdventureHelper.miniMessage().deserialize(this.optionalTitle.get(ctx), ctx.tagResolvers()));
CraftEngine.instance().guiManager().updateInventoryTitle(it, AdventureHelper.miniMessage().deserialize(this.optionalTitle, ctx.tagResolvers()));
}
});
} else {
@@ -47,7 +45,7 @@ public class OpenWindowFunction<CTX extends Context> extends AbstractConditional
CraftEngine.instance().guiManager().openInventory(viewer, this.guiType);
if (this.optionalTitle != null) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
CraftEngine.instance().guiManager().updateInventoryTitle(viewer, AdventureHelper.miniMessage().deserialize(this.optionalTitle.get(relationalContext), relationalContext.tagResolvers()));
CraftEngine.instance().guiManager().updateInventoryTitle(viewer, AdventureHelper.miniMessage().deserialize(this.optionalTitle, relationalContext.tagResolvers()));
}
}
}
@@ -66,7 +64,7 @@ public class OpenWindowFunction<CTX extends Context> extends AbstractConditional
@Override
public Function<CTX> create(Map<String, Object> arguments) {
TextProvider title = Optional.ofNullable(arguments.get("title")).map(String::valueOf).map(TextProviders::fromString).orElse(null);
String title = Optional.ofNullable(arguments.get("title")).map(String::valueOf).orElse(null);
String rawType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("gui-type"), "warning.config.function.open_window.missing_gui_type");
try {
GuiType type = GuiType.valueOf(rawType.toUpperCase(Locale.ENGLISH));

View File

@@ -7,8 +7,6 @@ import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.Nullable;
@@ -18,14 +16,14 @@ import java.util.Map;
public class TitleFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final PlayerSelector<CTX> selector;
private final TextProvider main;
private final TextProvider sub;
private final String main;
private final String sub;
private final NumberProvider fadeIn;
private final NumberProvider stay;
private final NumberProvider fadeOut;
public TitleFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector,
TextProvider main, TextProvider sub, NumberProvider fadeIn, NumberProvider stay, NumberProvider fadeOut) {
String main, String sub, NumberProvider fadeIn, NumberProvider stay, NumberProvider fadeOut) {
super(predicates);
this.selector = selector;
this.main = main;
@@ -39,16 +37,16 @@ public class TitleFunction<CTX extends Context> extends AbstractConditionalFunct
public void runInternal(CTX ctx) {
if (this.selector == null) {
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> it.sendTitle(
AdventureHelper.miniMessage().deserialize(this.main.get(ctx), ctx.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub.get(ctx), ctx.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.main, ctx.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub, ctx.tagResolvers()),
this.fadeIn.getInt(ctx), this.stay.getInt(ctx), this.fadeOut.getInt(ctx)
));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
viewer.sendTitle(
AdventureHelper.miniMessage().deserialize(this.main.get(relationalContext), relationalContext.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub.get(relationalContext), relationalContext.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.main, relationalContext.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub, relationalContext.tagResolvers()),
this.fadeIn.getInt(relationalContext), this.stay.getInt(relationalContext), this.fadeOut.getInt(relationalContext)
);
}
@@ -73,8 +71,7 @@ public class TitleFunction<CTX extends Context> extends AbstractConditionalFunct
NumberProvider fadeIn = NumberProviders.fromObject(arguments.getOrDefault("fade-in", 10));
NumberProvider stay = NumberProviders.fromObject(arguments.getOrDefault("stay", 20));
NumberProvider fadeOut = NumberProviders.fromObject(arguments.getOrDefault("fade-out", 5));
return new TitleFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()),
TextProviders.fromString(title), TextProviders.fromString(subtitle), fadeIn, stay, fadeOut);
return new TitleFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), title, subtitle, fadeIn, stay, fadeOut);
}
}
}

View File

@@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G
# Project settings
# Rule: [major update].[feature update].[bug fix]
project_version=0.0.63.3
project_version=0.0.63.4
config_version=46
lang_version=30
project_group=net.momirealms