fix commit
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
#modloaded randomtweaker
|
||||
#priority -10
|
||||
#reloadable
|
||||
|
||||
import mods.jei.JEI;
|
||||
import mods.randomtweaker.jei.IJeiPanel;
|
||||
import mods.randomtweaker.jei.IJeiUtils;
|
||||
import scripts.enchantwrapper.EnchantUtil;
|
||||
import scripts.enchantwrapper.EnchantUtil.WrapperRegistry;
|
||||
|
||||
var superenchantJEI as IJeiPanel = JEI.createJei("custom_superenchant", "Superenchants");
|
||||
superenchantJEI.setModid("MeatballCraft");
|
||||
superenchantJEI.setIcon(<contenttweaker:superenchant_wrapper>);
|
||||
superenchantJEI.addRecipeCatalyst(<contenttweaker:superenchant_wrapper>);
|
||||
superenchantJEI.setBackground(IJeiUtils.createBackground(150, 55));
|
||||
superenchantJEI.addSlot(IJeiUtils.createItemSlot(40, 25, true)); // input
|
||||
superenchantJEI.addSlot(IJeiUtils.createItemSlot(95, 25, false)); // output
|
||||
superenchantJEI.addSlot(IJeiUtils.createItemSlot(110, 0, false, false)); // list of enchants
|
||||
superenchantJEI.addElement(IJeiUtils.createArrowElement(64, 25, 0));
|
||||
superenchantJEI.addElement(IJeiUtils.createImageElement("mouseLeft", 68, 6, 13, 14, 0, 0, "contenttweaker:textures/gui/mouse_right.png", 16, 16));
|
||||
superenchantJEI.onTooltip(function(mouseX, mouseY) as string[]{
|
||||
if (mouseX <= 81 && mouseX >= 68 && mouseY <= 22 && mouseY >= 6) {
|
||||
return ["Right-click"];
|
||||
}
|
||||
else if (mouseX <= 109 && mouseX >= 95 && mouseY <= 18 && mouseY >= 4) {
|
||||
return ["Will have these enchants"];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
superenchantJEI.addElement(IJeiUtils.createImageElement("enchantsIn", 95, 4, 14, 14, 0, 0, "contenttweaker:textures/gui/arrow_left_down.png", 18, 14));
|
||||
superenchantJEI.register();
|
||||
|
||||
for wrapperItem in WrapperRegistry.INSTANCE.get() {
|
||||
val recipe = JEI.createJeiRecipe("custom_superenchant");
|
||||
recipe.addInput(wrapperItem);
|
||||
recipe.setOutputs(EnchantUtil.unwrapJEI(wrapperItem));
|
||||
recipe.build();
|
||||
}
|
||||
JEI.addItemNBTSubtype(<contenttweaker:superenchant_wrapper>);
|
||||
@@ -0,0 +1,145 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
#modloaded contenttweaker zenutils
|
||||
#loader crafttweaker
|
||||
#priority 9
|
||||
#reloadable
|
||||
|
||||
import crafttweaker.data.IData;
|
||||
import crafttweaker.item.IItemStack;
|
||||
import mods.contenttweaker.ResourceLocation;
|
||||
import mods.zenutils.DataUpdateOperation.APPEND;
|
||||
import mods.zenutils.StaticString;
|
||||
import scripts.enchantwrapper.EnchantUtil;
|
||||
import scripts.enchantwrapper.EnchantUtil.EnchantMap;
|
||||
import scripts.enchantwrapper.EnchantUtil.WrapperRegistry;
|
||||
|
||||
/**
|
||||
This script makes a wrapper item for enchanted items.
|
||||
This fixes a problem with existing worlds where new enchants being added/removed
|
||||
would cause CT recipes that output enchanted items to have the wrong enchants
|
||||
due to a shift in enchantment ids that CT cannot account for.
|
||||
**/
|
||||
|
||||
/**
|
||||
Controls the actual conversion of the wrapper item to the enchanted item on right click.
|
||||
**/
|
||||
<cotItem:superenchant_wrapper>.itemRightClick = function(stack, world, player, hand) {
|
||||
if (world.isRemote()) {
|
||||
return "FAIL";
|
||||
}
|
||||
val result as IItemStack = EnchantUtil.unwrap(stack);
|
||||
if (isNull(result)) {
|
||||
return "FAIL";
|
||||
}
|
||||
player.give(result);
|
||||
if (!player.creative) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
return "SUCCESS";
|
||||
};
|
||||
|
||||
zenClass SuperEnchantedItem {
|
||||
// The wrapperItem.
|
||||
var wrapperItem as IItemStack;
|
||||
|
||||
// The NBT to write to the wrapper.
|
||||
var mapNBT as IData;
|
||||
|
||||
/**
|
||||
Constructor to make the superenchant_wrapper item and write its necessary data
|
||||
to NBT. To get the resultant wrapper IItemStack, call:
|
||||
`SuperEnchantedItem(IItemStack item, EnchantMap enchants).getItem()`
|
||||
|
||||
item is the IItemStack to be superenchanted, possibly with any metadata/NBT.
|
||||
|
||||
enchants expects a populated EnchantMap object.
|
||||
**/
|
||||
zenConstructor(item as IItemStack, enchants as EnchantMap) {
|
||||
this.mapNBT = {} as IData;
|
||||
this.wrapperItem = <contenttweaker:superenchant_wrapper>;
|
||||
writeItemData(item, enchants.getMap());
|
||||
this.wrapperItem = this.wrapperItem.withTag(this.mapNBT);
|
||||
WrapperRegistry.INSTANCE.add(this.getItem());
|
||||
}
|
||||
|
||||
// Writes all necessary item data to wrapper's NBT.
|
||||
function writeItemData(item as IItemStack, enchants as int[ResourceLocation]) {
|
||||
this.mapNBT += {
|
||||
"id": item.definition.id
|
||||
} as IData;
|
||||
if (item.isDamageable) {
|
||||
this.mapNBT += {
|
||||
"damage": item.damage
|
||||
} as IData;
|
||||
}
|
||||
if (item.hasTag) {
|
||||
this.mapNBT += {
|
||||
"tag": item.tag - "ench"
|
||||
} as IData;
|
||||
}
|
||||
this.mapNBT += writeDelayedEnchants(enchants);
|
||||
writeDisplayData(item);
|
||||
}
|
||||
|
||||
// Write enchants to "delayedEnch" tag.
|
||||
function writeDelayedEnchants(enchants as int[ResourceLocation]) as IData {
|
||||
var enchantTags = {
|
||||
"delayedEnch": {
|
||||
}
|
||||
} as IData;
|
||||
for name, level in enchants {
|
||||
enchantTags = enchantTags.deepUpdate(this.writeTag(name, level), APPEND);
|
||||
}
|
||||
return enchantTags;
|
||||
}
|
||||
|
||||
// Writes tag for a single enchant.
|
||||
function writeTag(loc as ResourceLocation, level as int) as IData {
|
||||
val enchantTag = {
|
||||
"delayedEnch": [{
|
||||
`${loc.domain}:${loc.path}`: level
|
||||
}]
|
||||
} as IData;
|
||||
return enchantTag;
|
||||
}
|
||||
|
||||
// Writes the name/tooltip to display on the wrapper item.
|
||||
function writeDisplayData(item as IItemStack) {
|
||||
var info = ["§r§fItem: " + item.displayName] as string[];
|
||||
for enchantEntry in this.mapNBT.delayedEnch.asList() {
|
||||
for name, level in enchantEntry.asMap() {
|
||||
val enchant = <enchantment:${name}>.makeEnchantment(level);
|
||||
// Localization for level isn't loaded yet for some reason, let's just use the numeric level if needed.
|
||||
info += "§r§7" + StaticString.remove(enchant.displayName, "enchantment.level.");
|
||||
}
|
||||
}
|
||||
// Just use an IItemStack to easily store and copy lore.
|
||||
val tempCopy = this.wrapperItem.withLore(info) as IItemStack;
|
||||
this.mapNBT += {
|
||||
"display": {
|
||||
"Lore": tempCopy.tag.display.Lore,
|
||||
}
|
||||
} as IData;
|
||||
}
|
||||
|
||||
function getItem() as IItemStack {
|
||||
return this.wrapperItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
The scripts in this folder are not meant to be modified unless you need to change some functionality.
|
||||
You may want to change the modid for the JEI tab in EnchantJEI.zs. This can be any string, not just a specific modid.
|
||||
These scripts come from the "CT-EnchantWrapper" repo, see the repo's README for more details.
|
||||
Source: https://github.com/jchung01/CT-EnchantWrapper/
|
||||
@@ -0,0 +1,9 @@
|
||||
#loader contenttweaker
|
||||
import mods.contenttweaker.VanillaFactory;
|
||||
import mods.contenttweaker.ResourceLocation;
|
||||
|
||||
// The CoT item
|
||||
val wrapperItem = VanillaFactory.createItem("superenchant_wrapper");
|
||||
wrapperItem.maxStackSize = 1;
|
||||
wrapperItem.rarity = "epic";
|
||||
wrapperItem.register();
|
||||
Reference in New Issue
Block a user