44import huix .infinity .common .core .component .IFWDataComponents ;
55import huix .infinity .common .world .effect .UnClearEffect ;
66import huix .infinity .common .world .entity .player .LevelBonusStats ;
7+ import huix .infinity .common .world .entity .player .NutritionalStatus ;
78import huix .infinity .common .world .food .IFWFoodProperties ;
89import huix .infinity .common .world .item .IFWItems ;
10+ import huix .infinity .extension .func .FoodDataExtension ;
911import huix .infinity .init .event .IFWLoading ;
1012import huix .infinity .util .IFWEnchantmentHelper ;
1113import huix .infinity .util .WorldHelper ;
1921import net .minecraft .resources .ResourceKey ;
2022import net .minecraft .resources .ResourceLocation ;
2123import net .minecraft .server .level .ServerLevel ;
24+ import net .minecraft .server .level .ServerPlayer ;
2225import net .minecraft .tags .ItemTags ;
2326import net .minecraft .world .effect .MobEffects ;
2427import net .minecraft .world .entity .EquipmentSlotGroup ;
2932import net .minecraft .world .item .ArmorItem ;
3033import net .minecraft .world .item .ItemStack ;
3134import net .minecraft .world .item .Items ;
35+ import net .minecraft .world .level .GameRules ;
3236import net .minecraft .world .level .Level ;
3337import net .minecraft .world .level .LevelAccessor ;
3438import net .minecraft .world .level .block .Blocks ;
4549import net .neoforged .neoforge .event .LootTableLoadEvent ;
4650import net .neoforged .neoforge .event .entity .living .LivingDeathEvent ;
4751import net .neoforged .neoforge .event .entity .living .MobEffectEvent ;
48- import net .neoforged .neoforge .event .entity .player .CanContinueSleepingEvent ;
49- import net .neoforged .neoforge .event .entity .player .CriticalHitEvent ;
50- import net .neoforged .neoforge .event .entity .player .ItemTooltipEvent ;
51- import net .neoforged .neoforge .event .entity .player .PlayerEvent ;
52+ import net .neoforged .neoforge .event .entity .player .*;
5253import net .neoforged .neoforge .event .furnace .FurnaceFuelBurnTimeEvent ;
54+ import net .neoforged .neoforge .event .level .SleepFinishedTimeEvent ;
5355import net .neoforged .neoforge .event .level .block .CropGrowEvent ;
5456import net .neoforged .neoforge .event .tick .ServerTickEvent ;
5557import net .neoforged .neoforge .registries .datamaps .DataMapsUpdatedEvent ;
5658
57- import java .util .Iterator ;
58- import java .util .List ;
59- import java .util .Map ;
59+ import java .util .*;
6060
6161public class IFWEvents {
6262
@@ -172,7 +172,7 @@ private static void showFoodInfo(final FoodProperties food, final List<Component
172172 }
173173
174174 private static void showMoreFoodInfo (final IFWFoodProperties extraFood , final List <Component > list ) {
175- if (extraFood != null && Screen .hasAltDown ()) {
175+ if (extraFood != null && Screen .hasAltDown ()) {
176176 if (extraFood .protein () != 0 )
177177 list .add (Component .translatable ("foodtips.protein" , extraFood .protein ()).withStyle (ChatFormatting .YELLOW ));
178178 if (extraFood .phytonutrients () != 0 )
@@ -240,24 +240,95 @@ public static void onCropGrow(final CropGrowEvent.Pre event) {
240240
241241 @ SubscribeEvent
242242 public static void onCalculatePlayerTurn (CalculatePlayerTurnEvent event ) {
243- // 获取玩家
243+
244244 LocalPlayer player = Minecraft .getInstance ().player ;
245245
246246 if (player != null && player .hasEffect (MobEffects .MOVEMENT_SLOWDOWN )) {
247- // 获取缓慢效果等级
248- int amplifier = player .getEffect (MobEffects .MOVEMENT_SLOWDOWN ).getAmplifier ();
249- // 获取当前灵敏度
247+
248+ int amplifier = Objects . requireNonNull ( player .getEffect (MobEffects .MOVEMENT_SLOWDOWN ) ).getAmplifier ();
249+
250250 double sensitivity = event .getMouseSensitivity ();
251- // 根据缓慢等级降低灵敏度 (每级减少20%)
251+
252252 double reduction = 1.0 - ((amplifier + 1 ) * 0.2 );
253- // 设置新的灵敏度
253+
254254 event .setMouseSensitivity (sensitivity * reduction );
255255 }
256256 }
257257
258- // @SubscribeEvent
259- // public static void onSleepFinished(final SleepFinishedTimeEvent event) {
260- //
261- // }
258+ private static final Map <UUID , Long > playerSleepStartTime = new HashMap <>();
259+
260+ @ SubscribeEvent
261+ public static void onCanPlayerSleep (final CanPlayerSleepEvent event ) {
262+ ServerPlayer player = event .getEntity ();
263+
264+ if (event .getProblem () == null ) {
265+ long currentTime = player .level ().getDayTime ();
266+ playerSleepStartTime .put (player .getUUID (), currentTime );
267+ }
268+ }
269+
270+ @ SubscribeEvent
271+ public static void onSleepFinished (final SleepFinishedTimeEvent event ) {
272+ if (!(event .getLevel () instanceof ServerLevel serverLevel )) return ;
273+
274+ long newTime = event .getNewTime ();
275+
276+ // 为所有参与睡眠的玩家处理恢复
277+ for (ServerPlayer player : serverLevel .players ()) {
278+ UUID playerUUID = player .getUUID ();
279+ Long sleepStartTime = playerSleepStartTime .get (playerUUID );
262280
263- }
281+ if (sleepStartTime != null ) {
282+ // 计算实际跳过的游戏时间
283+ long actualSkippedTime = newTime - sleepStartTime ;
284+
285+ // 确保跳过时间是合理的(至少1000 ticks)
286+ if (actualSkippedTime > 1000 ) {
287+ calculateSleepHealing (player , actualSkippedTime );
288+ }
289+
290+ playerSleepStartTime .remove (playerUUID );
291+ }
292+ }
293+ }
294+
295+ @ SubscribeEvent
296+ public static void onPlayerWakeUp (final PlayerWakeUpEvent event ) {
297+ Player player = event .getEntity ();
298+ if (player .level ().isClientSide ()) return ;
299+
300+ // 清理可能残留的睡眠记录(处理睡眠被打断等情况)
301+ playerSleepStartTime .remove (player .getUUID ());
302+ }
303+
304+ private static void calculateSleepHealing (Player player , long skippedTime ) {
305+ if (!player .level ().getGameRules ().getBoolean (GameRules .RULE_NATURAL_REGENERATION )) {
306+ return ;
307+ }
308+
309+ if (player .getHealth () >= player .getMaxHealth ()) {
310+ return ;
311+ }
312+
313+ FoodDataExtension foodData = (FoodDataExtension ) player .getFoodData ();
314+ NutritionalStatus nutritionalStatus = foodData .ifw_nutritionalStatus ();
315+
316+ int baseHealInterval = 1280 ;
317+ int adjustedInterval = baseHealInterval * nutritionalStatus .naturalHealSpeedTimes ();
318+ int sleepHealInterval = adjustedInterval / 8 ;
319+ int healCount = (int ) (skippedTime / sleepHealInterval );
320+
321+ if (healCount > 0 ) {
322+ float maxHealth = player .getMaxHealth ();
323+ float currentHealth = player .getHealth ();
324+ float maxPossibleHeal = maxHealth - currentHealth ;
325+ float actualHeal = Math .min (healCount , maxPossibleHeal );
326+
327+ if (actualHeal > 0 ) {
328+ player .heal (actualHeal );
329+ float exhaustionCost = actualHeal * 6.0F ;
330+ player .getFoodData ().addExhaustion (exhaustionCost );
331+ }
332+ }
333+ }
334+ }
0 commit comments