1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-11 18:00:29 +00:00

Basic Minetweaker support (#327)

This provides the following methods:

 - dan200.computercraft.turtle.removeUpgrade(id: String)
 - dan200.computercraft.turtle.removeUpgrade(stack: IItemStack)
 - dan200.computercraft.turtle.addTool(id: String, craftItem: IItemStack[, toolItem: IItemStack][, kind: string])

While it's pretty minimal, it should allow for a reasonable amount of
functionality.

Closes #327 and #97.
This commit is contained in:
Jonathan Coates 2019-12-18 15:29:24 +00:00 committed by GitHub
parent 03b6d2f1ab
commit 3a5d50e572
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 409 additions and 46 deletions

View File

@ -59,6 +59,10 @@ repositories {
name "Amadornes"
url "https://maven.amadornes.com/"
}
maven {
name "CraftTweaker"
url "https://maven.blamejared.com/"
}
}
configurations {
@ -70,9 +74,10 @@ configurations {
dependencies {
checkstyle "com.puppycrawl.tools:checkstyle:8.25"
deobfProvided "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.554"
deobfProvided "MCMultiPart2:MCMultiPart:2.5.3"
deobfProvided "mezz.jei:jei_1.12.2:4.15.0.269:api"
deobfProvided "pl.asie:Charset-Lib:0.5.4.6"
deobfProvided "MCMultiPart2:MCMultiPart:2.5.3"
runtime "mezz.jei:jei_1.12.2:4.15.0.269"

View File

@ -19,12 +19,35 @@ import net.minecraftforge.fml.common.ModContainer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Stream;
public final class TurtleUpgrades
{
public static class Wrapper
{
final ITurtleUpgrade upgrade;
final int legacyId;
final String id;
final String modId;
boolean enabled;
public Wrapper( ITurtleUpgrade upgrade )
{
ModContainer mc = Loader.instance().activeModContainer();
this.upgrade = upgrade;
this.legacyId = upgrade.getLegacyUpgradeID();
this.id = upgrade.getUpgradeID().toString();
this.modId = mc != null && mc.getModId() != null ? mc.getModId() : null;
this.enabled = true;
}
}
private static ITurtleUpgrade[] vanilla;
private static final Map<String, ITurtleUpgrade> upgrades = new HashMap<>();
private static final Int2ObjectMap<ITurtleUpgrade> legacyUpgrades = new Int2ObjectOpenHashMap<>();
private static final IdentityHashMap<ITurtleUpgrade, String> upgradeOwners = new IdentityHashMap<>();
private static final IdentityHashMap<ITurtleUpgrade, Wrapper> wrappers = new IdentityHashMap<>();
private TurtleUpgrades() {}
@ -35,9 +58,7 @@ public final class TurtleUpgrades
int id = upgrade.getLegacyUpgradeID();
if( id >= 0 && id < 64 )
{
String message = getMessage( upgrade, "Legacy UpgradeID '" + id + "' is reserved by ComputerCraft" );
ComputerCraft.log.error( message );
throw new RuntimeException( message );
throw registrationError( upgrade, "Legacy Upgrade ID '" + id + "' is reserved by ComputerCraft" );
}
registerInternal( upgrade );
@ -47,58 +68,63 @@ public final class TurtleUpgrades
{
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
Wrapper wrapper = new Wrapper( upgrade );
// Check conditions
int legacyId = upgrade.getLegacyUpgradeID();
int legacyId = wrapper.legacyId;
if( legacyId >= 0 )
{
if( legacyId >= Short.MAX_VALUE )
{
String message = getMessage( upgrade, "UpgradeID '" + legacyId + "' is out of range" );
ComputerCraft.log.error( message );
throw new RuntimeException( message );
throw registrationError( upgrade, "Upgrade ID '" + legacyId + "' is out of range" );
}
ITurtleUpgrade existing = legacyUpgrades.get( legacyId );
if( existing != null )
{
String message = getMessage( upgrade, "UpgradeID '" + legacyId + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" );
ComputerCraft.log.error( message );
throw new RuntimeException( message );
throw registrationError( upgrade, "Upgrade ID '" + legacyId + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" );
}
}
String id = upgrade.getUpgradeID().toString();
String id = wrapper.id;
ITurtleUpgrade existing = upgrades.get( id );
if( existing != null )
{
String message = getMessage( upgrade, "UpgradeID '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" );
ComputerCraft.log.error( message );
throw new RuntimeException( message );
throw registrationError( upgrade, "Upgrade '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" );
}
// Register
if( legacyId >= 0 ) legacyUpgrades.put( legacyId, upgrade );
upgrades.put( id, upgrade );
ModContainer mc = Loader.instance().activeModContainer();
if( mc != null && mc.getModId() != null ) upgradeOwners.put( upgrade, mc.getModId() );
wrappers.put( upgrade, wrapper );
}
private static String getMessage( ITurtleUpgrade upgrade, String rest )
private static RuntimeException registrationError( ITurtleUpgrade upgrade, String rest )
{
return "Error registering '" + upgrade.getUnlocalisedAdjective() + " Turtle'. " + rest;
String message = "Error registering '" + upgrade.getUnlocalisedAdjective() + " Turtle'. " + rest;
ComputerCraft.log.error( message );
throw new IllegalArgumentException( message );
}
@Nullable
public static ITurtleUpgrade get( String id )
{
return upgrades.get( id );
}
@Nullable
public static ITurtleUpgrade get( int id )
{
return legacyUpgrades.get( id );
}
@Nullable
public static String getOwner( @Nonnull ITurtleUpgrade upgrade )
{
Wrapper wrapper = wrappers.get( upgrade );
return wrapper != null ? wrapper.modId : null;
}
public static ITurtleUpgrade get( @Nonnull ItemStack stack )
{
if( stack.isEmpty() ) return null;
@ -115,25 +141,24 @@ public final class TurtleUpgrades
return null;
}
public static Iterable<ITurtleUpgrade> getVanillaUpgrades()
public static Stream<ITurtleUpgrade> getVanillaUpgrades()
{
List<ITurtleUpgrade> vanilla = new ArrayList<>();
vanilla.add( ComputerCraft.TurtleUpgrades.diamondPickaxe );
vanilla.add( ComputerCraft.TurtleUpgrades.diamondAxe );
vanilla.add( ComputerCraft.TurtleUpgrades.diamondSword );
vanilla.add( ComputerCraft.TurtleUpgrades.diamondShovel );
vanilla.add( ComputerCraft.TurtleUpgrades.diamondHoe );
vanilla.add( ComputerCraft.TurtleUpgrades.craftingTable );
vanilla.add( ComputerCraft.TurtleUpgrades.wirelessModem );
vanilla.add( ComputerCraft.TurtleUpgrades.advancedModem );
vanilla.add( ComputerCraft.TurtleUpgrades.speaker );
return vanilla;
}
if( vanilla == null )
{
vanilla = new ITurtleUpgrade[] {
ComputerCraft.TurtleUpgrades.diamondPickaxe,
ComputerCraft.TurtleUpgrades.diamondAxe,
ComputerCraft.TurtleUpgrades.diamondSword,
ComputerCraft.TurtleUpgrades.diamondShovel,
ComputerCraft.TurtleUpgrades.diamondHoe,
ComputerCraft.TurtleUpgrades.craftingTable,
ComputerCraft.TurtleUpgrades.wirelessModem,
ComputerCraft.TurtleUpgrades.advancedModem,
ComputerCraft.TurtleUpgrades.speaker,
};
}
@Nullable
public static String getOwner( @Nonnull ITurtleUpgrade upgrade )
{
return upgradeOwners.get( upgrade );
return Arrays.stream( vanilla ).filter( x -> x != null && wrappers.get( x ).enabled );
}
public static Iterable<ITurtleUpgrade> getUpgrades()
@ -145,4 +170,14 @@ public final class TurtleUpgrades
{
return true;
}
public static void disable( ITurtleUpgrade upgrade )
{
Wrapper wrapper = wrappers.get( upgrade );
if( !wrapper.enabled ) return;
wrapper.enabled = false;
upgrades.remove( wrapper.id );
if( wrapper.legacyId >= 0 ) legacyUpgrades.remove( wrapper.legacyId );
}
}

View File

@ -0,0 +1,70 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.crafttweaker;
import crafttweaker.CraftTweakerAPI;
import crafttweaker.annotations.ModOnly;
import crafttweaker.annotations.ZenDoc;
import crafttweaker.annotations.ZenRegister;
import crafttweaker.api.item.IItemStack;
import crafttweaker.api.minecraft.CraftTweakerMC;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.integration.crafttweaker.actions.AddTurtleTool;
import dan200.computercraft.shared.integration.crafttweaker.actions.RemoveTurtleUpgradeByItem;
import dan200.computercraft.shared.integration.crafttweaker.actions.RemoveTurtleUpgradeByName;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
@ZenRegister
@ZenClass( "dan200.computercraft.turtle" )
@ModOnly( ComputerCraft.MOD_ID )
public class TurtleTweaker
{
@ZenMethod
@ZenDoc( "Remove a turtle upgrade with the given id" )
public static void removeUpgrade( String upgrade )
{
CraftTweakerAPI.apply( new RemoveTurtleUpgradeByName( upgrade ) );
}
@ZenMethod
@ZenDoc( "Remove a turtle upgrade crafted with the given item stack" )
public static void removeUpgrade( IItemStack stack )
{
CraftTweakerAPI.apply( new RemoveTurtleUpgradeByItem( CraftTweakerMC.getItemStack( stack ) ) );
}
@ZenMethod
@ZenDoc( "Add a new turtle tool with the given id, which crafts and acts using the given stack." )
public static void addTool( String id, IItemStack stack )
{
addTool( id, stack, stack, "tool" );
}
@ZenMethod
@ZenDoc( "Add a new turtle tool with the given id, which is crafted with one item, and uses another." )
public static void addTool( String id, IItemStack craftingStack, IItemStack toolStack )
{
addTool( id, craftingStack, toolStack, "tool" );
}
@ZenMethod
@ZenDoc( "Add a new turtle tool with the given id, which crafts and acts using the given stack. You may also" +
"specify a 'kind' of tool, which limits what blocks the turtle can break (for instance, an 'axe' may only break wood)." )
public static void addTool( String id, IItemStack stack, String kind )
{
addTool( id, stack, stack, kind );
}
@ZenMethod
@ZenDoc( "Add a new turtle tool with the given id, which is crafted with one item, and uses another. You may also" +
"specify a 'kind' of tool, which limits what blocks the turtle can break (for instance, an 'axe' may only break wood)." )
public static void addTool( String id, IItemStack craftingStack, IItemStack toolStack, String kind )
{
CraftTweakerAPI.apply( new AddTurtleTool( id, CraftTweakerMC.getItemStack( craftingStack ), CraftTweakerMC.getItemStack( toolStack ), kind ) );
}
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.crafttweaker.actions;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.TurtleUpgrades;
import dan200.computercraft.shared.turtle.upgrades.*;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* Register a new turtle tool.
*/
public class AddTurtleTool implements IAction
{
private interface Factory
{
TurtleTool create( ResourceLocation location, ItemStack craftItem, ItemStack toolItem );
}
private static final Map<String, Factory> kinds = new HashMap<>();
static
{
kinds.put( "tool", TurtleTool::new );
kinds.put( "axe", TurtleAxe::new );
kinds.put( "hoe", TurtleHoe::new );
kinds.put( "shovel", TurtleShovel::new );
kinds.put( "sword", TurtleSword::new );
}
private final String id;
private final ItemStack craftItem;
private final ItemStack toolItem;
private final String kind;
public AddTurtleTool( String id, ItemStack craftItem, ItemStack toolItem, String kind )
{
this.id = id;
this.craftItem = craftItem;
this.toolItem = toolItem;
this.kind = kind;
}
@Override
public void apply()
{
Factory factory = kinds.get( kind );
if( factory == null )
{
ComputerCraft.log.error( "Unknown turtle upgrade kind '{}' (this should have been rejected by verify!)", kind );
return;
}
try
{
TurtleUpgrades.register( factory.create( new ResourceLocation( id ), craftItem, toolItem ) );
}
catch( RuntimeException e )
{
ComputerCraft.log.error( "Registration of turtle tool failed", e );
}
}
@Override
public String describe()
{
return String.format( "Add new turtle %s '%s' (crafted with '%s', uses a '%s')", kind, id, craftItem, toolItem );
}
public Optional<String> getValidationProblem()
{
if( craftItem.isEmpty() ) return Optional.of( "Crafting item stack is empty." );
if( craftItem.hasTagCompound() && !craftItem.getTagCompound().isEmpty() )
{
return Optional.of( "Crafting item has NBT." );
}
if( toolItem.isEmpty() ) return Optional.of( "Tool item stack is empty." );
if( !kinds.containsKey( kind ) ) return Optional.of( String.format( "Unknown kind '%s'.", kind ) );
if( TurtleUpgrades.get( id ) != null )
{
return Optional.of( String.format( "An upgrade with the same name ('%s') has already been registered.", id ) );
}
return Optional.empty();
}
}

View File

@ -0,0 +1,32 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.crafttweaker.actions;
import java.util.Optional;
/**
* An extension of {@link IAction} with a single validation function, rather than two.
*/
public interface IAction extends crafttweaker.IAction
{
default Optional<String> getValidationProblem()
{
return Optional.empty();
}
@Override
default boolean validate()
{
return !getValidationProblem().isPresent();
}
@Override
default String describeInvalid()
{
return getValidationProblem().orElse( "No problems found." );
}
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.crafttweaker.actions;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.TurtleUpgrades;
import net.minecraft.item.ItemStack;
import java.util.Optional;
/**
* Removes a turtle upgrade crafted with the given stack.
*/
public class RemoveTurtleUpgradeByItem implements IAction
{
private final ItemStack stack;
public RemoveTurtleUpgradeByItem( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
ITurtleUpgrade upgrade = TurtleUpgrades.get( stack );
if( upgrade != null ) TurtleUpgrades.disable( upgrade );
}
@Override
public String describe()
{
return String.format( "Remove turtle upgrades crafted with '%s'", stack );
}
@Override
public Optional<String> getValidationProblem()
{
if( TurtleUpgrades.get( stack ) == null )
{
return Optional.of( String.format( "Unknown turtle upgrade crafted with '%s'.", stack ) );
}
return Optional.empty();
}
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.crafttweaker.actions;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.TurtleUpgrades;
import java.util.Optional;
/**
* Removes a turtle upgrade with the given id.
*/
public class RemoveTurtleUpgradeByName implements IAction
{
private final String id;
public RemoveTurtleUpgradeByName( String id )
{
this.id = id;
}
@Override
public void apply()
{
ITurtleUpgrade upgrade = TurtleUpgrades.get( id );
if( upgrade != null ) TurtleUpgrades.disable( upgrade );
}
@Override
public String describe()
{
return String.format( "Remove turtle upgrade '%s'", id );
}
@Override
public Optional<String> getValidationProblem()
{
if( TurtleUpgrades.get( id ) == null )
{
return Optional.of( String.format( "Unknown turtle upgrade '%s'.", id ) );
}
return Optional.empty();
}
}

View File

@ -48,13 +48,11 @@ public abstract class ItemTurtleBase extends ItemComputerBase implements ITurtle
ItemStack normalStack = TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null );
if( !normalStack.isEmpty() && normalStack.getItem() == this ) list.add( normalStack );
for( ITurtleUpgrade upgrade : TurtleUpgrades.getVanillaUpgrades() )
{
if( !TurtleUpgrades.suitableForFamily( family, upgrade ) ) continue;
ItemStack stack = TurtleItemFactory.create( -1, null, -1, family, null, upgrade, 0, null );
if( !stack.isEmpty() && stack.getItem() == this ) list.add( stack );
}
TurtleUpgrades.getVanillaUpgrades()
.filter( x -> TurtleUpgrades.suitableForFamily( family, x ) )
.map( x -> TurtleItemFactory.create( -1, null, -1, family, null, x, 0, null ) )
.filter( x -> !x.isEmpty() && x.getItem() == this )
.forEach( list::add );
}
@Nonnull

View File

@ -7,6 +7,7 @@
package dan200.computercraft.shared.turtle.upgrades;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
public class TurtleAxe extends TurtleTool
@ -21,6 +22,11 @@ public class TurtleAxe extends TurtleTool
super( id, legacyId, item );
}
public TurtleAxe( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
{
super( id, craftItem, toolItem );
}
@Override
protected float getDamageMultiplier()
{

View File

@ -35,6 +35,11 @@ public class TurtleHoe extends TurtleTool
super( id, legacyId, item );
}
public TurtleHoe( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
{
super( id, craftItem, toolItem );
}
@Override
protected boolean canBreakBlock( IBlockState state, World world, BlockPos pos, TurtlePlayer player )
{

View File

@ -35,6 +35,11 @@ public class TurtleShovel extends TurtleTool
super( id, legacyId, item );
}
public TurtleShovel( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
{
super( id, craftItem, toolItem );
}
@Override
protected boolean canBreakBlock( IBlockState state, World world, BlockPos pos, TurtlePlayer player )
{

View File

@ -10,6 +10,7 @@ import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@ -26,6 +27,11 @@ public class TurtleSword extends TurtleTool
super( id, legacyId, item );
}
public TurtleSword( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
{
super( id, craftItem, toolItem );
}
@Override
protected boolean canBreakBlock( IBlockState state, World world, BlockPos pos, TurtlePlayer player )
{

View File

@ -62,6 +62,12 @@ public class TurtleTool extends AbstractTurtleUpgrade
this.item = new ItemStack( item, 1, 0 );
}
public TurtleTool( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
{
super( id, -1, TurtleUpgradeType.Tool, craftItem );
this.item = toolItem;
}
@Nonnull
@Override
@SideOnly( Side.CLIENT )
@ -76,7 +82,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
);
Minecraft mc = Minecraft.getMinecraft();
return Pair.of(
mc.getRenderItem().getItemModelMesher().getItemModel( item ),
mc.getRenderItem().getItemModelMesher().getItemModel( getCraftingItem() ),
transform
);
}