88import de .dafuqs .spectrum .blocks .item_bowl .*;
99import de .dafuqs .spectrum .blocks .upgrade .*;
1010import de .dafuqs .spectrum .compat .biome_makeover .*;
11- import de .dafuqs .spectrum .enchantments .*;
1211import de .dafuqs .spectrum .helpers .*;
1312import de .dafuqs .spectrum .items .magic_items .*;
1413import de .dafuqs .spectrum .networking .*;
2322import net .minecraft .advancement .criterion .*;
2423import net .minecraft .block .*;
2524import net .minecraft .block .entity .*;
25+ import net .minecraft .component .type .ItemEnchantmentsComponent ;
2626import net .minecraft .enchantment .*;
2727import net .minecraft .entity .player .*;
2828import net .minecraft .inventory .*;
3131import net .minecraft .network .listener .*;
3232import net .minecraft .network .packet .*;
3333import net .minecraft .network .packet .s2c .play .*;
34+ import net .minecraft .registry .entry .RegistryEntry ;
35+ import net .minecraft .registry .tag .EnchantmentTags ;
3436import net .minecraft .server .network .*;
3537import net .minecraft .server .world .*;
3638import net .minecraft .sound .*;
@@ -65,14 +67,14 @@ public class EnchanterBlockEntity extends InWorldInteractionBlockEntity implemen
6567 // since the item bowls around the enchanter hold some items themselves
6668 // they get cached here for faster recipe lookup
6769 // virtualInventoryRecipeOrientation is the order the items are ordered for the recipe to match (rotations from 0-3)
68- protected SimpleInventory virtualInventoryIncludingBowlStacks ;
70+ protected ImplementedInventory virtualInventoryIncludingBowlStacks ;
6971 protected int virtualInventoryRecipeOrientation ;
7072 protected boolean virtualInventoryRecipeMirrored ;
7173
7274 protected boolean inventoryChanged ;
7375 private UpgradeHolder upgrades ;
7476
75- private GatedSpectrumRecipe currentRecipe ;
77+ private GatedSpectrumRecipe <?> currentRecipe ;
7678 private int craftingTime ;
7779 private int craftingTimeTotal ;
7880 private int currentItemProcessingTime ;
@@ -82,7 +84,7 @@ public class EnchanterBlockEntity extends InWorldInteractionBlockEntity implemen
8284
8385 public EnchanterBlockEntity (BlockPos pos , BlockState state ) {
8486 super (SpectrumBlockEntities .ENCHANTER , pos , state , INVENTORY_SIZE );
85- this .virtualInventoryIncludingBowlStacks = new SimpleInventory (INVENTORY_SIZE + 8 );
87+ this .virtualInventoryIncludingBowlStacks = ImplementedInventory . ofSize (INVENTORY_SIZE + 8 );
8688 this .currentItemProcessingTime = -1 ;
8789 }
8890
@@ -230,23 +232,31 @@ public static void serverTick(World world, BlockPos blockPos, BlockState blockSt
230232 public static boolean isValidCenterEnchantingSetup (@ NotNull EnchanterBlockEntity enchanterBlockEntity ) {
231233 ItemStack centerStack = enchanterBlockEntity .virtualInventoryIncludingBowlStacks .getStack (0 );
232234 boolean isEnchantableBookInCenter = SpectrumEnchantmentHelper .isEnchantableBook (centerStack );
233- if (!centerStack .isEmpty () && (isEnchantableBookInCenter || centerStack .getItem ().isEnchantable (centerStack )) && enchanterBlockEntity .virtualInventoryIncludingBowlStacks .getStack (1 ).getItem () instanceof ExperienceStorageItem ) {
235+
236+ var centerIsEnchantable = (isEnchantableBookInCenter || centerStack .getItem ().isEnchantable (centerStack ));
237+ var hasExpStorage = enchanterBlockEntity .virtualInventoryIncludingBowlStacks .getStack (1 ).getItem () instanceof ExperienceStorageItem ;
238+
239+ if (!centerStack .isEmpty () && centerIsEnchantable && hasExpStorage ) {
234240 // gilded books can copy enchantments from any source item
235241 boolean centerStackIsGildedBook = centerStack .isOf (SpectrumItems .GILDED_BOOK );
236242 boolean enchantedBookWithAdditionalEnchantmentsFound = false ;
237- Map <Enchantment , Integer > existingEnchantments = EnchantmentHelper .get (centerStack );
243+
244+ var existingEnchantments = EnchantmentHelper .getEnchantments (centerStack ).getEnchantmentEntries ();
238245 for (int i = 0 ; i < 8 ; i ++) {
239246 ItemStack virtualSlotStack = enchanterBlockEntity .virtualInventoryIncludingBowlStacks .getStack (2 + i );
247+
240248 // empty slots do not count
241249 if (!virtualSlotStack .isEmpty ()) {
242250 if (centerStackIsGildedBook || virtualSlotStack .getItem () instanceof EnchantedBookItem ) {
243- Map <Enchantment , Integer > currentEnchantedBookEnchantments = EnchantmentHelper .get (virtualSlotStack );
244- for (Enchantment enchantment : currentEnchantedBookEnchantments .keySet ()) {
245- if ((isEnchantableBookInCenter || enchantment .isAcceptableItem (centerStack )) && (!existingEnchantments .containsKey (enchantment ) || existingEnchantments .get (enchantment ) < currentEnchantedBookEnchantments .get (enchantment ))) {
251+ for (var entry : EnchantmentHelper .getEnchantments (virtualSlotStack ).getEnchantmentEntries ()) {
252+ var enchantment = entry .getKey ();
253+ var isAcceptable = isEnchantableBookInCenter || enchantment .value ().isAcceptableItem (centerStack );
254+ var isRedundant = existingEnchantments .stream ().anyMatch (existing -> existing .getKey () == enchantment && existing .getIntValue () >= entry .getIntValue ());
255+ if (isAcceptable && !isRedundant ) {
246256 if (enchanterBlockEntity .canOwnerApplyConflictingEnchantments ) {
247257 enchantedBookWithAdditionalEnchantmentsFound = true ;
248258 break ;
249- } else if (SpectrumEnchantmentHelper .canCombineAny (existingEnchantments , currentEnchantedBookEnchantments )) {
259+ } else if (SpectrumEnchantmentHelper .canCombineAny (centerStack , virtualSlotStack )) {
250260 enchantedBookWithAdditionalEnchantmentsFound = true ;
251261 break ;
252262 }
@@ -257,8 +267,10 @@ public static boolean isValidCenterEnchantingSetup(@NotNull EnchanterBlockEntity
257267 }
258268 }
259269 }
270+
260271 return enchantedBookWithAdditionalEnchantmentsFound ;
261272 }
273+
262274 return false ;
263275 }
264276
@@ -300,10 +312,10 @@ private static boolean checkRecipeRequirements(World world, BlockPos blockPos, @
300312 public static void enchantCenterItem (@ NotNull EnchanterBlockEntity enchanterBlockEntity ) {
301313 ItemStack centerStack = enchanterBlockEntity .getStack (0 );
302314 ItemStack centerStackCopy = centerStack .copy ();
303- Map < Enchantment , Integer > highestEnchantments = getHighestEnchantmentsInItemBowls (enchanterBlockEntity );
315+ var highestEnchantments = getHighestEnchantmentsInItemBowls (enchanterBlockEntity );
304316
305- for (Enchantment enchantment : highestEnchantments .keySet ()) {
306- centerStackCopy = SpectrumEnchantmentHelper .addOrUpgradeEnchantment (centerStackCopy , enchantment , highestEnchantments . get ( enchantment ), false , enchanterBlockEntity .canOwnerApplyConflictingEnchantments ).getRight ();
317+ for (var entry : highestEnchantments .getEnchantmentEntries ()) {
318+ centerStackCopy = SpectrumEnchantmentHelper .addOrUpgradeEnchantment (centerStackCopy , entry . getKey (), entry . getIntValue ( ), false , enchanterBlockEntity .canOwnerApplyConflictingEnchantments ).getRight ();
307319 }
308320
309321 int spentExperience = enchanterBlockEntity .currentItemProcessingTime / EnchanterBlockEntity .REQUIRED_TICKS_FOR_EACH_EXPERIENCE_POINT ;
@@ -325,27 +337,24 @@ public static void enchantCenterItem(@NotNull EnchanterBlockEntity enchanterBloc
325337 }
326338 }
327339
328- public static Map <Enchantment , Integer > getHighestEnchantmentsInItemBowls (@ NotNull EnchanterBlockEntity enchanterBlockEntity ) {
329- List <ItemStack > bowlStacks = new ArrayList <>();
330- for (int i = 0 ; i < 8 ; i ++) {
331- bowlStacks .add (enchanterBlockEntity .virtualInventoryIncludingBowlStacks .getStack (2 + i ));
332- }
333-
334- return SpectrumEnchantmentHelper .collectHighestEnchantments (bowlStacks );
340+ public static ItemEnchantmentsComponent getHighestEnchantmentsInItemBowls (@ NotNull EnchanterBlockEntity enchanterBlockEntity ) {
341+ return SpectrumEnchantmentHelper .collectHighestEnchantments (
342+ enchanterBlockEntity .virtualInventoryIncludingBowlStacks .getItems ().subList (2 , 10 ));
335343 }
336344
337345 public static int getRequiredExperienceToEnchantCenterItem (@ NotNull EnchanterBlockEntity enchanterBlockEntity ) {
338346 boolean valid = false ;
339347 ItemStack centerStack = enchanterBlockEntity .getStack (0 );
340348 if (!centerStack .isEmpty () && (centerStack .getItem ().isEnchantable (centerStack ) || SpectrumEnchantmentHelper .isEnchantableBook (centerStack ))) {
341349 ItemStack centerStackCopy = centerStack .copy ();
342- Map < Enchantment , Integer > highestEnchantmentLevels = getHighestEnchantmentsInItemBowls (enchanterBlockEntity );
350+ var highestEnchantments = getHighestEnchantmentsInItemBowls (enchanterBlockEntity );
343351 int requiredExperience = 0 ;
344- for (Enchantment enchantment : highestEnchantmentLevels .keySet ()) {
345- int enchantmentLevel = highestEnchantmentLevels .get (enchantment );
346- int currentRequired = getRequiredExperienceToEnchantWithEnchantment (centerStackCopy , enchantment , enchantmentLevel , enchanterBlockEntity .canOwnerApplyConflictingEnchantments );
352+ for (var entry : highestEnchantments .getEnchantmentEntries ()) {
353+ var enchantment = entry .getKey ();
354+ int level = entry .getIntValue ();
355+ int currentRequired = getRequiredExperienceToEnchantWithEnchantment (centerStackCopy , enchantment , level , enchanterBlockEntity .canOwnerApplyConflictingEnchantments );
347356 if (currentRequired > 0 ) {
348- centerStackCopy = SpectrumEnchantmentHelper .addOrUpgradeEnchantment (centerStackCopy , enchantment , enchantmentLevel , false , enchanterBlockEntity .canOwnerApplyConflictingEnchantments ).getRight ();
357+ centerStackCopy = SpectrumEnchantmentHelper .addOrUpgradeEnchantment (centerStackCopy , enchantment , level , false , enchanterBlockEntity .canOwnerApplyConflictingEnchantments ).getRight ();
349358 requiredExperience += currentRequired ;
350359 valid = true ;
351360 } else {
@@ -370,8 +379,8 @@ public static int getRequiredExperienceToEnchantCenterItem(@NotNull EnchanterBlo
370379 * @param level The enchantments level
371380 * @return The required experience to enchant. -1 if the enchantment is not applicable
372381 */
373- public static int getRequiredExperienceToEnchantWithEnchantment (ItemStack stack , Enchantment enchantment , int level , boolean allowEnchantmentConflicts ) {
374- if (!enchantment .isAcceptableItem (stack ) && !SpectrumEnchantmentHelper .isEnchantableBook (stack )) {
382+ public static int getRequiredExperienceToEnchantWithEnchantment (ItemStack stack , RegistryEntry < Enchantment > enchantment , int level , boolean allowEnchantmentConflicts ) {
383+ if (!enchantment .value (). isAcceptableItem (stack ) && !SpectrumEnchantmentHelper .isEnchantableBook (stack )) {
375384 return -1 ;
376385 }
377386
@@ -380,7 +389,7 @@ public static int getRequiredExperienceToEnchantWithEnchantment(ItemStack stack,
380389 return -1 ;
381390 }
382391
383- boolean conflicts = SpectrumEnchantmentHelper . hasEnchantmentThatConflictsWith (stack , enchantment );
392+ boolean conflicts = ! EnchantmentHelper . isCompatible (stack . getEnchantments (). getEnchantments () , enchantment );
384393 if (conflicts && !allowEnchantmentConflicts ) {
385394 return -1 ;
386395 }
@@ -392,31 +401,26 @@ public static int getRequiredExperienceToEnchantWithEnchantment(ItemStack stack,
392401 return requiredExperience ;
393402 }
394403
395- public static Integer getEnchantingPrice (ItemStack stack , Enchantment enchantment , int level ) {
404+ public static Integer getEnchantingPrice (ItemStack stack , RegistryEntry < Enchantment > enchantment , int level ) {
396405 int enchantability = Math .max (1 , stack .getItem ().getEnchantability ()); // items like Elytras have an enchantability of 0, but can get unbreaking
397- if (enchantment .isAcceptableItem (stack ) || SpectrumEnchantmentHelper .isEnchantableBook (stack )) {
406+ if (enchantment .value (). isAcceptableItem (stack ) || SpectrumEnchantmentHelper .isEnchantableBook (stack )) {
398407 return getRequiredExperienceForEnchantment (enchantability , enchantment , level );
399408 }
400409 return -1 ;
401410 }
402411
403- public static int getRequiredExperienceForEnchantment (int enchantability , Enchantment enchantment , int level ) {
412+ public static int getRequiredExperienceForEnchantment (int enchantability , RegistryEntry < Enchantment > entry , int level ) {
404413 if (enchantability > 0 ) {
405- int rarityCost ;
406- Enchantment .Rarity rarity = enchantment .getRarity ();
407- switch (rarity ) {
408- case COMMON -> rarityCost = 10 ;
409- case UNCOMMON -> rarityCost = 25 ;
410- case RARE -> rarityCost = 50 ;
411- default -> rarityCost = 80 ;
412- }
413-
414+ var enchantment = entry .value ();
415+
416+ // Interpolated version of COMMON -> 10, UNCOMMON -> 25, RARE -> 50, VERY_RARE -> 80
417+ var rarityMults = new float [] { 0 , 10 , 12.5F , 12.67F , 12.5F , 12 , 11.33F , 10.71F , 10 };
418+ var anvilCost = enchantment .getAnvilCost ();
419+ var rarityCost = rarityMults [Math .min (anvilCost , rarityMults .length - 1 )] * anvilCost ;
420+
414421 float levelCost = level + ((float ) level / enchantment .getMaxLevel ()); // the higher the level, the pricier. But not as bad for enchantments with high max levels
415- float specialMulti = enchantment .isTreasure () ? 2.0F : enchantment .isCursed () ? 1.5F : 1.0F ;
416- float selectionAvailabilityMod = 1.0F ;
417- if (!(enchantment instanceof SpectrumEnchantment )) {
418- selectionAvailabilityMod = (enchantment .isAvailableForRandomSelection () ? 0.5F : 0.75F ) + (enchantment .isAvailableForEnchantedBookOffer () ? 0.5F : 0.75F );
419- }
422+ float specialMulti = entry .isIn (EnchantmentTags .TREASURE ) ? 2.0F : entry .isIn (EnchantmentTags .CURSE ) ? 1.5F : 1.0F ;
423+ float selectionAvailabilityMod = (entry .isIn (EnchantmentTags .IN_ENCHANTING_TABLE ) ? 0.5F : 0.75F ) + (entry .isIn (EnchantmentTags .TRADEABLE ) ? 0.5F : 0.75F );
420424 float enchantabilityMod = (4.0F / (2 + enchantability )) * 4.0F ;
421425 return (int ) Math .floor (rarityCost * levelCost * specialMulti * selectionAvailabilityMod * enchantabilityMod );
422426 }
@@ -548,7 +552,7 @@ private static void calculateCurrentRecipe(@NotNull World world, @NotNull Enchan
548552 }
549553
550554 enchanterBlockEntity .craftingTime = 0 ;
551- GatedSpectrumRecipe previousRecipe = enchanterBlockEntity .currentRecipe ;
555+ GatedSpectrumRecipe <?> previousRecipe = enchanterBlockEntity .currentRecipe ;
552556 enchanterBlockEntity .currentRecipe = null ;
553557 int previousOrientation = enchanterBlockEntity .virtualInventoryRecipeOrientation ;
554558 boolean previousMirrored = enchanterBlockEntity .virtualInventoryRecipeMirrored ;
0 commit comments