This commit is contained in:
yaohunya 2025-08-10 04:54:05 +08:00
parent d1fc0be07f
commit 228725300e
10 changed files with 57 additions and 122 deletions

View File

@ -13,7 +13,6 @@ import com.yaohun.demonskills.gui.SkillsGui;
import com.yaohun.demonskills.listener.PlayerListener;
import com.yaohun.demonskills.listener.SkillKeyListener;
import com.yaohun.demonskills.manage.PlayerManager;
import com.yaohun.demonskills.util.AsyncPlayerDataSaver;
import com.yaohun.demonskills.util.CDTimeAPI;
import me.Demon.DemonPlugin.DemonAPI;
import org.bukkit.Bukkit;
@ -50,8 +49,6 @@ public class SkillsMain extends JavaPlugin {
}
Bukkit.getConsoleSender().sendMessage("§b[魂式技能] §a插件成功载入Server");
Bukkit.getConsoleSender().sendMessage("§b[魂式技能] §a妖魂QQ: §b1763917516");
new AsyncPlayerDataSaver(this);
}
@Override

View File

@ -1,10 +1,8 @@
package com.yaohun.demonskills.data;
import com.yaohun.demonskills.SkillsMain;
import com.yaohun.demonskills.core.Skill;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.data.NbtItem;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@ -13,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class PlayerData {
@ -63,38 +60,20 @@ public class PlayerData {
}
}
public void SavePlayerData() {
// 1. 主线程内抓取快照避免异步直接访问成员变量
int magicMaxSnapshot = this.magicMax;
// 复制键盘映射注意深拷贝 ItemStack
Map<Integer, ItemStack> keyboardSnapshot = new HashMap<>();
for (Map.Entry<Integer, ItemStack> entry : this.keyBoardStackMap.entrySet()) {
keyboardSnapshot.put(entry.getKey(), entry.getValue().clone());
public void SavePlayerData(){
this.configuration.set("Magic",this.magicMax);
this.configuration.set("KeyBoard",null);
for (Integer keyBoard : keyBoardStackMap.keySet()) {
ItemStack keyBoardStack = keyBoardStackMap.get(keyBoard);
this.configuration.set("KeyBoard."+keyBoard,keyBoardStack);
}
// 创建配置快照
File fileSnapshot = this.file;
YamlConfiguration configSnapshot = new YamlConfiguration();
// 2. 异步保存使用快照对象避免线程冲突
Bukkit.getScheduler().runTaskAsynchronously(SkillsMain.inst(), () -> {
configSnapshot.set("Magic", magicMaxSnapshot);
configSnapshot.set("KeyBoard", null);
for (Map.Entry<Integer, ItemStack> entry : keyboardSnapshot.entrySet()) {
configSnapshot.set("KeyBoard." + entry.getKey(), entry.getValue());
}
try {
configSnapshot.save(fileSnapshot);
this.configuration.save(this.file);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
});
}
public String getPlayerName() {
return name;
}

View File

@ -72,7 +72,8 @@ public class StoneEquipGui implements Listener {
player.closeInventory();
PlayerManager playerManager = SkillsMain.getPlayerManager();
PlayerData playerData = playerManager.getPlayerData(playerName);
// 设置完成后保存玩家数据
playerData.SavePlayerData();
SkillsGui.checkItemSetBindKeyBoard(playerData, skillStone, rawSlot);
player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
new BukkitRunnable() {

View File

@ -68,44 +68,44 @@ public class Skill_赤焰旋风斩 {
new DelayComponent(8L, Arrays.asList(
new PotionEffectComponent(PotionEffectType.SLOW,70,2),
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L, Arrays.asList(
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L, Arrays.asList(
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L, Arrays.asList(
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L, Arrays.asList(
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L,Arrays.asList(
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L,Arrays.asList(
new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5,true)),
new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
new DelayComponent(10L,Arrays.asList(
// 播放爆炸音效
new SoundComponent("ENTITY_GENERIC_EXPLODE",1.0f,1.0f),
// 播放 跟随岩浆粒子 5次
new ParticlesComponent(Particle.LAVA,5,0.2,5),
new ProjectileAdvanceComponent(0.6,0.8,new NearestEnemiesSelector(3))
new ProjectileAdvanceComponent(0.6,0.8,new NearestEnemiesSelector(3,true))
))
))
))

View File

@ -9,7 +9,6 @@ import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
import com.yaohun.demonskills.component.particles.ParticlesComponent;
import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
import com.yaohun.demonskills.core.Skill;
import com.yaohun.demonskills.data.PlayerData;
import com.yaohun.demonskills.manage.PlayerManager;

View File

@ -92,7 +92,7 @@ public class Skill_逐影破空斩 {
new PotionEffectComponent(PotionEffectType.SLOW,10,5,new ConeEnemiesSelector(10.0,45)),
new SoundComponent("挥舞剑气1.ogg", 0.6f, 1.0f),
new DelayComponent(8L,Arrays.asList(
new ProjectileAdvanceComponent(-2,0.2,new ConeEnemiesSelector(10.0,45)),
new ProjectileAdvanceComponent(-2,0.2,new ConeEnemiesSelector(10.0,45,true)),
new DamageComponent(damage * 0.2,new ConeEnemiesSelector(10.0,45))
))
))

View File

@ -18,12 +18,19 @@ public class ConeEnemiesSelector implements TargetSelector {
private final double radius; // 范围
private final double angle; // 角度 60°
private int limit = -1;
private boolean playerImmune = false;
public ConeEnemiesSelector(double radius, double angle) {
this.radius = radius;
this.angle = angle;
}
public ConeEnemiesSelector(double radius, double angle,boolean playerImmune) {
this.radius = radius;
this.angle = angle;
this.playerImmune = playerImmune;
}
public ConeEnemiesSelector(double radius, double angle, int limit) {
this.radius = radius;
this.angle = angle;
@ -40,6 +47,11 @@ public class ConeEnemiesSelector implements TargetSelector {
if (!(entity instanceof LivingEntity) || entity.equals(caster)) continue;
if (entity instanceof ArmorStand) continue;
if (CitizensAPI.getNPCRegistry().isNPC(entity)) continue;
if(playerImmune){
if(entity instanceof Player){
continue;
}
}
Vector toTarget = entity.getLocation().toVector().subtract(eyeVec);
toTarget.setY(0);

View File

@ -10,15 +10,23 @@ import org.bukkit.entity.Player;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class NearestEnemiesSelector implements TargetSelector {
private final double radius;
private int limit = 0;
// 是否让玩家免疫不作为目标
private boolean playerImmune = false;
public NearestEnemiesSelector(double radius) {
this.radius = radius;
}
public NearestEnemiesSelector(double radius,boolean playerImmune) {
this.radius = radius;
this.playerImmune = playerImmune;
}
public NearestEnemiesSelector(double radius, int limit) {
this.radius = radius;
this.limit = limit;
@ -26,20 +34,20 @@ public class NearestEnemiesSelector implements TargetSelector {
@Override
public List<Entity> selectTargets(Player caster) {
if(limit != 0) {
return caster.getNearbyEntities(radius, radius, radius).stream()
Stream<Entity> stream = caster.getNearbyEntities(radius, radius, radius).stream()
.filter(e -> !(e instanceof ArmorStand))
.filter(e -> e instanceof LivingEntity && !e.equals(caster))
.filter(e -> !CitizensAPI.getNPCRegistry().isNPC(e)) // 排除NPC
.sorted(Comparator.comparingDouble(e -> e.getLocation().distanceSquared(caster.getLocation())))
.limit(limit)
.collect(Collectors.toList());
} else {
return caster.getNearbyEntities(radius, radius, radius).stream()
.filter(e -> !(e instanceof ArmorStand))
.filter(e -> !CitizensAPI.getNPCRegistry().isNPC(e)) // 排除NPC
.filter(e -> e instanceof LivingEntity && !e.equals(caster))
.collect(Collectors.toList());
.filter(e -> !CitizensAPI.getNPCRegistry().isNPC(e)); // 排除NPC
if (playerImmune) {
stream = stream.filter(e -> !(e instanceof Player)); // 玩家免疫
}
stream = stream.sorted(Comparator.comparingDouble(e -> e.getLocation().distanceSquared(caster.getLocation())));
if (limit > 0) {
stream = stream.limit(limit);
}
return stream.collect(Collectors.toList());
}
}

View File

@ -1,61 +0,0 @@
package com.yaohun.demonskills.util;
import com.yaohun.demonskills.SkillsMain;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.List;
public class AsyncPlayerDataSaver {
private final SkillsMain plugin;
private final int batchSize = 5;
private final int delayBetweenBatches = 20; // 每批延迟1秒20tick
public AsyncPlayerDataSaver(SkillsMain plugin) {
this.plugin = plugin;
startAutoSave();
}
public void startAutoSave() {
new BukkitRunnable() {
@Override
public void run() {
List<Player> onlinePlayers = new ArrayList<>(Bukkit.getOnlinePlayers());
if (onlinePlayers.isEmpty()) {
return;
}
int total = onlinePlayers.size();
int batches = (int) Math.ceil((double) total / batchSize);
for (int i = 0; i < batches; i++) {
final int batchIndex = i;
new BukkitRunnable() {
@Override
public void run() {
int start = batchIndex * batchSize;
int end = Math.min(start + batchSize, total);
for (int j = start; j < end; j++) {
Player p = onlinePlayers.get(j);
Bukkit.getScheduler().runTaskAsynchronously(SkillsMain.inst(), () -> {
savePlayerData(p); // 你的保存方法异步安全
});
}
}
}.runTaskLater(SkillsMain.inst(), (long) delayBetweenBatches * i);
}
}
}.runTaskTimer(SkillsMain.inst(), 20 * 60 * 10, 20 * 60 * 10); // 每5分钟执行一次
}
private void savePlayerData(Player player) {
// TODO: 将你的数据写入YAML或数据库
// 注意线程安全例如避免直接操作 Bukkit API只处理内存数据快照
}
}

View File

@ -1,6 +1,6 @@
name: DemonSkills
main: com.yaohun.demonskills.SkillsMain
version: 1.3.6
version: 1.3.8
depend:
- DemonAPI
commands: