Files
meatballcraft/scripts/enchantwrapper/EnchantUtil.zs
T
sainagh 0a09116c6e 0.16
2024-08-18 18:25:41 -07:00

145 lines
4.5 KiB
Plaintext

#priority 10
#reloadable
import crafttweaker.data.IData;
import crafttweaker.enchantments.IEnchantment;
import crafttweaker.item.IItemStack;
import mods.contenttweaker.ResourceLocation;
import mods.zenutils.StaticString;
/**
Same as IEnchantment#makeTag(), but uses int enchant id.
Useful if you have JEID extending enchantment ids.
**/
function makeIntTag(enchant as IEnchantment, isBook as bool) as IData {
var key = "ench";
if (isBook) {
key = "StoredEnchantments";
}
return {
`${key}`: [{
id: enchant.definition.id,
lvl: enchant.level
}]
} as IData;
}
/**
From a superenchant_wrapper item, return the actual superenchanted item.
**/
function unwrap(item as IItemStack) as IItemStack {
if (item.definition.id != "contenttweaker:superenchant_wrapper" || !item.hasTag) {
return null;
}
var out as IItemStack = <item:${item.tag.id}>.withDamage(item.damage);
var enchList = {} as IData;
// Convert delayed enchants to actual enchants.
for enchant in item.tag.delayedEnch.asList() {
// A singleton map of the enchant.
for name, level in enchant.asMap() {
enchList += makeIntTag(<enchantment:${name}>.makeEnchantment(level), false);
}
}
out = out.withTag(item.tag.tag + enchList);
return out;
}
/**
From a superenchant_wrapper item, return a representation of the superenchanted item, split in two items.
1) The actual item to be superenchanted, with all NBT data EXCEPT enchants.
2) An enchanted book with a list of all the enchants that will be applied to the item.
This two-fold representation is needed to display the correct enchants after JEI has already loaded
the recipe, and to preserve the usual "Show recipe/usages" functionality.
**/
function unwrapJEI(wrapper as IItemStack) as IItemStack[] {
if (wrapper.definition.id != "contenttweaker:superenchant_wrapper" || !wrapper.hasTag) {
return null;
}
var base as IItemStack = <item:${wrapper.tag.id}>
.withDamage(wrapper.damage)
.withTag(wrapper.tag.tag);
// Use an extra tag to make sure only this item has its tooltip removed.
val fromJEI = {
fromJEI: true
} as IData;
base = base.withTag(base.tag + fromJEI);
// Add a dummy enchant to the item for the glow.
val dummyEnchant = <enchantment:minecraft:protection>.makeEnchantment(1);
base.addEnchantment(dummyEnchant);
base.removeTooltip(dummyEnchant.displayName);
// Unique identifier for the book when running addAdvancedTooltip.
val identifier = {
id: wrapper.tag.id,
delayedEnch: wrapper.tag.delayedEnch
} as IData;
var book as IItemStack = <minecraft:enchanted_book>.withTag(identifier);
// Setup transformer on book to run later.
// This transforms the book, not the item, because we want to keep recipe lookup functionality
// for the superenchanted item.
var transformed = book.transformNew(function(item) {
var enchList = {} as IData;
for enchant in wrapper.tag.delayedEnch.asList() {
for name, level in enchant.asMap() {
enchList += makeIntTag(<enchantment:${name}>.makeEnchantment(level), true);
}
}
return item.withTag(enchList).withLore(["The superenchanted item will have these enchants"]);
});
// Run the transformer on book tooltip hover.
book.addAdvancedTooltip(function(item) {
transformed.applyNewTransform(item);
return null;
});
return [base, book] as IItemStack[];
}
/**
Holds a map of (ResourceLocation name, int level) enchantment entries with
predictable iteration order (insertion order).
Making an instance would look something like this:
`EnchantMap().add(name1, level1).add(name2, level2)...;`
**/
zenClass EnchantMap {
val enchants as int[ResourceLocation];
zenConstructor() {
enchants = {} as int[ResourceLocation]$orderly;
}
function add(name as string, level as int) as EnchantMap {
if (StaticString.countMatches(name, ':') != 1) {
print("EnchantWrapper.EnchantMap.zs - Add to map failed! name: " + name + " level:" + level);
}
else {
enchants[ResourceLocation.create(name)] = level;
}
return this;
}
function getMap() as int[ResourceLocation] {
return this.enchants;
}
}
/**
Registry that holds all registered superenchant_wrapper items.
For use in EnchantWrapper.SuperEnchantedItem.
**/
zenClass WrapperRegistry {
static INSTANCE = WrapperRegistry();
val wrapperItems as IItemStack[];
zenConstructor() {
wrapperItems = [] as IItemStack[];
}
function add(wrapper as IItemStack) {
wrapperItems += wrapper;
}
function get() as IItemStack[] {
return this.wrapperItems;
}
}