夏日冰熊
本帖最后由 南外丶仓鼠 于 2021-2-8 18:19 编辑

代码:
  1. public class QuickNight {
  2.     private static YamlConfiguration yaml;
  3.     private static double percent;
  4.     private static int speed;
  5.     private static boolean title;

  6.     public QuickNight() {
  7.         File file = new File(UntilTheEndServer.getInstance().getDataFolder(), "timeoperate.yml");
  8.         if (!file.exists())
  9.             UntilTheEndServer.getInstance().saveResource("timeoperate.yml", false);
  10.         yaml = YamlConfiguration.loadConfiguration(file);

  11.         if (!yaml.getBoolean("quickNight.enable"))
  12.             return;

  13.         percent = yaml.getDouble("quickNight.percent");
  14.         speed = yaml.getInt("quickNight.speed");
  15.         title = yaml.getBoolean("quickNight.title");

  16.         new BukkitRunnable() {
  17.             @Override
  18.             public void run() {
  19.                 for (World world : Bukkit.getWorlds()) {
  20.                     //白天不进行计算
  21.                     if (world.getTime() < 12600) {
  22.                         continue;
  23.                     }
  24.                     //计算某世界总睡觉玩家人数
  25.                     int amount = 0;
  26.                     if (world.getPlayers().size() == 0) {
  27.                         continue;
  28.                     }
  29.                     for (Player player : world.getPlayers()) {
  30.                         if (player.isSleeping()) {
  31.                             amount++;
  32.                         }
  33.                     }
  34.                     //如果全部都在入睡,就按原版机制跳到第二天
  35.                     if (amount == world.getPlayers().size()) {
  36.                         continue;
  37.                     }
  38.                     //如果入睡人数超过占比,则加速时间流动
  39.                     if (amount >= world.getPlayers().size() * percent) {
  40.                         long newTime = world.getTime() + 2 * (speed - 1);
  41.                         System.out.println(newTime);
  42.                         if (newTime >= 24000) {
  43.                             world.setTime(newTime - 24000);
  44.                         } else {
  45.                             world.setTime(newTime);
  46.                         }
  47.                         //告诉玩家几点了
  48.                         if (title) {
  49.                             for (Player player : world.getPlayers()) {
  50.                                 player.resetTitle();
  51.                                 player.sendTitle("§a" + getFormatTime(newTime), "§e世界时间");
  52.                             }
  53.                         }
  54.                     }
  55.                 }
  56.             }
  57.         }.runTaskTimer(UntilTheEndServer.getInstance(), 0L, 2L);
  58.     }

  59.     //把世界时间刻变为刻度的hh:mm
  60.     private static String getFormatTime(long newTime) {
  61.         long hour = newTime / 1000;
  62.         long minute = (long) (newTime % 1000 * 0.06);
  63.         String tmp = "";
  64.         if (minute < 10) {
  65.             tmp += "0" + minute;
  66.         } else {
  67.             tmp += minute;
  68.         }
  69.         if (hour + 6 >= 24) {
  70.             return "0" + (hour + 6 - 24) + ":" + tmp;
  71.         } else {
  72.             return (hour + 6) + ":" + tmp;
  73.         }
  74.     }
  75. }
复制代码
其中
percent=0.3
speed=30


代码目的:
当服务器某世界夜晚时,睡觉的玩家超过一定占比,夜晚时间开始加速流动,直到白天结束睡觉


出现的问题:
从12600刻(下午六点左右)一部分玩家开始睡觉,加速流逝到16400刻左右时,突然地睡觉的一部分玩家突然停止睡觉,时间跳到第二天0刻(上午6点)于是我尝试从16400刻开始入睡,结果时间加速流逝到18200刻左右,又出现了上面的情况。
这说明我代码的加速判定是没问题的。
但是当时的确服务器内有两名玩家在线,其中有一位不在睡觉,essentials也没有判定其为afk(挂机状态),但是时间就像是所有人在睡觉一样突然的跳到第二天
我算了一下,从入睡到结束睡眠大致等于MC原版单人模式从入睡到第二天经过的现实时间(8-10s左右)

我的猜测:
bukkit判定睡眠是根据ip(因为当时服务器内两名玩家都是我的测试号,同IP)

请求各位大佬解答,感激不尽


南柯郡守
本帖最后由 南柯郡守 于 2021-2-9 00:02 编辑

1. 判定玩家睡觉跳时间并不是判断ip 因为Player下有个setSleepingIgnored(boolean isSleeping)
2. 你说的 突然跳到0刻 是一个在睡觉一个没睡觉的情况下跳到0刻的嘛




你这个不就是相当于直接跳到0刻嘛

洞穴夜莺
本帖最后由 洞穴夜莺 于 2021-2-9 00:11 编辑
南柯郡守 发表于 2021-2-8 23:59
1. 判定玩家睡觉跳时间并不是判断ip 因为Player下有个setSleepingIgnored(boolean isSleeping)
2. 你说 ...

那不一样
>=又不是==

我倒是觉得楼主应该把整个项目发上来


而且时间k和k + 24000是不同的时间,你不能这样处理的

南柯郡守
洞穴夜莺 发表于 2021-2-9 00:04
那不一样
>=又不是==

24001-24000=1

那不就是把世界时间设置为1刻
那天不就亮了 那玩家不就自动起床了
我觉得基本上没问题  就是流速倍数太大了

南柯郡守
还有一件事

最好是在加速刚开始的时候把时间流动先停掉

不然你在这加速 他自己也在跑

最后速度肯定是比预期快的

夏日冰熊
南柯郡守 发表于 2021-2-9 00:11
24001-24000=1

那不就是把世界时间设置为1刻

我调试的时候看着时间流逝,到连2w都没到就停了
即使是20倍速也不可能10秒过完晚上啊
我是百思不得其解才去测出游戏刻数据的

夏日冰熊
南柯郡守 发表于 2021-2-8 23:59
1. 判定玩家睡觉跳时间并不是判断ip 因为Player下有个setSleepingIgnored(boolean isSleeping)
2. 你说 ...

我曾将sleepingignore设为false
没有作用😭

夏日冰熊
洞穴夜莺 发表于 2021-2-9 00:04
那不一样
>=又不是==


项目在https://github.com/HamsterYDS/UntilTheEndServer

其中有两个模块会操纵时间,都在utes.timeoperate下
我测试加速夜晚的时候,另一个模块是disable状态,应该不会有影响

南柯郡守
本帖最后由 南柯郡守 于 2021-2-9 00:28 编辑
尝试从16400刻开始入睡...
...结果时间加速流逝到18200刻左右
把时间流动先停掉.....
...最后速度肯定是比预期快的

24000-16400=7600tick
7600÷20=380秒
原本过完夜晚需要380秒(6分多钟)

2 * (speed - 1)
已知speed=30
即 1tick=58tick
你算算速度放大了多少倍

夏日冰熊
南柯郡守 发表于 2021-2-9 00:16
还有一件事

最好是在加速刚开始的时候把时间流动先停掉

初始化的时候已经setdaylightcycle false了
算出来过一晚上大概需要30秒,但是连其一半时间都没到,睡觉就停止了

我是看着每刻tick的数值变化的,到16000就突然停了,然后跳到24000也就是下一天的0

南柯郡守
本帖最后由 南柯郡守 于 2021-2-9 00:49 编辑
南外丶仓鼠 发表于 2021-2-9 00:31
初始化的时候已经setdaylightcycle false了
算出来过一晚上大概需要30秒,但是连其一半时间都没到,睡觉 ...

7600 tick ÷ (20 x 1tick  x 58) ≈ 6.55秒

不到7秒就跑过7600tick了

1tick=58tick  相当于一秒跑了1160tick 七秒天就亮了


就是说 你16400刻开始睡觉算
需要7600tick天才会亮
你speed=30 直接把速度翻了58倍

原本7600刻需要380秒跑完
现在只用不到7秒就跑完了




即便是12600刻计算入睡开始加速
24000-12600=11400 tick
11400÷20=570 秒

加速58倍之后
570 秒 ÷ 58 ≈ 9.83 秒

也不超过十秒

所以你说的
算出来过一晚上大概需要30秒,但是连其一半时间都没到,睡觉就停止了

其实没毛病




至于你说的
每刻tick的数值变化的,到16000就突然停了

确实有点迷
不过建议直接System.out.println(world.getTime());看看



哦 你这是2刻执行一次啊
问题不大 7*2 =14  10*2=20 都差不多



夏日冰熊
南柯郡守 发表于 2021-2-9 00:38
7600 tick ÷ (20 x 1tick  x 58) ≈ 6.55秒

不到7秒就跑过7600tick了

代码中已经有System.out了
我调了半天,硬是连个大于2w的数没看到,而且天色的确是由全黑到全白,非常突兀,没有清晨的效果

夏日冰熊
南柯郡守 发表于 2021-2-9 00:38
7600 tick ÷ (20 x 1tick  x 58) ≈ 6.55秒

不到7秒就跑过7600tick了

明天录个视频
感谢大佬不断跟踪帮助谢谢🙏🙏

夏日冰熊
本帖最后由 南外丶仓鼠 于 2021-2-9 08:42 编辑

录屏
https://www.bilibili.com/blackboard/newplayer.html?playlist=false&crossDomain=1&aid=801559789&page=1
@南柯郡守

南柯郡守
本帖最后由 南柯郡守 于 2021-2-9 14:24 编辑

我直接用你的代码稍加修改后测试了
这是视频(没发小破站 审核太久)
https://cowtransfer.com/s/b7709b3567b841



以下是代码实现

  1. package top.themeda.ancientworld.runnable;

  2. import org.bukkit.Bukkit;
  3. import org.bukkit.World;
  4. import org.bukkit.entity.Player;
  5. import org.bukkit.scheduler.BukkitRunnable;

  6. import top.themeda.ancientworld.Core;

  7. public class TimeBoost {
  8.     private static double percent;
  9.     private static int speed;
  10.     private static boolean title;
  11.         public TimeBoost(){
  12.                
  13.         percent = 0.5d;
  14.     speed = 20;
  15.     title=true;
  16.     new BukkitRunnable() {
  17.         @Override
  18.         public void run() {
  19.             for (World world : Bukkit.getWorlds()) {
  20.                 //白天不进行计算
  21.                 if (world.getTime() < 12600) {
  22.                     continue;
  23.                 }
  24.                 //计算某世界总睡觉玩家人数
  25.                 int amount = 0;
  26.                 if (world.getPlayers().size() == 0) {
  27.                     continue;
  28.                 }
  29.                 for (Player player : world.getPlayers()) {
  30.                     if (player.isSleeping()) {
  31.                         amount++;
  32.                     }
  33.                 }
  34.                 //如果全部都在入睡,就按原版机制跳到第二天
  35.                 if (amount == world.getPlayers().size()) {
  36.                     continue;//草! 无良论坛吞我代码
  37.                                  //多开一行。 你这里如果真的关了时间流逝 那么所有玩家都睡觉也不会使得时间跳到第二天
  38.                 }

  39.                 //如果入睡人数超过占比,则加速时间流动
  40.                 if (amount >= world.getPlayers().size() * percent) {
  41.                     long newTime = world.getTime() + 2 * speed;
  42.                     System.out.println(newTime);
  43.                     if (newTime >= 24000) {
  44.                         world.setTime(newTime - 24000);
  45.                     } else {
  46.                         world.setTime(newTime);
  47.                     }
  48.                     //告诉玩家几点了
  49.                     if (title) {
  50.                         for (Player player : world.getPlayers()) {
  51.                             player.resetTitle();
  52.                             player.sendTitle("§a" + newTime, "§e世界时间",10,20,10);
  53.                         }
  54.                     }
  55.                 }
  56.             }
  57.         }
  58.     }.runTaskTimer(Core.getInstance(), 0L, 2L);
  59.     }
  60. }
复制代码






我看视频 你将时间设置在12600之后 开始睡觉的第一个输出时间是12700+  

所以你时间流逝并没有关掉

夏日冰熊
南柯郡守 发表于 2021-2-9 14:20
我直接用你的代码稍加修改后测试了
这是视频(没发小破站 审核太久)
https://cowtransfer.com/s/b7709b3567b ...

原来如此,我差个setdaylightcycle
实在感谢
但是仍有一个问题,为什么一个玩家不在睡觉,仍然执行了原版的机制

南柯郡守
南外丶仓鼠 发表于 2021-2-9 18:42
原来如此,我差个setdaylightcycle
实在感谢
但是仍有一个问题,为什么一个玩家不在睡觉,仍然执行了原版 ...

无法复现 所以暂时无法得出结论

还有一件事

你冻结时间自然流动之后你要手动操作他以正常速度流动

不然没有玩家睡觉那黑夜总会是黑夜

第一页 上一页 下一页 最后一页