88import it .unimi .dsi .fastutil .objects .Object2IntMap ;
99import it .unimi .dsi .fastutil .objects .Object2IntOpenHashMap ;
1010import net .earthcomputer .clientcommands .Configs ;
11+ import net .earthcomputer .clientcommands .command .ClientCommandHelper ;
1112import net .earthcomputer .clientcommands .util .MultiVersionCompat ;
1213import net .earthcomputer .clientcommands .task .ItemThrowTask ;
1314import net .earthcomputer .clientcommands .task .LongTask ;
5051import org .jetbrains .annotations .Nullable ;
5152import org .slf4j .Logger ;
5253
54+ import java .lang .ref .WeakReference ;
5355import java .util .ArrayList ;
5456import java .util .Collections ;
5557import java .util .Comparator ;
@@ -114,6 +116,13 @@ public class EnchantmentCracker {
114116 public static final Logger LOGGER = LogUtils .getLogger ();
115117 private static final int PROGRESS_BAR_WIDTH = 50 ;
116118
119+ private static WeakReference <LongTask > currentEnchantingTask = null ;
120+ private static boolean isCurrentlyThrowingItems = false ;
121+
122+ public static void registerEvents () {
123+ PlayerRandCracker .RNG_CALLED_EVENT .register (EnchantmentCracker ::onRNGCallEvent );
124+ }
125+
117126 // RENDERING
118127 /*
119128 * This section is in charge of rendering the overlay on the enchantment GUI
@@ -309,28 +318,43 @@ private static void addPlayerRNGInfo(int enchantmentSeed) {
309318 }
310319 }
311320
312- public static void onEnchantedItem () {
321+ private static void onRNGCallEvent (PlayerRandCracker .RNGCallEvent event ) {
322+ if (event .getType () != PlayerRandCracker .RNGCallType .ENCHANTING ) {
323+ LongTask enchantingTask = currentEnchantingTask == null ? null : currentEnchantingTask .get ();
324+ if (enchantingTask != null ) {
325+ // if currently throwing items, unexpected RNG calls are handled by the item throw task
326+ if (!isCurrentlyThrowingItems ) {
327+ ClientCommandHelper .sendError (Component .translatable ("commands.cenchant.unexpectedCall" , event .getType ().getResetMessage ()));
328+ enchantingTask ._break ();
329+ }
330+ }
331+ return ;
332+ }
333+
313334 if (Configs .playerCrackState == PlayerRandCracker .CrackState .UNCRACKED && !isEnchantingPredictionEnabled ()) {
314335 return ;
315336 }
316337 if (Configs .playerCrackState .knowsSeed ()) {
338+ long prevSeed = PlayerRandCracker .getSeed ();
339+ int xpSeed = PlayerRandCracker .nextInt ();
340+ PlayerRandCracker .setSeed (prevSeed );
317341 possibleXPSeeds .clear ();
318- possibleXPSeeds .add (PlayerRandCracker . nextInt () );
342+ possibleXPSeeds .add (xpSeed );
319343 Configs .playerCrackState = PlayerRandCracker .CrackState .CRACKED ;
320344 Configs .enchCrackState = CrackState .CRACKED ;
345+ event .setMaintained ();
321346 } else if (Configs .playerCrackState == PlayerRandCracker .CrackState .HALF_CRACKED ) {
322347 possibleXPSeeds .clear ();
323348 Configs .playerCrackState = PlayerRandCracker .CrackState .ENCH_CRACKING_2 ;
324349 Configs .enchCrackState = CrackState .UNCRACKED ;
350+ event .setMaintainedEvenIfSeedUnknown ();
325351 } else if ((Configs .playerCrackState == PlayerRandCracker .CrackState .UNCRACKED
326352 || Configs .playerCrackState == PlayerRandCracker .CrackState .ENCH_CRACKING_1
327353 || Configs .playerCrackState == PlayerRandCracker .CrackState .ENCH_CRACKING_2 )) {
328354 possibleXPSeeds .clear ();
329355 Configs .playerCrackState = PlayerRandCracker .CrackState .ENCH_CRACKING_1 ;
330356 Configs .enchCrackState = CrackState .UNCRACKED ;
331- } else {
332- PlayerRandCracker .onUnexpectedItemEnchant ();
333- Configs .enchCrackState = CrackState .UNCRACKED ;
357+ event .setMaintainedEvenIfSeedUnknown ();
334358 }
335359 doneEnchantment = true ;
336360 }
@@ -405,9 +429,16 @@ public static String manipulateEnchantments(Item item, Predicate<List<Enchantmen
405429 LongTaskList taskList = new LongTaskList () {
406430 @ Override
407431 public Set <Object > getMutexKeys () {
408- return simulate ? Set .of () : Set .of (ItemThrowTask .class );
432+ return simulate ? Set .of (EnchantmentCracker .class ) : Set .of (EnchantmentCracker .class , ItemThrowTask .class );
433+ }
434+
435+ @ Override
436+ public void onCompleted () {
437+ super .onCompleted ();
438+ currentEnchantingTask = null ;
409439 }
410440 };
441+ currentEnchantingTask = new WeakReference <>(taskList );
411442
412443 taskList .addTask (new SimpleTask () {
413444 private int index = 0 ;
@@ -454,28 +485,36 @@ public void onCompleted() {
454485 }
455486
456487 if (!simulate && finalResult != null ) {
488+ doneEnchantment = false ;
457489 int timesNeeded = finalResult .itemThrows ();
458490 if (timesNeeded != ManipulateResult .NO_DUMMY ) {
459491 if (timesNeeded != 0 ) {
460492 player .snapTo (player .getX (), player .getY (), player .getZ (), player .getYRot (), 90 );
461493 // sync rotation to server before we throw any items
462494 player .connection .send (new ServerboundMovePlayerPacket .Rot (player .getYRot (), 90 , player .onGround (), player .horizontalCollision ));
463- Configs .playerCrackState = PlayerRandCracker .CrackState .MANIPULATING_ENCHANTMENTS ;
464495 }
465496 if (timesNeeded > 0 ) {
497+ isCurrentlyThrowingItems = true ;
466498 taskList .addTask (new ItemThrowTask (timesNeeded , ItemThrowTask .FLAG_WAIT_FOR_ITEMS ) {
467499 @ Override
468- public boolean condition () {
469- if (Configs .playerCrackState != PlayerRandCracker .CrackState .MANIPULATING_ENCHANTMENTS ) {
500+ public void onCompleted () {
501+ super .onCompleted ();
502+ Minecraft .getInstance ().player .playNotifySound (SoundEvents .NOTE_BLOCK_PLING .value (), SoundSource .PLAYERS , 1.0f , 2.0f );
503+ isCurrentlyThrowingItems = false ;
504+ }
505+
506+ @ Override
507+ protected void onFailedToThrowItem (PlayerRandCracker .ThrowItemsResult throwItemsResult ) {
508+ super .onFailedToThrowItem (throwItemsResult );
509+ if (throwItemsResult .getType () != PlayerRandCracker .ThrowItemsResult .Type .NOT_ENOUGH_ITEMS ) {
470510 taskList ._break ();
471- return false ;
472511 }
473- return super .condition ();
474512 }
475513
476514 @ Override
477- public void onCompleted () {
478- Minecraft .getInstance ().player .playNotifySound (SoundEvents .NOTE_BLOCK_PLING .value (), SoundSource .PLAYERS , 1.0f , 2.0f );
515+ protected void onUnexpectedRNGCall (PlayerRandCracker .RNGCallType callType ) {
516+ ClientCommandHelper .sendError (Component .translatable ("commands.cenchant.unexpectedCall" , callType .getResetMessage ()));
517+ taskList ._break ();
479518 }
480519
481520 @ Override
@@ -498,14 +537,12 @@ protected void onItemThrown(int current, int total) {
498537 taskList .addTask (new LongTask () {
499538 @ Override
500539 public void initialize () {
501- Configs .playerCrackState = PlayerRandCracker .CrackState .WAITING_DUMMY_ENCHANT ;
502540 Minecraft .getInstance ().gui .getChat ().addMessage (Component .translatable ("enchCrack.insn.dummy" ));
503- doneEnchantment = false ;
504541 }
505542
506543 @ Override
507544 public boolean condition () {
508- return Configs . playerCrackState == PlayerRandCracker . CrackState . WAITING_DUMMY_ENCHANT ;
545+ return ! doneEnchantment ;
509546 }
510547
511548 @ Override
@@ -524,11 +561,10 @@ public String toString() {
524561 });
525562 }
526563
527- doneEnchantment = true ;
528564 taskList .addTask (new OneTickTask () {
529565 @ Override
530566 public void run () {
531- if (Configs .enchCrackState == CrackState .CRACKED && doneEnchantment ) {
567+ if (Configs .enchCrackState == CrackState .CRACKED ) {
532568 ChatComponent chat = Minecraft .getInstance ().gui .getChat ();
533569 chat .addMessage (Component .translatable ("enchCrack.insn.ready" ).withStyle (ChatFormatting .BOLD ));
534570 chat .addMessage (Component .translatable ("enchCrack.insn.bookshelves" , finalResult .bookshelves ));
0 commit comments