Several recipe improvements

- Some performance improvements to JEI recipe resolver
   - Use a shared map for upgrade items, meaning we only need one map
     lookup.
   - Cache the basic upgrade recipes.
 - Use the MC version within project rather than version name.
This commit is contained in:
SquidDev 2019-03-19 11:47:12 +00:00
parent 71b1f8138d
commit e46f09a939
24 changed files with 157 additions and 105 deletions

View File

@ -25,39 +25,37 @@
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
apply plugin: 'maven' apply plugin: 'maven'
def mc_version = "1.12.2" version = mod_version
def main_version = "1.81.1"
version = "${mc_version}-${main_version}"
group = "org.squiddev" group = "org.squiddev"
archivesBaseName = "cc-tweaked" archivesBaseName = "cc-tweaked-${mc_version}"
minecraft { minecraft {
version = "${mc_version}-14.23.4.2749" version = "${mc_version}-${forge_version}"
runDir = "run" runDir = "run"
replace '${version}', main_version replace '${version}', mod_version
// the mappings can be changed at any time, and must be in the following format. mappings = mappings_version
// snapshot_YYYYMMDD snapshot are built nightly. makeObfSourceJar = false
// stable_# stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not allways work.
// simply re-run your setup task after changing the mappings to update your workspace.
mappings = "snapshot_20180724"
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
} }
repositories { repositories {
maven { maven {
name = "JEI" name "JEI"
url = "http://dvs1.progwml6.com/files/maven" url "http://dvs1.progwml6.com/files/maven"
} }
maven { maven {
name = "squiddev" name "SquidDev"
url = "https://squiddev.cc/maven" url "https://squiddev.cc/maven"
}
ivy {
name "Charset"
artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]"
}
maven {
name "Amadornes"
url "http://maven.amadornes.com/"
} }
ivy { artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]" }
maven { url "http://maven.amadornes.com/" }
} }
configurations { configurations {
@ -152,7 +150,7 @@ task proguardMove(dependsOn: proguard) {
reobfJar.dependsOn proguardMove reobfJar.dependsOn proguardMove
processResources { processResources {
inputs.property "version", main_version inputs.property "version", mod_version
inputs.property "mcversion", mc_version inputs.property "mcversion", mc_version
def hash = 'none' def hash = 'none'
@ -174,7 +172,7 @@ task proguardMove(dependsOn: proguard) {
include 'mcmod.info' include 'mcmod.info'
include 'assets/computercraft/lua/rom/help/credits.txt' include 'assets/computercraft/lua/rom/help/credits.txt'
expand 'version': main_version, expand 'version': mod_version,
'mcversion': mc_version, 'mcversion': mc_version,
'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n') 'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
} }
@ -260,22 +258,22 @@ task compressJson(dependsOn: extractAnnotationsJar) {
pom.project { pom.project {
name 'CC: Tweaked' name 'CC: Tweaked'
packaging 'jar' packaging 'jar'
description 'A fork of ComputerCraft which aims to provide earlier access to the more experimental and in-development features of the mod.' description 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
url 'https://github.com/SquidDev-CC/CC-Tweaked' url 'https://github.com/SquidDev-CC/CC-Tweaked'
scm { scm {
url 'https://github.com/dan200/ComputerCraft.git' url 'https://github.com/SquidDev-CC/CC-Tweaked.git'
} }
issueManagement { issueManagement {
system 'github' system 'github'
url 'https://github.com/dan200/ComputerCraft/issues' url 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
} }
licenses { licenses {
license { license {
name 'ComputerCraft Public License, Version 1.0' name 'ComputerCraft Public License, Version 1.0'
url 'https://github.com/dan200/ComputerCraft/blob/master/LICENSE' url 'https://github.com/SquidDev-CC/CC-Tweaked/blob/master/LICENSE'
distribution 'repo' distribution 'repo'
} }
} }
@ -298,7 +296,7 @@ task compressJson(dependsOn: extractAnnotationsJar) {
gradle.projectsEvaluated { gradle.projectsEvaluated {
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint" options.compilerArgs << "-Xlint" << "-Xlint:-processing" << "-Werror"
} }
} }

7
gradle.properties Normal file
View File

@ -0,0 +1,7 @@
# Mod properties
mod_version=1.81.1
# Minecraft properties
mc_version=1.12.2
forge_version=14.23.4.2749
mappings_version=snapshot_20180724

View File

@ -1 +1 @@
rootProject.name = 'cc-tweaked' rootProject.name = "cc-tweaked-${mc_version}"

View File

@ -25,7 +25,6 @@
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*; import java.util.*;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@ -34,8 +33,9 @@ class RecipeResolver implements IRecipeRegistryPlugin
{ {
static final ComputerFamily[] MAIN_FAMILIES = new ComputerFamily[] { ComputerFamily.Normal, ComputerFamily.Advanced }; static final ComputerFamily[] MAIN_FAMILIES = new ComputerFamily[] { ComputerFamily.Normal, ComputerFamily.Advanced };
private final Map<Item, List<ITurtleUpgrade>> turtleUpgrades = new HashMap<>(); private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
private final Map<Item, List<IPocketUpgrade>> pocketUpgrades = new HashMap<>(); private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
private final List<UpgradeInfo> turtleUpgrades = new ArrayList<>();
private boolean initialised = false; private boolean initialised = false;
/** /**
@ -50,51 +50,38 @@ private void setupCache()
{ {
ItemStack stack = upgrade.getCraftingItem(); ItemStack stack = upgrade.getCraftingItem();
if( stack.isEmpty() ) continue; if( stack.isEmpty() ) continue;
turtleUpgrades.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( upgrade );
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
turtleUpgrades.add( info );
} }
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() ) for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() )
{ {
ItemStack stack = upgrade.getCraftingItem(); ItemStack stack = upgrade.getCraftingItem();
if( stack.isEmpty() ) continue; if( stack.isEmpty() ) continue;
pocketUpgrades.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( upgrade );
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
pocketUpgrades.add( info );
} }
} }
@Nullable private boolean hasUpgrade( @Nonnull ItemStack stack )
private ITurtleUpgrade getTurtleUpgrade( @Nonnull ItemStack stack )
{ {
if( stack.isEmpty() ) return null; if( stack.isEmpty() ) return false;
setupCache(); setupCache();
List<ITurtleUpgrade> upgrades = turtleUpgrades.get( stack.getItem() ); List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
if( upgrades == null ) return null; if( upgrades == null ) return false;
for( ITurtleUpgrade upgrade : upgrades ) for( UpgradeInfo upgrade : upgrades )
{ {
ItemStack craftingStack = upgrade.getCraftingItem(); ItemStack craftingStack = upgrade.stack;
if( !craftingStack.isEmpty() && InventoryUtil.areItemsSimilar( stack, craftingStack ) ) return upgrade; if( !craftingStack.isEmpty() && InventoryUtil.areItemsSimilar( stack, craftingStack ) ) return true;
} }
return null; return false;
}
@Nullable
private IPocketUpgrade getPocketUpgrade( @Nonnull ItemStack stack )
{
if( stack.isEmpty() ) return null;
setupCache();
List<IPocketUpgrade> upgrades = pocketUpgrades.get( stack.getItem() );
if( upgrades == null ) return null;
for( IPocketUpgrade upgrade : upgrades )
{
ItemStack craftingStack = upgrade.getCraftingItem();
if( !craftingStack.isEmpty() && InventoryUtil.areItemsSimilar( stack, craftingStack ) ) return upgrade;
}
return null;
} }
@Nonnull @Nonnull
@ -109,7 +96,7 @@ public <V> List<String> getRecipeCategoryUids( @Nonnull IFocus<V> focus )
{ {
case INPUT: case INPUT:
return stack.getItem() instanceof ITurtleItem || stack.getItem() instanceof ItemPocketComputer || return stack.getItem() instanceof ITurtleItem || stack.getItem() instanceof ItemPocketComputer ||
getTurtleUpgrade( stack ) != null || getPocketUpgrade( stack ) != null hasUpgrade( stack )
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING ) ? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
: Collections.emptyList(); : Collections.emptyList();
case OUTPUT: case OUTPUT:
@ -152,6 +139,8 @@ public <T extends IRecipeWrapper> List<T> getRecipeWrappers( @Nonnull IRecipeCat
@Nonnull @Nonnull
private List<Shaped> findRecipesWithInput( @Nonnull ItemStack stack ) private List<Shaped> findRecipesWithInput( @Nonnull ItemStack stack )
{ {
setupCache();
if( stack.getItem() instanceof ITurtleItem ) if( stack.getItem() instanceof ITurtleItem )
{ {
// Suggest possible upgrades which can be applied to this turtle // Suggest possible upgrades which can be applied to this turtle
@ -161,16 +150,17 @@ private List<Shaped> findRecipesWithInput( @Nonnull ItemStack stack )
if( left != null && right != null ) return Collections.emptyList(); if( left != null && right != null ) return Collections.emptyList();
List<Shaped> recipes = new ArrayList<>(); List<Shaped> recipes = new ArrayList<>();
for( ITurtleUpgrade upgrade : TurtleUpgrades.getUpgrades() ) for( UpgradeInfo upgrade : turtleUpgrades )
{ {
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
if( left == null ) if( left == null )
{ {
recipes.add( horizontal( asList( stack, upgrade.getCraftingItem() ), turtleWith( stack, upgrade, right ) ) ); recipes.add( horizontal( asList( stack, upgrade.stack ), turtleWith( stack, upgrade.turtle, right ) ) );
} }
if( right == null ) if( right == null )
{ {
recipes.add( horizontal( asList( stack, upgrade.getCraftingItem() ), turtleWith( stack, left, upgrade ) ) ); recipes.add( horizontal( asList( upgrade.stack, stack ), turtleWith( stack, left, upgrade.turtle ) ) );
} }
} }
@ -184,40 +174,44 @@ else if( stack.getItem() instanceof ItemPocketComputer )
if( back != null ) return Collections.emptyList(); if( back != null ) return Collections.emptyList();
List<Shaped> recipes = new ArrayList<>(); List<Shaped> recipes = new ArrayList<>();
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() ) for( UpgradeInfo upgrade : pocketUpgrades )
{ {
recipes.add( vertical( asList( stack, upgrade.getCraftingItem() ), pocketWith( stack, upgrade ) ) ); recipes.add( vertical( asList( stack, upgrade.stack ), pocketWith( stack, upgrade.pocket ) ) );
} }
return recipes; return recipes;
} }
else else
{ {
// Find places this may be used as an upgrade. List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
ITurtleUpgrade turtle = getTurtleUpgrade( stack ); if( upgrades == null ) return Collections.emptyList();
IPocketUpgrade pocket = getPocketUpgrade( stack );
if( turtle == null && pocket == null ) return Collections.emptyList();
List<Shaped> recipes = new ArrayList<>( 1 ); List<Shaped> recipes = null;
for( ComputerFamily family : MAIN_FAMILIES ) boolean multiple = false;
for( UpgradeInfo upgrade : upgrades )
{ {
if( turtle != null && TurtleUpgrades.suitableForFamily( family, turtle ) ) ItemStack craftingStack = upgrade.stack;
if( craftingStack.isEmpty() || !InventoryUtil.areItemsSimilar( stack, craftingStack ) )
{ {
recipes.add( horizontal( continue;
asList( stack, TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ),
TurtleItemFactory.create( -1, null, -1, family, turtle, null, 0, null )
) );
} }
if( pocket != null ) if( recipes == null )
{ {
recipes.add( vertical( recipes = upgrade.getRecipes();
asList( stack, PocketComputerItemFactory.create( -1, null, -1, family, null ) ), }
PocketComputerItemFactory.create( -1, null, -1, family, pocket ) else
) ); {
if( !multiple )
{
multiple = true;
recipes = new ArrayList<>( recipes );
}
recipes.addAll( upgrade.getRecipes() );
} }
} }
return recipes;
return recipes == null ? Collections.emptyList() : recipes;
} }
} }
@ -233,14 +227,15 @@ private List<Shaped> findRecipesWithOutput( @Nonnull ItemStack stack )
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.Left ); ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.Left );
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.Right ); ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.Right );
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
if( left != null ) if( left != null )
{ {
recipes.add( horizontal( asList( left.getCraftingItem(), turtleWith( stack, null, right ) ), stack ) ); recipes.add( horizontal( asList( turtleWith( stack, null, right ), left.getCraftingItem() ), stack ) );
} }
if( right != null ) if( right != null )
{ {
recipes.add( horizontal( asList( turtleWith( stack, left, null ), right.getCraftingItem() ), stack ) ); recipes.add( horizontal( asList( right.getCraftingItem(), turtleWith( stack, left, null ) ), stack ) );
} }
return cast( recipes ); return cast( recipes );
@ -298,7 +293,7 @@ private static Shaped horizontal( List<ItemStack> input, ItemStack result )
return new Shaped( input.size(), 1, input, result ); return new Shaped( input.size(), 1, input, result );
} }
static class Shaped implements IShapedCraftingRecipeWrapper private static class Shaped implements IShapedCraftingRecipeWrapper
{ {
private final int width; private final int width;
private final int height; private final int height;
@ -332,4 +327,55 @@ public void getIngredients( @Nonnull IIngredients ingredients )
ingredients.setOutput( VanillaTypes.ITEM, output ); ingredients.setOutput( VanillaTypes.ITEM, output );
} }
} }
private static class UpgradeInfo
{
final ItemStack stack;
final ITurtleUpgrade turtle;
final IPocketUpgrade pocket;
ArrayList<Shaped> recipes;
UpgradeInfo( ItemStack stack, ITurtleUpgrade turtle )
{
this.stack = stack;
this.turtle = turtle;
this.pocket = null;
}
UpgradeInfo( ItemStack stack, IPocketUpgrade pocket )
{
this.stack = stack;
this.turtle = null;
this.pocket = pocket;
}
List<Shaped> getRecipes()
{
ArrayList<Shaped> recipes = this.recipes;
if( recipes != null ) return recipes;
recipes = this.recipes = new ArrayList<>( 4 );
for( ComputerFamily family : MAIN_FAMILIES )
{
if( turtle != null && TurtleUpgrades.suitableForFamily( family, turtle ) )
{
recipes.add( horizontal(
asList( stack, TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ),
TurtleItemFactory.create( -1, null, -1, family, null, turtle, 0, null )
) );
}
if( pocket != null )
{
recipes.add( vertical(
asList( stack, PocketComputerItemFactory.create( -1, null, -1, family, null ) ),
PocketComputerItemFactory.create( -1, null, -1, family, pocket )
) );
}
}
recipes.trimToSize();
return recipes;
}
}
} }

View File

@ -42,6 +42,7 @@ public PocketServerComputer( World world, int computerID, String label, int inst
@Nullable @Nullable
@Override @Override
@Deprecated
public Entity getEntity() public Entity getEntity()
{ {
return m_entity; return m_entity;

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "computercraft:advanced_modem" }, "#": { "item": "computercraft:advanced_modem" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "computercraft:peripheral", "data": 5 }, "#": { "item": "computercraft:peripheral", "data": 5 },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "computercraft:peripheral", "data": 1 }, "#": { "item": "computercraft:peripheral", "data": 1 },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:crafting_table" }, "#": { "item": "minecraft:crafting_table" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_axe" }, "#": { "item": "minecraft:diamond_axe" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_hoe" }, "#": { "item": "minecraft:diamond_hoe" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_pickaxe" }, "#": { "item": "minecraft:diamond_pickaxe" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_shovel" }, "#": { "item": "minecraft:diamond_shovel" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_advanced", "group": "computercraft:upgrade_turtle_advanced",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_sword" }, "#": { "item": "minecraft:diamond_sword" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "computercraft:advanced_modem" }, "#": { "item": "computercraft:advanced_modem" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "computercraft:peripheral", "data": 5 }, "#": { "item": "computercraft:peripheral", "data": 5 },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "computercraft:peripheral", "data": 1 }, "#": { "item": "computercraft:peripheral", "data": 1 },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:crafting_table" }, "#": { "item": "minecraft:crafting_table" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_axe" }, "#": { "item": "minecraft:diamond_axe" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_hoe" }, "#": { "item": "minecraft:diamond_hoe" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_pickaxe" }, "#": { "item": "minecraft:diamond_pickaxe" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_shovel" }, "#": { "item": "minecraft:diamond_shovel" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_normal", "group": "computercraft:upgrade_turtle_normal",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": "minecraft:diamond_sword" }, "#": { "item": "minecraft:diamond_sword" },

View File

@ -2,7 +2,7 @@
"type": "computercraft:impostor_shaped", "type": "computercraft:impostor_shaped",
"group": "computercraft:upgrade_turtle_${turtle_family}", "group": "computercraft:upgrade_turtle_${turtle_family}",
"pattern": [ "pattern": [
"T#" "#T"
], ],
"key": { "key": {
"#": { "item": ${upgrade_item} }, "#": { "item": ${upgrade_item} },