Closed heartalborada-del closed 2 years ago
想了一下,其实可以在关闭插件的时候保存
稍微写了下,应该没啥大的毛病
好家伙,效率拉满了属于是。 看代码应该没啥问题,如果方便的话开个pr我merge进来吧( 肥肠感谢您的贡献
好家伙,效率拉满了属于是。 看代码应该没啥问题,如果方便的话开个pr我merge进来吧( 肥肠感谢您的贡献
我现在在整洞穴检测 (bbs上面的矿洞里面缺氧的功能我服玩家提出来的)
那个可能得稍微改下框架,现在用enableworld可能不太够,可能得每个世界记录个type,type 用来表示世界是完全有氧(原版)/ 洞穴无氧,其余有氧 / 完全无氧,这三种类型。
关于探测洞穴,我目前没有什么特别好的idea,可能还是得检测高度,高度低于海平面一定程度的直接钦定为洞穴环境。(mabye?)但这样没法区分天然结构和人工结构
那个可能得稍微改下框架,现在用enableworld可能不太够,可能得每个世界记录个type,type 用来表示世界是完全有氧(原版)/ 洞穴无氧,其余有氧 / 完全无氧,这三种类型。
关于探测洞穴,我目前没有什么特别好的idea,可能还是得检测高度,高度低于海平面一定程度的直接钦定为洞穴环境。(mabye?)但这样没法区分天然结构和人工结构
我现在的想法是,遍历玩家周围11*11*11的范围,判断是否是“洞穴方块”并且方块离最高方块相差一定距离,然后大于某个数值就判定为洞穴,也确实无法区分天然和人工结构
11*11*11
的空间其实也不算小了,如果检查频率高的话我感觉可能会占用太多算力。但是我思来想去,总感觉地下结构都算做洞穴也没啥毛病。就算是人工结构一样会有缺氧的现象存在,需要长期使用的人工地下结构本来就应该补充氧气(在这里对应氧气室)。在这种基础上,直接检测高度也许是个好主意
11*11*11
的空间其实也不算小了,如果检查频率高的话我感觉可能会占用太多算力。但是我思来想去,总感觉地下结构都算做洞穴也没啥毛病。就算是人工结构一样会有缺氧的现象存在,需要长期使用的人工地下结构本来就应该补充氧气(在这里对应氧气室)。在这种基础上,直接检测高度也许是个好主意
这个是我目前写的检测,监听的是PlayerMoveEvent
public static boolean checkIsOnCave(Location center) {
int count = 0;
World w = center.getWorld();
float version = Util.GetServerVersion();
int min = version < 1.18 ? 0 : -64; //1.14的api没看到World.getMinHeight的实现
int cx = center.getBlockX(), cy = center.getBlockY(), cz = center.getBlockZ();
for(int i = 0;i <= 1331;i++) {
int x = i%11 + cx - 5, y = i/11%11 + cy -5, z = i/11/11%11 +cz -5;
if(y > w.getMaxHeight() || y < -64 || y < min) continue;
Location lo = new Location(w,x,y,z);
Block ch = lo.getBlock();
int hy = w.getHighestBlockAt(lo).getY();
if(ch.isEmpty()) continue;
if(ch.getLightFromSky() == 15) continue;
if(lo.getBlock().getType() == Material.STONE && hy - y > 20) count++;
if(count >= 333) return true;
}
return false;
}
11*11*11
的空间其实也不算小了,如果检查频率高的话我感觉可能会占用太多算力。但是我思来想去,总感觉地下结构都算做洞穴也没啥毛病。就算是人工结构一样会有缺氧的现象存在,需要长期使用的人工地下结构本来就应该补充氧气(在这里对应氧气室)。在这种基础上,直接检测高度也许是个好主意这个是我目前写的检测,监听的是PlayerMoveEvent
public static boolean checkIsOnCave(Location center) { int count = 0; World w = center.getWorld(); float version = Util.GetServerVersion(); int min = version < 1.18 ? 0 : -64; //1.14的api没看到World.getMinHeight的实现 int cx = center.getBlockX(), cy = center.getBlockY(), cz = center.getBlockZ(); for(int i = 0;i <= 1331;i++) { int x = i%11 + cx - 5, y = i/11%11 + cy -5, z = i/11/11%11 +cz -5; if(y > w.getMaxHeight() || y < -64 || y < min) continue; Location lo = new Location(w,x,y,z); Block ch = lo.getBlock(); int hy = w.getHighestBlockAt(lo).getY(); if(ch.isEmpty()) continue; if(ch.getLightFromSky() == 15) continue; if(lo.getBlock().getType() == Material.STONE && hy - y > 20) count++; if(count >= 333) return true; } return false; }
跑了下图,感觉性能影响不大 Timings
如果是在moveevent的话,加个基于玩家的时间戳吧,最多两秒一次检测什么的,要不玩家多起来可能还真会卡。 P.S. 这个枚举写法我真是第一次见,我还是too young too simple,如果给我写的话我就三层循环了(
诶,不对,这个不应该在OnTickEnd那里调用吗?
诶,不对,这个不应该在OnTickEnd那里调用吗?
如果写在tickend好像就会跟气密室冲突
诶,不对,这个不应该在OnTickEnd那里调用吗?
如果写在tickend好像就会跟气密室冲突
不会呀,
public void OnTickEnd(ServerTickEndEvent e)
{
if (e.getTickNumber() % 20 != 0) return;
for (Player player : Bukkit.getOnlinePlayers())
{
if(!Config.EnableWorlds.contains(player.getWorld().getName())) continue; //这里得改成判断是不是全氧世界
if(player.getGameMode()!= GameMode.SURVIVAL) continue;
if(!OxygenSystem.playerOxygen.containsKey(player.getUniqueId()))
OxygenSystem.playerOxygen.put(player.getUniqueId(), (double) OxygenCalculator.GetMaxOxygen(player));
if(SealedRoomCalculator.GetBelong(player.getLocation())==0) //不在气密室里
{
//如果是山洞无氧世界且不在山洞里,return
boolean result = OxygenCalculator.SetOxygen(player, -1);
if(!result)
{
ItemStack oxygenTank = OxygenCalculator.GetOxygenTank(player);
if(oxygenTank==null)
player.damage(2);
else
{
oxygenTank.add(-1);
OxygenCalculator.ConsumeOxygenTank(player);
player.getInventory().addItem(OxygenTankProembryo.GetItem());
}
}
}
else
OxygenCalculator.SetOxygen(player,Config.RoomOxygenAdd);
OxygenUtil.ShowOxygen(player);
}
}
草,我是sb
写的有点烂,脑子是晕的
public void OnTickEnd(ServerTickEndEvent e)
{
if (e.getTickNumber() % 20 != 0) return;
for (Player player : Bukkit.getOnlinePlayers())
{
if(!Config.EnableWorlds.contains(player.getWorld().getName())) continue;
if(player.getGameMode()!= GameMode.SURVIVAL) continue;
if(!OxygenSystem.playerOxygen.containsKey(player.getUniqueId()))
OxygenSystem.playerOxygen.put(player.getUniqueId(), (double) OxygenCalculator.GetMaxOxygen(player));
if(SealedRoomCalculator.GetBelong(player.getLocation())==0 && !Config.EnableCaveNonOxygenWorlds.contains(player.getWorld().getName()))
{
boolean result = OxygenCalculator.SetOxygen(player, -1);
if(!result)
{
ItemStack oxygenTank = OxygenCalculator.GetOxygenTank(player);
if(oxygenTank==null)
player.damage(2);
else
{
oxygenTank.add(-1);
OxygenCalculator.ConsumeOxygenTank(player);
player.getInventory().addItem(OxygenTankProembryo.GetItem());
}
}
} else if (Config.EnableCaveNonOxygenWorlds.contains(player.getWorld().getName())) {
if(SealedCaveCalculator.checkIsOnCave(player.getLocation())) {
boolean result = OxygenCalculator.SetOxygen(player, -1);
if(!result)
{
ItemStack oxygenTank = OxygenCalculator.GetOxygenTank(player);
if(oxygenTank==null)
player.damage(2);
else
{
oxygenTank.add(-1);
OxygenCalculator.ConsumeOxygenTank(player);
player.getInventory().addItem(OxygenTankProembryo.GetItem());
}
}
}
} else OxygenCalculator.SetOxygen(player,Config.RoomOxygenAdd);
OxygenUtil.ShowOxygen(player);
}
}
我去找找地下会生成的方块(
我在想咋兼容1.19的新方块
写的有点烂,脑子是晕的
public void OnTickEnd(ServerTickEndEvent e) { if (e.getTickNumber() % 20 != 0) return; for (Player player : Bukkit.getOnlinePlayers()) { if(!Config.EnableWorlds.contains(player.getWorld().getName())) continue; if(player.getGameMode()!= GameMode.SURVIVAL) continue; if(!OxygenSystem.playerOxygen.containsKey(player.getUniqueId())) OxygenSystem.playerOxygen.put(player.getUniqueId(), (double) OxygenCalculator.GetMaxOxygen(player)); if(SealedRoomCalculator.GetBelong(player.getLocation())==0 && !Config.EnableCaveNonOxygenWorlds.contains(player.getWorld().getName())) { boolean result = OxygenCalculator.SetOxygen(player, -1); if(!result) { ItemStack oxygenTank = OxygenCalculator.GetOxygenTank(player); if(oxygenTank==null) player.damage(2); else { oxygenTank.add(-1); OxygenCalculator.ConsumeOxygenTank(player); player.getInventory().addItem(OxygenTankProembryo.GetItem()); } } } else if (Config.EnableCaveNonOxygenWorlds.contains(player.getWorld().getName())) { if(SealedCaveCalculator.checkIsOnCave(player.getLocation())) { boolean result = OxygenCalculator.SetOxygen(player, -1); if(!result) { ItemStack oxygenTank = OxygenCalculator.GetOxygenTank(player); if(oxygenTank==null) player.damage(2); else { oxygenTank.add(-1); OxygenCalculator.ConsumeOxygenTank(player); player.getInventory().addItem(OxygenTankProembryo.GetItem()); } } } } else OxygenCalculator.SetOxygen(player,Config.RoomOxygenAdd); OxygenUtil.ShowOxygen(player); } }
写得有点麻烦,但是问题不大,merge之后我再改就行
我在想咋兼容1.19的新方块
可以考虑使用现有API(旧版本的),然后看看getblock.getType返回的是啥Material,如果能返回新方块的Material的话问题就不大,大不了用getString检测名字(暴论)。
u1s1,我也不知道怎么去获取新方块
我在想咋兼容1.19的新方块
可以考虑使用现有API(旧版本的),然后看看getblock.getType返回的是啥Material,如果能返回新方块的Material的话问题就不大,大不了用getString检测名字(暴论)。
u1s1,我也不知道怎么去获取新方块
测试之后这样写没问题
for(String s : Config.CaveBlockList) CaveBlockList.add(Material.matchMaterial(s));
其实玩家的氧气值可以存在他们的nbt里面,这样就可以数据持久化,但是不知道性能如何