Skip to content

Commit

Permalink
enhance: 改进技能存储
Browse files Browse the repository at this point in the history
    - 将配置根据伪装ID分为不同的小文件存储,就像基岩版的行为包那样
  • Loading branch information
MATRIX-feather committed Oct 11, 2024
1 parent 87b6f20 commit 9db780b
Show file tree
Hide file tree
Showing 19 changed files with 546 additions and 631 deletions.
4 changes: 3 additions & 1 deletion src/main/java/xyz/nifeather/morph/MorphManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.nifeather.morph.abilities.AbilityManager;
import xyz.nifeather.morph.abilities.MorphAbility;
import xyz.nifeather.morph.backends.DisguiseBackend;
import xyz.nifeather.morph.backends.DisguiseWrapper;
import xyz.nifeather.morph.backends.WrapperAttribute;
Expand Down Expand Up @@ -884,7 +886,7 @@ private DisguiseBuildResult buildDisguise(MorphParameters parameters, DisguiseMe
}

@Resolved
private VanillaMessageStore vanillaMessageStore;
private AbilityManager abilityManager;

private void postBuildDisguise(DisguiseBuildResult result,
MorphParameters parameters,
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/xyz/nifeather/morph/MorphPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import xyz.nifeather.morph.network.multiInstance.MultiInstanceService;
import xyz.nifeather.morph.network.server.MorphClientHandler;
import xyz.nifeather.morph.skills.MorphSkillHandler;
import xyz.nifeather.morph.storage.skill.SkillAbilityConfigurationStore;
import xyz.nifeather.morph.storage.skill.SkillsConfigurationStoreNew;
import xyz.nifeather.morph.transforms.Transformer;
import xyz.nifeather.morph.updates.UpdateHandler;
import xiamomc.pluginbase.Command.CommandHelper;
Expand Down Expand Up @@ -219,7 +219,7 @@ public void onEnable()

dependencyManager.cache(cmdHelper = new MorphCommandManager());

dependencyManager.cache(new SkillAbilityConfigurationStore());
dependencyManager.cache(new SkillsConfigurationStoreNew());

dependencyManager.cache(new MessageUtils());

Expand Down
112 changes: 53 additions & 59 deletions src/main/java/xyz/nifeather/morph/abilities/AbilityManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,22 @@
import xyz.nifeather.morph.abilities.impl.onAttack.ExtraKnockbackAbility;
import xyz.nifeather.morph.abilities.impl.onAttack.PotionOnAttackAbility;
import xyz.nifeather.morph.events.api.lifecycle.AbilitiesFinishedInitializeEvent;
import xyz.nifeather.morph.storage.skill.SkillAbilityConfiguration;
import xyz.nifeather.morph.storage.skill.SkillAbilityConfigurationStore;
import xyz.nifeather.morph.storage.skill.ISkillOption;
import xiamomc.pluginbase.Annotations.Initializer;
import xiamomc.pluginbase.Annotations.Resolved;
import xyz.nifeather.morph.storage.skill.SkillsConfigurationStoreNew;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

public class AbilityManager extends MorphPluginObject
{
private final List<IMorphAbility<?>> registedAbilities = new ObjectArrayList<>();

@Resolved
private SkillAbilityConfigurationStore store;

private boolean initalizeDone;
private SkillsConfigurationStoreNew store;

/**
* 注册一个被动技能
Expand All @@ -50,32 +49,6 @@ public boolean registerAbility(IMorphAbility<?> ability)

registedAbilities.add(ability);

//SkillConfigurationStore只会在重载时给已经注册的被动添加设置
//所有在重载/初始化完成后加入的技能都需要我们手动查询
if (initalizeDone)
{
//添加设置
store.getConfiguredSkills().forEach((configuration, skill) ->
{
if (!ability.setOptionGeneric(configuration.getIdentifier(), configuration.getAbilityOptions(ability)))
{
logger.warn("Unable to initialize skill configuration for " + configuration.getIdentifier() + " -> " + ability.getIdentifier());
}
});

//添加到map中所有符合条件的技能配置里
var id = ability.getIdentifier().asString();
var matchingConfigs = configToAbilitiesMap.entrySet()
.stream().filter(e -> e.getKey().getAbilitiyIdentifiers().contains(id)).toList();

matchingConfigs.forEach(c ->
{
var list = configToAbilitiesMap.get(c.getKey());

if (!list.contains(ability)) list.add(ability);
});
}

Bukkit.getPluginManager().registerEvents(ability, plugin);
return true;
}
Expand Down Expand Up @@ -140,52 +113,84 @@ private void load()
new SpiderAbility()
));

initalizeDone = true;

Bukkit.getPluginManager().callEvent(new AbilitiesFinishedInitializeEvent(this));
}

@NotNull
public Map<NamespacedKey, ISkillOption> getOptionsFor(String disguiseIdentifier)
{
var configuration = store.get(disguiseIdentifier);
if (configuration == null) return new Object2ObjectOpenHashMap<>();

Map<NamespacedKey, ISkillOption> optionMap = new ConcurrentHashMap<>();
configuration.getAbilitiyIdentifiers().forEach(a ->
{
var idKey = NamespacedKey.fromString(a);

if (idKey == null)
{
logger.warn("Invalid ability ID: %s".formatted(a));
return;
}

var abilityInstance = this.getAbility(idKey);
if (abilityInstance == null) return;

optionMap.put(idKey, configuration.getAbilityOptions(abilityInstance));
});

return optionMap;
}

@Nullable
public IMorphAbility<?> getAbility(@Nullable NamespacedKey key)
public IMorphAbility<?> getAbility(@Nullable NamespacedKey abilityIdentifier)
{
if (key == null) return null;
if (abilityIdentifier == null) return null;

var val = registedAbilities.stream()
.filter(a -> a.getIdentifier().equals(key)).findFirst().orElse(null);
.filter(a -> a.getIdentifier().equals(abilityIdentifier)).findFirst().orElse(null);

if (val == null)
logger.warn("Unknown ability: " + key.asString());
logger.warn("Unknown ability: " + abilityIdentifier.asString());

return val;
}

private final Map<SkillAbilityConfiguration, List<IMorphAbility<?>>> configToAbilitiesMap = new Object2ObjectOpenHashMap<>();

/**
* 为某个伪装ID获取被动技能
*
* @param id 伪装ID
* @param disguiseIdentifier 伪装ID
* @return 被动技能列表
*/
@NotNull
public List<IMorphAbility<?>> getAbilitiesFor(String id)
public List<IMorphAbility<?>> getAbilitiesFor(String disguiseIdentifier)
{
return this.getAbilitiesFor(id, false);
return this.getAbilitiesFor(disguiseIdentifier, false);
}

/**
* @param disguiseIdentifier 目标伪装
* @param noFallback 是否要搜索命名空间的默认配置
*/
@NotNull
public List<IMorphAbility<?>> getAbilitiesFor(String id, boolean noFallback)
public List<IMorphAbility<?>> getAbilitiesFor(String disguiseIdentifier, boolean noFallback)
{
var entry = configToAbilitiesMap.entrySet().stream()
.filter(s -> s.getKey().getIdentifier().equals(id)).findFirst().orElse(null);
var configuration = store.get(disguiseIdentifier);

if (entry != null)
if (configuration != null)
{
return entry.getValue();
List<IMorphAbility<?>> abilities = new ObjectArrayList<>();
configuration.getAbilitiyIdentifiers().forEach(id ->
{
var instance = this.getAbility(NamespacedKey.fromString(id));
if (instance != null) abilities.add(instance);
});

return abilities;
}
else if (!noFallback)
{
var idSpilt = id.split(":", 2);
var idSpilt = disguiseIdentifier.split(":", 2);
if (idSpilt.length < 1) return List.of();

var idNew = idSpilt[0] + ":" + MorphManager.disguiseFallbackName;
Expand All @@ -195,15 +200,4 @@ else if (!noFallback)

return List.of();
}

public void setAbilities(SkillAbilityConfiguration configuration, List<IMorphAbility<?>> abilities)
{
configToAbilitiesMap.put(configuration, abilities);
}

public void clearAbilities()
{
configToAbilitiesMap.clear();
registedAbilities.forEach(IMorphAbility::clearOptions);
}
}
28 changes: 27 additions & 1 deletion src/main/java/xyz/nifeather/morph/abilities/AbilityUpdater.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@
import xyz.nifeather.morph.config.MorphConfigManager;
import xyz.nifeather.morph.misc.DisguiseState;
import xyz.nifeather.morph.misc.permissions.CommonPermissions;
import xyz.nifeather.morph.storage.skill.IAbilityConfigLookup;
import xyz.nifeather.morph.utilities.PermissionUtils;
import xiamomc.pluginbase.Annotations.Initializer;
import xiamomc.pluginbase.Bindables.Bindable;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class AbilityUpdater extends MorphPluginObject
public class AbilityUpdater extends MorphPluginObject implements IAbilityConfigLookup
{
@NotNull
private final DisguiseState parentState;
Expand Down Expand Up @@ -255,4 +258,27 @@ public static boolean hasPermissionFor(IMorphAbility<?> ability, DisguiseState s
var singleAbilityPerm = CommonPermissions.abilityPermissionOf(ability.getIdentifier().asString(), state.getDisguiseIdentifier());
return PermissionUtils.hasPermission(state.getPlayer(), singleAbilityPerm, true);
}

//region IAbilityConfigLookup

private final Map<String, Object> abilityConfigMap = new ConcurrentHashMap<>();

@Override
@Nullable
public <X> X lookupAbilityConfig(String identifier, Class<X> expectedClass)
{
var val = abilityConfigMap.getOrDefault(identifier, null);
if (val == null) return null;

if (expectedClass.isInstance(val)) return (X) val;
else return null;
}

@Override
public void setAbilityConfig(String identifier, Object config)
{
abilityConfigMap.put(identifier, config);
}

//endregion IAbilityConfigLookup
}
30 changes: 10 additions & 20 deletions src/main/java/xyz/nifeather/morph/abilities/IMorphAbility.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.LoggerFactory;
import xyz.nifeather.morph.misc.DisguiseState;
import xyz.nifeather.morph.storage.skill.ISkillOption;

Expand Down Expand Up @@ -81,36 +80,27 @@ public default boolean handle(Player player, DisguiseState state)
*
* @return 操作是否成功
*/
public boolean setOption(@NotNull String disguiseIdentifier, @Nullable T option);
public default boolean setOption(@NotNull String disguiseIdentifier, @Nullable T option)
{
return false;
}

/**
* @apiNote 内部轮子
* @return option是否可以cast为目标option,为null则返回true并略过,反之返回setOption的结果
*/
@Deprecated(forRemoval = true)
@ApiStatus.Internal
public default boolean setOptionGeneric(String disguiseIdentifier, ISkillOption option)
{
T castedOption;

if (option == null)
return true;

try
{
castedOption = (T) option;
}
catch (ClassCastException e)
{
LoggerFactory.getLogger("morph").error("添加设置时出现问题: " + e.getMessage());
e.printStackTrace();
return false;
}

return setOption(disguiseIdentifier, castedOption);
return false;
}

/**
* 清除此被动的所有设置
*/
public void clearOptions();
@Deprecated(forRemoval = true)
public default void clearOptions()
{
}
}
26 changes: 1 addition & 25 deletions src/main/java/xyz/nifeather/morph/abilities/MorphAbility.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package xyz.nifeather.morph.abilities;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -104,11 +103,7 @@ public T getDefaultOption()
@Nullable
protected T getOptionFor(DisguiseState state)
{
return getOr(
() -> optionMap.get(state.getDisguiseIdentifier()),
Objects::nonNull,
() -> optionMap.get(state.skillLookupIdentifier())
);
return state.getAbilityUpdater().lookupAbilityConfig(this.getIdentifier().asString(), (Class<T>)getDefaultOption().getClass());
}

public interface Returner<R>
Expand All @@ -133,23 +128,4 @@ protected <R> R getOr(Returner<R> value, Predicate<R> p, Returner<R> fallbackVal
else
return fallbackValue.apply();
}

protected final Map<String, T> optionMap = new Object2ObjectOpenHashMap<>();

@Override
public boolean setOption(@NotNull String disguiseIdentifier, @Nullable T option)
{
if (option == null)
return false;

optionMap.put(disguiseIdentifier, option);

return true;
}

@Override
public void clearOptions()
{
optionMap.clear();
}
}
10 changes: 5 additions & 5 deletions src/main/java/xyz/nifeather/morph/abilities/impl/FlyAbility.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public boolean handle(Player player, DisguiseState state)
if (gameMode == GameType.CREATIVE || gameMode == GameType.SPECTATOR)
return super.handle(player, state);

var option = optionMap.get(state.skillLookupIdentifier());
var option = this.getOptionFor(state);

var worldName = player.getWorld().getName();
var allowFlightConditions = player.getFoodLevel() > option.getMinimumHunger()
Expand Down Expand Up @@ -184,11 +184,11 @@ public boolean revokeFromPlayer(Player player, DisguiseState state)
return new FlyOption();
}

public float getTargetFlySpeed(String identifier)
public float getTargetFlySpeed(DisguiseState state)
{
if (identifier == null) return Float.NaN;
if (state == null) return Float.NaN;

var value = optionMap.getOrDefault(identifier, null);
var value = this.getOptionFor(state);

if (value != null)
return value.getFlyingSpeed();
Expand All @@ -204,7 +204,7 @@ public boolean updateFlyingState(DisguiseState state)

if (player.getGameMode() != GameMode.SPECTATOR)
{
float speed = getTargetFlySpeed(state.skillLookupIdentifier());
float speed = getTargetFlySpeed(state);

speed = Float.isNaN(speed) ? 0.1f : MathUtils.clamp(-1f, 1f, speed);

Expand Down
Loading

0 comments on commit 9db780b

Please sign in to comment.