mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-02-15 02:20:05 +00:00
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway. Old way to register a turtle/pocket computer upgrade: ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade"))); New way to register a turtle/pocket computer upgrade: First, define a serialiser for your turtle upgrade type: static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" ); public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE = SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) ); SERIALISERS.register(bus); // Call in your mod constructor. Now either create a JSON string or use a data generator to register your upgrades: class TurtleDataGenerator extends TurtleUpgradeDataProvider { @Override protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade ) simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade); } } See much better! In all seriousness, this does offer some benefits, namely that it's now possible to overwrite or create upgrades via datapacks. Actual changes: - Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions. - Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used to load upgrades from JSON files in datapacks, and then read/write them to network packets (much like recipe serialisers). - The upgrade registries now subscribe to datapack reload events. They find all JSON files in the data/$mod_id/computercraft/{turtle,pocket}_upgrades directories, parse them, and then register them as upgrades. Once datapacks have fully reloaded, these upgrades are then sent over the network to the client. - Add data generators for turtle and pocket computer upgrades, to make the creation of JSON files a bit easier. - Port all of CC:T's upgrades over to use the new system.
This commit is contained in:
parent
a4c5ecf8df
commit
7b7527ec80
4
src/generated/resources/data/computercraft/computercraft/pocket_upgrades/speaker.json
generated
Normal file
4
src/generated/resources/data/computercraft/computercraft/pocket_upgrades/speaker.json
generated
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:speaker",
|
||||
"item": "computercraft:speaker"
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:wireless_modem_advanced",
|
||||
"item": "computercraft:wireless_modem_advanced"
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:wireless_modem_normal",
|
||||
"item": "computercraft:wireless_modem_normal"
|
||||
}
|
4
src/generated/resources/data/computercraft/computercraft/turtle_upgrades/speaker.json
generated
Normal file
4
src/generated/resources/data/computercraft/computercraft/turtle_upgrades/speaker.json
generated
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:speaker",
|
||||
"item": "computercraft:speaker"
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:wireless_modem_advanced",
|
||||
"item": "computercraft:wireless_modem_advanced"
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:wireless_modem_normal",
|
||||
"item": "computercraft:wireless_modem_normal"
|
||||
}
|
4
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/crafting_table.json
generated
Normal file
4
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/crafting_table.json
generated
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:workbench",
|
||||
"item": "minecraft:crafting_table"
|
||||
}
|
5
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_axe.json
generated
Normal file
5
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_axe.json
generated
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "computercraft:tool",
|
||||
"item": "minecraft:diamond_axe",
|
||||
"damageMultiplier": 6.0
|
||||
}
|
5
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_hoe.json
generated
Normal file
5
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_hoe.json
generated
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "computercraft:tool",
|
||||
"item": "minecraft:diamond_hoe",
|
||||
"breakable": "computercraft:turtle_hoe_harvestable"
|
||||
}
|
4
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_pickaxe.json
generated
Normal file
4
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_pickaxe.json
generated
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "computercraft:tool",
|
||||
"item": "minecraft:diamond_pickaxe"
|
||||
}
|
5
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_shovel.json
generated
Normal file
5
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_shovel.json
generated
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "computercraft:tool",
|
||||
"item": "minecraft:diamond_shovel",
|
||||
"breakable": "computercraft:turtle_shovel_harvestable"
|
||||
}
|
6
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_sword.json
generated
Normal file
6
src/generated/resources/data/minecraft/computercraft/turtle_upgrades/diamond_sword.json
generated
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"type": "computercraft:tool",
|
||||
"item": "minecraft:diamond_sword",
|
||||
"damageMultiplier": 9.0,
|
||||
"breakable": "computercraft:turtle_sword_harvestable"
|
||||
}
|
@ -12,9 +12,6 @@ import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -79,27 +76,6 @@ public final class ComputerCraft
|
||||
public static int monitorWidth = 8;
|
||||
public static int monitorHeight = 6;
|
||||
|
||||
public static final class TurtleUpgrades
|
||||
{
|
||||
public static TurtleModem wirelessModemNormal;
|
||||
public static TurtleModem wirelessModemAdvanced;
|
||||
public static TurtleSpeaker speaker;
|
||||
|
||||
public static TurtleCraftingTable craftingTable;
|
||||
public static TurtleSword diamondSword;
|
||||
public static TurtleShovel diamondShovel;
|
||||
public static TurtleTool diamondPickaxe;
|
||||
public static TurtleAxe diamondAxe;
|
||||
public static TurtleHoe diamondHoe;
|
||||
}
|
||||
|
||||
public static final class PocketUpgrades
|
||||
{
|
||||
public static PocketModem wirelessModemNormal;
|
||||
public static PocketModem wirelessModemAdvanced;
|
||||
public static PocketSpeaker speaker;
|
||||
}
|
||||
|
||||
// Registries
|
||||
public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry();
|
||||
public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry();
|
||||
|
@ -15,14 +15,14 @@ import dan200.computercraft.api.network.IPacketNetwork;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.core.apis.ApiFactories;
|
||||
import dan200.computercraft.core.asm.GenericMethod;
|
||||
import dan200.computercraft.core.filesystem.FileMount;
|
||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||
import dan200.computercraft.shared.*;
|
||||
import dan200.computercraft.shared.BundledRedstone;
|
||||
import dan200.computercraft.shared.MediaProviders;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
@ -125,12 +125,6 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
GenericPeripheralProvider.addCapability( capability );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||
{
|
||||
TurtleUpgrades.register( upgrade );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
|
||||
{
|
||||
@ -149,12 +143,6 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
MediaProviders.register( provider );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
PocketUpgrades.register( upgrade );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IPacketNetwork getWirelessNetwork()
|
||||
|
@ -17,9 +17,7 @@ import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
@ -38,19 +36,14 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public final class ComputerCraftAPI
|
||||
{
|
||||
public static final String MOD_ID = "computercraft";
|
||||
|
||||
@Nonnull
|
||||
public static String getInstalledVersion()
|
||||
{
|
||||
return getInstance().getInstalledVersion();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
public static String getAPIVersion()
|
||||
{
|
||||
return getInstalledVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
||||
*
|
||||
@ -151,19 +144,6 @@ public final class ComputerCraftAPI
|
||||
getInstance().registerGenericCapability( capability );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new turtle turtle for use in ComputerCraft. After calling this,
|
||||
* users should be able to craft Turtles with your new turtle. It is recommended to call
|
||||
* this during the load() method of your mod.
|
||||
*
|
||||
* @param upgrade The turtle upgrade to register.
|
||||
* @see ITurtleUpgrade
|
||||
*/
|
||||
public static void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||
{
|
||||
getInstance().registerTurtleUpgrade( upgrade );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a bundled redstone provider to provide bundled redstone output for blocks.
|
||||
*
|
||||
@ -201,11 +181,6 @@ public final class ComputerCraftAPI
|
||||
getInstance().registerMediaProvider( provider );
|
||||
}
|
||||
|
||||
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
getInstance().registerPocketUpgrade( upgrade );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get the game-wide wireless network.
|
||||
*
|
||||
@ -286,16 +261,12 @@ public final class ComputerCraftAPI
|
||||
|
||||
void registerGenericCapability( @Nonnull Capability<?> capability );
|
||||
|
||||
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
||||
|
||||
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||
|
||||
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
|
||||
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
||||
|
||||
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||
|
||||
@Nonnull
|
||||
IPacketNetwork getWirelessNetwork();
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.shared;
|
||||
package dan200.computercraft.api;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@ -13,6 +13,9 @@ import net.minecraft.tags.Tag;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
/**
|
||||
* Tags provided by ComputerCraft.
|
||||
*/
|
||||
public class ComputerCraftTags
|
||||
{
|
||||
public static class Items
|
||||
@ -35,9 +38,24 @@ public class ComputerCraftTags
|
||||
public static final Tag.Named<Block> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final Tag.Named<Block> MONITOR = make( "monitor" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken by any turtle tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_ALWAYS_BREAKABLE = make( "turtle_always_breakable" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken by the default shovel tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_SHOVEL_BREAKABLE = make( "turtle_shovel_harvestable" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken with the default sword tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_SWORD_BREAKABLE = make( "turtle_sword_harvestable" );
|
||||
|
||||
/**
|
||||
* Blocks which can be broken with the default hoe tool.
|
||||
*/
|
||||
public static final Tag.Named<Block> TURTLE_HOE_BREAKABLE = make( "turtle_hoe_harvestable" );
|
||||
|
||||
private static Tag.Named<Block> make( String name )
|
@ -5,15 +5,11 @@
|
||||
*/
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraftforge.common.util.NonNullSupplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link IPocketUpgrade}s.
|
||||
@ -24,48 +20,18 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
|
||||
{
|
||||
private final ResourceLocation id;
|
||||
private final String adjective;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
private final ItemStack stack;
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemStack stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, NonNullSupplier<ItemStack> item )
|
||||
{
|
||||
this( id, Util.makeDescriptionId( "upgrade", id ) + ".adjective", item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, ItemStack stack )
|
||||
{
|
||||
this( id, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemLike item )
|
||||
{
|
||||
this( id, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, ItemLike item )
|
||||
{
|
||||
this( id, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, Supplier<? extends ItemLike> item )
|
||||
{
|
||||
this( id, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( ResourceLocation id, Supplier<? extends ItemLike> item )
|
||||
{
|
||||
this( id, new CachedStack( item ) );
|
||||
this( id, IUpgradeBase.getDefaultAdjective( id ), stack );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -86,32 +52,6 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the construction of an item stack.
|
||||
*
|
||||
* @see dan200.computercraft.api.turtle.AbstractTurtleUpgrade For explanation of this class.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemLike> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemLike> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,24 @@
|
||||
*/
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.IUpgradeBase;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Additional peripherals for pocket computers.
|
||||
* A peripheral which can be equipped to the back side of a pocket computer.
|
||||
*
|
||||
* @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade)
|
||||
* Pocket upgrades are defined in two stages. First, on creates a {@link IPocketUpgrade} subclass and corresponding
|
||||
* {@link PocketUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||
*
|
||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||
* the upgrade registered internally. See the documentation in {@link PocketUpgradeSerialiser} for details on this process
|
||||
* and where files should be located.
|
||||
*
|
||||
* @see PocketUpgradeSerialiser For how to register a pocket computer upgrade.
|
||||
*/
|
||||
public interface IPocketUpgrade extends IUpgradeBase
|
||||
{
|
||||
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A data provider to generate pocket computer upgrades.
|
||||
*
|
||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||
*
|
||||
* @see GatherDataEvent To register your data provider
|
||||
* @see PocketUpgradeSerialiser
|
||||
*/
|
||||
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade, PocketUpgradeSerialiser<?>>
|
||||
{
|
||||
public PocketUpgradeDataProvider( @Nonnull DataGenerator generator )
|
||||
{
|
||||
super( generator, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.TYPE );
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.internal.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistryEntry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reads a {@link IPocketUpgrade} from disk and reads/writes it to a network packet.
|
||||
*
|
||||
* This follows the same format as {@link dan200.computercraft.api.turtle.TurtleUpgradeSerialiser} - consult the
|
||||
* documentation there for more information.
|
||||
*
|
||||
* @param <T> The type of pocket computer upgrade this is responsible for serialising.
|
||||
* @see IPocketUpgrade
|
||||
* @see PocketUpgradeDataProvider
|
||||
*/
|
||||
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T, PocketUpgradeSerialiser<?>>
|
||||
{
|
||||
/**
|
||||
* A {@link Class} representing an abstract {@link PocketUpgradeSerialiser}. This is largely intended for use with
|
||||
* Forge Registry methods/classes, such as {@link DeferredRegister} and {@link RegistryManager#getRegistry(Class)}.
|
||||
*/
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Class<PocketUpgradeSerialiser<?>> TYPE = (Class<PocketUpgradeSerialiser<?>>) (Class<?>) PocketUpgradeSerialiser.class;
|
||||
|
||||
/**
|
||||
* A convenient base class to inherit to implement {@link PocketUpgradeSerialiser}.
|
||||
*
|
||||
* @param <T> The type of the upgrade created by this serialiser.
|
||||
*/
|
||||
abstract class Base<T extends IPocketUpgrade> extends ForgeRegistryEntry<PocketUpgradeSerialiser<?>> implements PocketUpgradeSerialiser<T>
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleRecipeSerializer}, but for
|
||||
* upgrades.
|
||||
*
|
||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simple( @Nonnull Function<ResourceLocation, T> factory )
|
||||
{
|
||||
class Impl extends SimpleSerialiser<T, PocketUpgradeSerialiser<?>> implements PocketUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( Function<ResourceLocation, T> constructor )
|
||||
{
|
||||
super( constructor );
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl( factory );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||
* {@link IUpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade.
|
||||
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simpleWithCustomItem( @Nonnull BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
class Impl extends SerialiserWithCraftingItem<T, PocketUpgradeSerialiser<?>> implements PocketUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
super( factory );
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl( factory );
|
||||
}
|
||||
}
|
@ -5,15 +5,11 @@
|
||||
*/
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraftforge.common.util.NonNullSupplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
@ -25,9 +21,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
private final ResourceLocation id;
|
||||
private final TurtleUpgradeType type;
|
||||
private final String adjective;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
private final ItemStack stack;
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
@ -35,39 +31,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this( id, type, Util.makeDescriptionId( "upgrade", id ) + ".adjective", stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, type, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
|
||||
{
|
||||
this( id, type, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemLike item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemLike item )
|
||||
{
|
||||
this( id, type, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, Supplier<? extends ItemLike> item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, Supplier<? extends ItemLike> item )
|
||||
{
|
||||
this( id, type, new CachedStack( item ) );
|
||||
this( id, type, IUpgradeBase.getDefaultAdjective( id ), stack );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -95,32 +61,6 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* A supplier which converts an item into an item stack.
|
||||
*
|
||||
* Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemLike> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemLike> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.IUpgradeBase;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@ -21,10 +20,17 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The primary interface for defining an update for Turtles. A turtle update
|
||||
* can either be a new tool, or a new peripheral.
|
||||
* The primary interface for defining an update for Turtles. A turtle update can either be a new tool, or a new
|
||||
* peripheral.
|
||||
*
|
||||
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
|
||||
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
||||
* {@link TurtleUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||
*
|
||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||
* the upgrade registered internally. See the documentation in {@link TurtleUpgradeSerialiser} for details on this process
|
||||
* and where files should be located.
|
||||
*
|
||||
* @see TurtleUpgradeSerialiser For how to register a turtle upgrade.
|
||||
*/
|
||||
public interface ITurtleUpgrade extends IUpgradeBase
|
||||
{
|
||||
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.ComputerCraftTags;
|
||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A data provider to generate turtle upgrades.
|
||||
*
|
||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||
*
|
||||
* @see GatherDataEvent To register your data provider
|
||||
* @see TurtleUpgradeSerialiser
|
||||
*/
|
||||
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade, TurtleUpgradeSerialiser<?>>
|
||||
{
|
||||
private static final ResourceLocation TOOL_ID = new ResourceLocation( ComputerCraftAPI.MOD_ID, "tool" );
|
||||
|
||||
public TurtleUpgradeDataProvider( DataGenerator generator )
|
||||
{
|
||||
super( generator, "Turtle Upgrades", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.TYPE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new turtle tool upgrade, such as a pickaxe or shovel.
|
||||
*
|
||||
* @param id The ID of this tool.
|
||||
* @param item The item used for tool actions. Note, this doesn't inherit all properties of the tool, you may need
|
||||
* to specify {@link ToolBuilder#damageMultiplier(float)} and {@link ToolBuilder#breakable(Tag.Named)}.
|
||||
* @return A tool builder,
|
||||
*/
|
||||
@Nonnull
|
||||
public final ToolBuilder tool( @Nonnull ResourceLocation id, @Nonnull Item item )
|
||||
{
|
||||
return new ToolBuilder( id, existingSerialiser( TOOL_ID ), item );
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for custom turtle tool upgrades.
|
||||
*
|
||||
* @see #tool(ResourceLocation, Item)
|
||||
*/
|
||||
public static class ToolBuilder
|
||||
{
|
||||
private final ResourceLocation id;
|
||||
private final TurtleUpgradeSerialiser<?> serialiser;
|
||||
private final Item toolItem;
|
||||
private String adjective;
|
||||
private Item craftingItem;
|
||||
private Float damageMultiplier = null;
|
||||
private Tag.Named<Block> breakable;
|
||||
|
||||
ToolBuilder( ResourceLocation id, TurtleUpgradeSerialiser<?> serialiser, Item toolItem )
|
||||
{
|
||||
this.id = id;
|
||||
this.serialiser = serialiser;
|
||||
this.toolItem = toolItem;
|
||||
craftingItem = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom adjective for this tool. By default this takes its adjective from the tool item.
|
||||
*
|
||||
* @param adjective The new adjective to use.
|
||||
* @return The tool builder, for further use.
|
||||
*/
|
||||
@Nonnull
|
||||
public ToolBuilder adjective( @Nonnull String adjective )
|
||||
{
|
||||
this.adjective = adjective;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom item which is used to craft this upgrade. By default this is the same as the provided tool
|
||||
* item, but you may wish to override it.
|
||||
*
|
||||
* @param craftingItem The item used to craft this upgrade.
|
||||
* @return The tool builder, for further use.
|
||||
*/
|
||||
@Nonnull
|
||||
public ToolBuilder craftingItem( @Nonnull Item craftingItem )
|
||||
{
|
||||
this.craftingItem = craftingItem;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to
|
||||
* get the final damage.
|
||||
*
|
||||
* @param damageMultiplier The damage multiplier.
|
||||
* @return The tool builder, for futher use.
|
||||
*/
|
||||
public ToolBuilder damageMultiplier( float damageMultiplier )
|
||||
{
|
||||
this.damageMultiplier = damageMultiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a list of breakable blocks. If not given, the tool can break all blocks. If given, only blocks
|
||||
* in this tag, those in {@link ComputerCraftTags.Blocks#TURTLE_ALWAYS_BREAKABLE} and "insta-mine" ones can
|
||||
* be broken.
|
||||
*
|
||||
* @param breakable The tag containing all blocks breakable by this item.
|
||||
* @return The tool builder, for further use.
|
||||
* @see ComputerCraftTags.Blocks
|
||||
*/
|
||||
public ToolBuilder breakable( @Nonnull Tag.Named<Block> breakable )
|
||||
{
|
||||
this.breakable = breakable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register this as an upgrade.
|
||||
*
|
||||
* @param add The callback given to {@link #addUpgrades(Consumer)}.
|
||||
*/
|
||||
public void add( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add )
|
||||
{
|
||||
add.accept( new Upgrade<>( id, serialiser, s -> {
|
||||
s.addProperty( "item", toolItem.getRegistryName().toString() );
|
||||
if( adjective != null ) s.addProperty( "adjective", adjective );
|
||||
if( craftingItem != null ) s.addProperty( "craftItem", craftingItem.getRegistryName().toString() );
|
||||
if( damageMultiplier != null ) s.addProperty( "damageMultiplier", damageMultiplier );
|
||||
if( breakable != null ) s.addProperty( "breakable", breakable.getName().toString() );
|
||||
} ) );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.internal.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistryEntry;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
||||
*
|
||||
* These should be registered in a {@link IForgeRegistry} while the game is loading, much like {@link RecipeSerializer}s.
|
||||
* It is suggested you use a {@link DeferredRegister}.
|
||||
*
|
||||
* If your turtle upgrade doesn't have any associated configurable parameters (like most upgrades), you can use
|
||||
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
|
||||
*
|
||||
* <h2>Example</h2>
|
||||
* <pre>{@code
|
||||
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
|
||||
*
|
||||
* // Register a new upgrade serialiser called "my_upgrade".
|
||||
* public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
|
||||
* SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
|
||||
*
|
||||
* // Then in your constructor
|
||||
* SERIALISERS.register( bus );
|
||||
* }</pre>
|
||||
*
|
||||
* We can then define a new upgrade using JSON by placing the following in
|
||||
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
|
||||
*
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "type": my_mod:my_upgrade",
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
||||
*
|
||||
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
||||
* @see ITurtleUpgrade
|
||||
* @see TurtleUpgradeDataProvider
|
||||
*/
|
||||
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T, TurtleUpgradeSerialiser<?>>
|
||||
{
|
||||
/**
|
||||
* A {@link Class} representing an abstract {@link TurtleUpgradeSerialiser}. This is largely intended for use with
|
||||
* Forge Registry methods/classes, such as {@link DeferredRegister} and {@link RegistryManager#getRegistry(Class)}.
|
||||
*/
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Class<TurtleUpgradeSerialiser<?>> TYPE = (Class<TurtleUpgradeSerialiser<?>>) (Class<?>) TurtleUpgradeSerialiser.class;
|
||||
|
||||
/**
|
||||
* A convenient base class to inherit to implement {@link TurtleUpgradeSerialiser}.
|
||||
*
|
||||
* @param <T> The type of the upgrade created by this serialiser.
|
||||
*/
|
||||
abstract class Base<T extends ITurtleUpgrade> extends ForgeRegistryEntry<TurtleUpgradeSerialiser<?>> implements TurtleUpgradeSerialiser<T>
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleRecipeSerializer}, but for
|
||||
* upgrades.
|
||||
*
|
||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simple( @Nonnull Function<ResourceLocation, T> factory )
|
||||
{
|
||||
class Impl extends SimpleSerialiser<T, TurtleUpgradeSerialiser<?>> implements TurtleUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( Function<ResourceLocation, T> constructor )
|
||||
{
|
||||
super( constructor );
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl( factory );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||
* {@link IUpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade.
|
||||
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simpleWithCustomItem( @Nonnull BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
class Impl extends SerialiserWithCraftingItem<T, TurtleUpgradeSerialiser<?>> implements TurtleUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
super( factory );
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl( factory );
|
||||
}
|
||||
}
|
@ -3,10 +3,11 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api;
|
||||
package dan200.computercraft.api.upgrades;
|
||||
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@ -83,4 +84,18 @@ public interface IUpgradeBase
|
||||
if( craftingShareTag == null ) return shareTag.isEmpty();
|
||||
return shareTag.equals( craftingShareTag );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a suitable default unlocalised adjective for an upgrade ID. This converts "modid:some_upgrade" to
|
||||
* "upgrade.modid.some_upgrade.adjective".
|
||||
*
|
||||
* @param id The upgrade ID.
|
||||
* @return The generated adjective.
|
||||
* @see #getUnlocalisedAdjective()
|
||||
*/
|
||||
@Nonnull
|
||||
static String getDefaultAdjective( @Nonnull ResourceLocation id )
|
||||
{
|
||||
return Util.makeDescriptionId( "upgrade", id ) + ".adjective";
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.upgrades;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.internal.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.HashCache;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A data generator/provider for turtle and pocket computer upgrades. This should not be extended direclty, instead see
|
||||
* the other sub-classes.
|
||||
*
|
||||
* @param <T> The base class of upgrades.
|
||||
* @param <R> The upgrade serialiser to register for.
|
||||
*/
|
||||
public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends UpgradeSerialiser<?, R>> implements DataProvider
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
private final DataGenerator generator;
|
||||
private final String name;
|
||||
private final String folder;
|
||||
private final Class<R> klass;
|
||||
|
||||
private List<T> upgrades;
|
||||
|
||||
protected UpgradeDataProvider( @Nonnull DataGenerator generator, @Nonnull String name, @Nonnull String folder, @Nonnull Class<R> klass )
|
||||
{
|
||||
this.generator = generator;
|
||||
this.name = name;
|
||||
this.folder = folder;
|
||||
this.klass = klass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
||||
*
|
||||
* @param id The ID of the upgrade to create.
|
||||
* @param serialiser The simple serialiser.
|
||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||
*/
|
||||
@Nonnull
|
||||
public final Upgrade<R> simple( @Nonnull ResourceLocation id, @Nonnull R serialiser )
|
||||
{
|
||||
if( !(serialiser instanceof SimpleSerialiser) )
|
||||
{
|
||||
throw new IllegalStateException( serialiser + " must be a simple() seriaiser." );
|
||||
}
|
||||
|
||||
return new Upgrade<>( id, serialiser, s -> {} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
||||
*
|
||||
* @param id The ID of the upgrade to create.
|
||||
* @param serialiser The simple serialiser.
|
||||
* @param item The crafting upgrade for this item.
|
||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||
*/
|
||||
@Nonnull
|
||||
public final Upgrade<R> simpleWithCustomItem( @Nonnull ResourceLocation id, @Nonnull R serialiser, @Nonnull Item item )
|
||||
{
|
||||
if( !(serialiser instanceof SerialiserWithCraftingItem) )
|
||||
{
|
||||
throw new IllegalStateException( serialiser + " must be a simpleWithCustomItem() serialiser." );
|
||||
}
|
||||
|
||||
return new Upgrade<>( id, serialiser, s ->
|
||||
s.addProperty( "item", Objects.requireNonNull( item.getRegistryName(), "Item is not registered" ).toString() )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all turtle or pocket computer upgrades.
|
||||
*
|
||||
* <strong>Example usage:</strong>
|
||||
* <pre>{@code
|
||||
* protected void addUpgrades(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
|
||||
* simple(new ResourceLocation("mymod", "speaker"), SPEAKER_SERIALISER.get()).add(addUpgrade);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param addUpgrade A callback used to register an upgrade.
|
||||
*/
|
||||
protected abstract void addUpgrades( @Nonnull Consumer<Upgrade<R>> addUpgrade );
|
||||
|
||||
@Override
|
||||
public final void run( @Nonnull HashCache cache ) throws IOException
|
||||
{
|
||||
Path base = generator.getOutputFolder().resolve( "data" );
|
||||
|
||||
Set<ResourceLocation> seen = new HashSet<>();
|
||||
List<T> upgrades = new ArrayList<>();
|
||||
addUpgrades( upgrade -> {
|
||||
if( !seen.add( upgrade.id() ) ) throw new IllegalStateException( "Duplicate upgrade " + upgrade.id() );
|
||||
|
||||
var json = new JsonObject();
|
||||
json.addProperty( "type", Objects.requireNonNull( upgrade.serialiser().getRegistryName(), "Serialiser has not been registered" ).toString() );
|
||||
upgrade.serialise().accept( json );
|
||||
|
||||
try
|
||||
{
|
||||
DataProvider.save( GSON, cache, json, base.resolve( upgrade.id().getNamespace() + "/" + folder + "/" + upgrade.id().getPath() + ".json" ) );
|
||||
}
|
||||
catch( IOException e )
|
||||
{
|
||||
LOGGER.error( "Failed to save {} {}", name, upgrade.id(), e );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@SuppressWarnings( "unchecked" ) var result = (T) upgrade.serialiser().fromJson( upgrade.id(), json );
|
||||
upgrades.add( result );
|
||||
}
|
||||
catch( IllegalArgumentException | JsonParseException e )
|
||||
{
|
||||
LOGGER.error( "Failed to parse {} {}", name, upgrade.id(), e );
|
||||
}
|
||||
} );
|
||||
|
||||
this.upgrades = upgrades;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final R existingSerialiser( @Nonnull ResourceLocation id )
|
||||
{
|
||||
var result = RegistryManager.ACTIVE.getRegistry( klass ).getValue( id );
|
||||
if( result == null ) throw new IllegalArgumentException( "No such serialiser " + klass );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<T> getGeneratedUpgrades()
|
||||
{
|
||||
if( upgrades == null ) throw new IllegalStateException( "Upgrades have not beeen generated yet" );
|
||||
return upgrades;
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructed upgrade instance, produced {@link #addUpgrades(Consumer)}.
|
||||
*
|
||||
* @param id The ID for this upgrade.
|
||||
* @param serialiser The serialiser which reads and writes this upgrade.
|
||||
* @param serialise Augment the generated JSON with additional fields.
|
||||
* @param <R> The type of upgrade serialiser.
|
||||
*/
|
||||
public static record Upgrade<R extends UpgradeSerialiser<?, R>>(
|
||||
ResourceLocation id, R serialiser, Consumer<JsonObject> serialise
|
||||
)
|
||||
{
|
||||
/**
|
||||
* Convenience method for registering an upgrade.
|
||||
*
|
||||
* @param add The callback given to {@link #addUpgrades(Consumer)}
|
||||
*/
|
||||
public void add( @Nonnull Consumer<Upgrade<R>> add )
|
||||
{
|
||||
add.accept( this );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Base interface for upgrade serialisers. This should generally not be implemented directly, instead implementing one
|
||||
* of {@link TurtleUpgradeSerialiser} or {@link PocketUpgradeSerialiser}.
|
||||
*
|
||||
* However, it may sometimes be useful to implement this if you have some shared logic between upgrade types.
|
||||
*
|
||||
* @param <R> The serialiser for this upgrade category, either {@code TurtleUpgradeSerialiser<?>} or {@code PocketUpgradeSerialiser<?>}.
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
* @see TurtleUpgradeSerialiser
|
||||
* @see PocketUpgradeSerialiser
|
||||
*/
|
||||
public interface UpgradeSerialiser<T extends IUpgradeBase, R extends UpgradeSerialiser<?, R>> extends IForgeRegistryEntry<R>
|
||||
{
|
||||
/**
|
||||
* Read this upgrade from a JSON file in a datapack.
|
||||
*
|
||||
* @param id The ID of this upgrade.
|
||||
* @param object The JSON object to load this upgrade from.
|
||||
* @return The constructed upgrade, with a {@link IUpgradeBase#getUpgradeID()} equal to {@code id}.
|
||||
* @see net.minecraft.util.GsonHelper For additional JSON helper methods.
|
||||
*/
|
||||
@Nonnull
|
||||
T fromJson( @Nonnull ResourceLocation id, @Nonnull JsonObject object );
|
||||
|
||||
/**
|
||||
* Read this upgrade from a network packet, sent from the server.
|
||||
*
|
||||
* @param id The ID of this upgrade.
|
||||
* @param buffer The buffer object to read this upgrade from.
|
||||
* @return The constructed upgrade, with a {@link IUpgradeBase#getUpgradeID()} equal to {@code id}.
|
||||
*/
|
||||
@Nonnull
|
||||
T fromNetwork( @Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer );
|
||||
|
||||
/**
|
||||
* Write this upgrade to a network packet, to be sent to the client.
|
||||
*
|
||||
* @param buffer The buffer object to write this upgrade to
|
||||
* @param upgrade The upgrade to write.
|
||||
*/
|
||||
void toNetwork( @Nonnull FriendlyByteBuf buffer, @Nonnull T upgrade );
|
||||
|
||||
}
|
@ -14,7 +14,7 @@ import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BasicCustomLoader<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
|
||||
class BasicCustomLoader<T extends ModelBuilder<T>> extends CustomLoaderBuilder<T>
|
||||
{
|
||||
private final Consumer<JsonObject> extra;
|
||||
|
||||
|
@ -25,13 +25,13 @@ import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockModelProvider extends BlockStateProvider
|
||||
class BlockModelProvider extends BlockStateProvider
|
||||
{
|
||||
private ModelFile monitorBase;
|
||||
private ModelFile turtleBase;
|
||||
private ModelFile modemBase;
|
||||
|
||||
public BlockModelProvider( DataGenerator generator, ExistingFileHelper existingFileHelper )
|
||||
BlockModelProvider( DataGenerator generator, ExistingFileHelper existingFileHelper )
|
||||
{
|
||||
super( generator, ComputerCraft.MOD_ID, existingFileHelper );
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
|
||||
import static dan200.computercraft.shared.ComputerCraftTags.Blocks.*;
|
||||
import static dan200.computercraft.api.ComputerCraftTags.Blocks.*;
|
||||
|
||||
public class BlockTagsGenerator extends BlockTagsProvider
|
||||
class BlockTagsGenerator extends BlockTagsProvider
|
||||
{
|
||||
public BlockTagsGenerator( DataGenerator generator, ExistingFileHelper helper )
|
||||
BlockTagsGenerator( DataGenerator generator, ExistingFileHelper helper )
|
||||
{
|
||||
super( generator, ComputerCraft.MOD_ID, helper );
|
||||
}
|
||||
|
@ -23,7 +23,12 @@ public class Generators
|
||||
DataGenerator generator = event.getGenerator();
|
||||
ExistingFileHelper existingFiles = event.getExistingFileHelper();
|
||||
|
||||
generator.addProvider( new RecipeGenerator( generator ) );
|
||||
var turtleUpgrades = new TurtleUpgradeGenerator( generator );
|
||||
var pocketUpgrades = new PocketUpgradeGenerator( generator );
|
||||
generator.addProvider( turtleUpgrades );
|
||||
generator.addProvider( pocketUpgrades );
|
||||
|
||||
generator.addProvider( new RecipeGenerator( generator, turtleUpgrades, pocketUpgrades ) );
|
||||
generator.addProvider( new LootTableGenerator( generator ) );
|
||||
generator.addProvider( new BlockModelProvider( generator, existingFiles ) );
|
||||
|
||||
|
@ -6,18 +6,18 @@
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.ComputerCraftTags.Blocks;
|
||||
import dan200.computercraft.api.ComputerCraftTags.Blocks;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.tags.ItemTagsProvider;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
|
||||
import static dan200.computercraft.shared.ComputerCraftTags.Items.*;
|
||||
import static dan200.computercraft.api.ComputerCraftTags.Items.*;
|
||||
|
||||
public class ItemTagsGenerator extends ItemTagsProvider
|
||||
class ItemTagsGenerator extends ItemTagsProvider
|
||||
{
|
||||
public ItemTagsGenerator( DataGenerator generator, BlockTagsGenerator blockTags, ExistingFileHelper helper )
|
||||
ItemTagsGenerator( DataGenerator generator, BlockTagsGenerator blockTags, ExistingFileHelper helper )
|
||||
{
|
||||
super( generator, blockTags, ComputerCraft.MOD_ID, helper );
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ import net.minecraftforge.fmllegacy.RegistryObject;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class LootTableGenerator extends LootTableProvider
|
||||
class LootTableGenerator extends LootTableProvider
|
||||
{
|
||||
public LootTableGenerator( DataGenerator generator )
|
||||
LootTableGenerator( DataGenerator generator )
|
||||
{
|
||||
super( generator );
|
||||
}
|
||||
|
@ -28,13 +28,13 @@ import java.util.function.BiConsumer;
|
||||
/**
|
||||
* An alternative to {@link net.minecraft.data.loot.LootTableProvider}, with a more flexible interface.
|
||||
*/
|
||||
public abstract class LootTableProvider implements DataProvider
|
||||
abstract class LootTableProvider implements DataProvider
|
||||
{
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
|
||||
private final DataGenerator generator;
|
||||
|
||||
public LootTableProvider( DataGenerator generator )
|
||||
LootTableProvider( DataGenerator generator )
|
||||
{
|
||||
this.generator = generator;
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static dan200.computercraft.shared.Registry.ModItems;
|
||||
import static dan200.computercraft.shared.Registry.ModPocketUpgradeSerialisers;
|
||||
|
||||
class PocketUpgradeGenerator extends PocketUpgradeDataProvider
|
||||
{
|
||||
PocketUpgradeGenerator( DataGenerator generator )
|
||||
{
|
||||
super( generator );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addUpgrades( @Nonnull Consumer<Upgrade<PocketUpgradeSerialiser<?>>> addUpgrade )
|
||||
{
|
||||
addUpgrade.accept( simpleWithCustomItem( id( "speaker" ), ModPocketUpgradeSerialisers.SPEAKER.get(), ModItems.SPEAKER.get() ) );
|
||||
simpleWithCustomItem( id( "wireless_modem_normal" ), ModPocketUpgradeSerialisers.WIRELESS_MODEM_NORMAL.get(), ModItems.WIRELESS_MODEM_NORMAL.get() ).add( addUpgrade );
|
||||
simpleWithCustomItem( id( "wireless_modem_advanced" ), ModPocketUpgradeSerialisers.WIRELESS_MODEM_ADVANCED.get(), ModItems.WIRELESS_MODEM_ADVANCED.get() ).add( addUpgrade );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ResourceLocation id( @Nonnull String id )
|
||||
{
|
||||
return new ResourceLocation( ComputerCraft.MOD_ID, id );
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.PocketUpgrades;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.TurtleUpgrades;
|
||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
@ -39,14 +39,20 @@ import javax.annotation.Nonnull;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static dan200.computercraft.shared.ComputerCraftTags.Items.COMPUTER;
|
||||
import static dan200.computercraft.shared.ComputerCraftTags.Items.WIRED_MODEM;
|
||||
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
|
||||
import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM;
|
||||
|
||||
public class RecipeGenerator extends RecipeProvider
|
||||
class RecipeGenerator extends RecipeProvider
|
||||
{
|
||||
public RecipeGenerator( DataGenerator generator )
|
||||
private final TurtleUpgradeDataProvider turtleUpgrades;
|
||||
private final PocketUpgradeDataProvider pocketUpgrades;
|
||||
|
||||
RecipeGenerator( DataGenerator generator, TurtleUpgradeDataProvider turtleUpgrades, PocketUpgradeDataProvider pocketUpgrades )
|
||||
{
|
||||
super( generator );
|
||||
|
||||
this.turtleUpgrades = turtleUpgrades;
|
||||
this.pocketUpgrades = pocketUpgrades;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,7 +107,8 @@ public class RecipeGenerator extends RecipeProvider
|
||||
|
||||
String nameId = family.name().toLowerCase( Locale.ROOT );
|
||||
|
||||
TurtleUpgrades.getVanillaUpgrades().forEach( upgrade -> {
|
||||
for( var upgrade : turtleUpgrades.getGeneratedUpgrades() )
|
||||
{
|
||||
ItemStack result = TurtleItemFactory.create( -1, null, -1, family, null, upgrade, -1, null );
|
||||
ShapedRecipeBuilder
|
||||
.shaped( result.getItem() )
|
||||
@ -117,7 +124,7 @@ public class RecipeGenerator extends RecipeProvider
|
||||
nameId, upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()
|
||||
) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +142,8 @@ public class RecipeGenerator extends RecipeProvider
|
||||
|
||||
String nameId = family.name().toLowerCase( Locale.ROOT );
|
||||
|
||||
PocketUpgrades.getVanillaUpgrades().forEach( upgrade -> {
|
||||
for( var upgrade : pocketUpgrades.getGeneratedUpgrades() )
|
||||
{
|
||||
ItemStack result = PocketComputerItemFactory.create( -1, null, -1, family, upgrade );
|
||||
ShapedRecipeBuilder
|
||||
.shaped( result.getItem() )
|
||||
@ -152,7 +160,7 @@ public class RecipeGenerator extends RecipeProvider
|
||||
nameId, upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()
|
||||
) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Adapter for recipes which overrides the serializer and adds custom item NBT.
|
||||
*/
|
||||
public final class RecipeWrapper implements FinishedRecipe
|
||||
final class RecipeWrapper implements FinishedRecipe
|
||||
{
|
||||
private final FinishedRecipe recipe;
|
||||
private final CompoundTag resultData;
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftTags.Blocks;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Items;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static dan200.computercraft.shared.Registry.ModItems;
|
||||
import static dan200.computercraft.shared.Registry.ModTurtleSerialisers;
|
||||
|
||||
class TurtleUpgradeGenerator extends TurtleUpgradeDataProvider
|
||||
{
|
||||
TurtleUpgradeGenerator( DataGenerator generator )
|
||||
{
|
||||
super( generator );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
|
||||
{
|
||||
simpleWithCustomItem( id( "speaker" ), ModTurtleSerialisers.SPEAKER.get(), ModItems.SPEAKER.get() ).add( addUpgrade );
|
||||
simpleWithCustomItem( vanilla( "crafting_table" ), ModTurtleSerialisers.WORKBENCH.get(), Items.CRAFTING_TABLE ).add( addUpgrade );
|
||||
simpleWithCustomItem( id( "wireless_modem_normal" ), ModTurtleSerialisers.WIRELESS_MODEM_NORMAL.get(), ModItems.WIRELESS_MODEM_NORMAL.get() ).add( addUpgrade );
|
||||
simpleWithCustomItem( id( "wireless_modem_advanced" ), ModTurtleSerialisers.WIRELESS_MODEM_ADVANCED.get(), ModItems.WIRELESS_MODEM_ADVANCED.get() ).add( addUpgrade );
|
||||
|
||||
tool( vanilla( "diamond_axe" ), Items.DIAMOND_AXE ).damageMultiplier( 6.0f ).add( addUpgrade );
|
||||
tool( vanilla( "diamond_pickaxe" ), Items.DIAMOND_PICKAXE ).add( addUpgrade );
|
||||
tool( vanilla( "diamond_hoe" ), Items.DIAMOND_HOE ).breakable( Blocks.TURTLE_HOE_BREAKABLE ).add( addUpgrade );
|
||||
tool( vanilla( "diamond_shovel" ), Items.DIAMOND_SHOVEL ).breakable( Blocks.TURTLE_SHOVEL_BREAKABLE ).add( addUpgrade );
|
||||
tool( vanilla( "diamond_sword" ), Items.DIAMOND_SWORD ).breakable( Blocks.TURTLE_SWORD_BREAKABLE ).damageMultiplier( 9.0f ).add( addUpgrade );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ResourceLocation id( @Nonnull String id )
|
||||
{
|
||||
return new ResourceLocation( ComputerCraft.MOD_ID, id );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ResourceLocation vanilla( @Nonnull String id )
|
||||
{
|
||||
// Naughty, please don't do this. Mostly here for some semblance of backwards compatibility.
|
||||
return new ResourceLocation( "minecraft", id );
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.internal.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.registries.ForgeRegistryEntry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Simple serialiser which returns a constant upgrade with a custom crafting item.
|
||||
*
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*
|
||||
* @param <R> The serialiser for this upgrade category, either {@code TurtleUpgradeSerialiser<?>} or {@code PocketUpgradeSerialiser<?>}.
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
*/
|
||||
public abstract class SerialiserWithCraftingItem<T extends IUpgradeBase, R extends UpgradeSerialiser<?, R>> extends ForgeRegistryEntry<R> implements UpgradeSerialiser<T, R>
|
||||
{
|
||||
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
||||
|
||||
protected SerialiserWithCraftingItem( BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromJson( @Nonnull ResourceLocation id, @Nonnull JsonObject object )
|
||||
{
|
||||
var item = GsonHelper.getAsItem( object, "item" );
|
||||
return factory.apply( id, new ItemStack( item ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromNetwork( @Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer )
|
||||
{
|
||||
ItemStack item = buffer.readItem();
|
||||
return factory.apply( id, item );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toNetwork( @Nonnull FriendlyByteBuf buffer, @Nonnull T upgrade )
|
||||
{
|
||||
buffer.writeItem( upgrade.getCraftingItem() );
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.internal.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.ForgeRegistryEntry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Simple serialiser which returns a constant upgrade.
|
||||
*
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*
|
||||
* @param <R> The serialiser for this upgrade category, either {@code TurtleUpgradeSerialiser<?>} or {@code PocketUpgradeSerialiser<?>}.
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
*/
|
||||
public abstract class SimpleSerialiser<T extends IUpgradeBase, R extends UpgradeSerialiser<?, R>> extends ForgeRegistryEntry<R> implements UpgradeSerialiser<T, R>
|
||||
{
|
||||
private final Function<ResourceLocation, T> constructor;
|
||||
|
||||
public SimpleSerialiser( Function<ResourceLocation, T> constructor )
|
||||
{
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromJson( @Nonnull ResourceLocation id, @Nonnull JsonObject object )
|
||||
{
|
||||
return constructor.apply( id );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromNetwork( @Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer )
|
||||
{
|
||||
return constructor.apply( id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toNetwork( @Nonnull FriendlyByteBuf buffer, @Nonnull T upgrade )
|
||||
{
|
||||
}
|
||||
}
|
@ -15,6 +15,8 @@ import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.IComputer;
|
||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.UpgradesLoadedMessage;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@ -24,10 +26,7 @@ import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
import net.minecraft.world.level.storage.loot.LootPool;
|
||||
import net.minecraft.world.level.storage.loot.entries.LootTableReference;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
|
||||
import net.minecraftforge.event.AddReloadListenerEvent;
|
||||
import net.minecraftforge.event.LootTableLoadEvent;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.*;
|
||||
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
@ -145,5 +144,21 @@ public final class CommonHooks
|
||||
public static void onAddReloadListeners( AddReloadListenerEvent event )
|
||||
{
|
||||
event.addListener( ResourceMount.RELOAD_LISTENER );
|
||||
event.addListener( TurtleUpgrades.instance() );
|
||||
event.addListener( PocketUpgrades.instance() );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onDatapackSync( OnDatapackSyncEvent event )
|
||||
{
|
||||
var packet = new UpgradesLoadedMessage();
|
||||
if( event.getPlayer() == null )
|
||||
{
|
||||
NetworkHandler.sendToAllPlayers( packet );
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkHandler.sendToPlayer( event.getPlayer(), packet );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,81 +7,27 @@ package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class PocketUpgrades
|
||||
{
|
||||
private static final Map<String, IPocketUpgrade> upgrades = new HashMap<>();
|
||||
private static final Map<IPocketUpgrade, String> upgradeOwners = new Object2ObjectLinkedOpenCustomHashMap<>( Util.identityStrategy() );
|
||||
private static final UpgradeManager<PocketUpgradeSerialiser<?>, IPocketUpgrade> registry = new UpgradeManager<>(
|
||||
"pocket computer upgrade", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.TYPE
|
||||
);
|
||||
|
||||
private PocketUpgrades() {}
|
||||
|
||||
public static synchronized void register( @Nonnull IPocketUpgrade upgrade )
|
||||
public static UpgradeManager<PocketUpgradeSerialiser<?>, IPocketUpgrade> instance()
|
||||
{
|
||||
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
|
||||
|
||||
String id = upgrade.getUpgradeID().toString();
|
||||
IPocketUpgrade existing = upgrades.get( id );
|
||||
if( existing != null )
|
||||
{
|
||||
throw new IllegalStateException( "Error registering '" + upgrade.getUnlocalisedAdjective() + " pocket computer'. UpgradeID '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " pocket computer'" );
|
||||
}
|
||||
|
||||
upgrades.put( id, upgrade );
|
||||
|
||||
ModContainer mc = ModLoadingContext.get().getActiveContainer();
|
||||
if( mc != null && mc.getModId() != null ) upgradeOwners.put( upgrade, mc.getModId() );
|
||||
return registry;
|
||||
}
|
||||
|
||||
public static IPocketUpgrade get( String id )
|
||||
public static Stream<IPocketUpgrade> getVanillaUpgrades()
|
||||
{
|
||||
// Fix a typo in the advanced modem upgrade's name. I'm sorry, I realise this is horrible.
|
||||
if( id.equals( "computercraft:advanved_modem" ) ) id = "computercraft:advanced_modem";
|
||||
|
||||
return upgrades.get( id );
|
||||
}
|
||||
|
||||
public static IPocketUpgrade get( @Nonnull ItemStack stack )
|
||||
{
|
||||
if( stack.isEmpty() ) return null;
|
||||
|
||||
for( IPocketUpgrade upgrade : upgrades.values() )
|
||||
{
|
||||
ItemStack craftingStack = upgrade.getCraftingItem();
|
||||
if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && upgrade.isItemSuitable( stack ) )
|
||||
{
|
||||
return upgrade;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getOwner( IPocketUpgrade upgrade )
|
||||
{
|
||||
return upgradeOwners.get( upgrade );
|
||||
}
|
||||
|
||||
public static Iterable<IPocketUpgrade> getVanillaUpgrades()
|
||||
{
|
||||
List<IPocketUpgrade> vanilla = new ArrayList<>();
|
||||
vanilla.add( ComputerCraft.PocketUpgrades.wirelessModemNormal );
|
||||
vanilla.add( ComputerCraft.PocketUpgrades.wirelessModemAdvanced );
|
||||
vanilla.add( ComputerCraft.PocketUpgrades.speaker );
|
||||
return vanilla;
|
||||
}
|
||||
|
||||
public static Iterable<IPocketUpgrade> getUpgrades()
|
||||
{
|
||||
return Collections.unmodifiableCollection( upgrades.values() );
|
||||
return instance().getUpgradeWrappers().values().stream()
|
||||
.filter( x -> x.modId().equals( ComputerCraft.MOD_ID ) )
|
||||
.map( UpgradeManager.UpgradeWrapper::upgrade );
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.media.IMedia;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.shared.command.arguments.ArgumentSerializers;
|
||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
@ -74,7 +76,10 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.item.*;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.RecordItem;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
@ -95,6 +100,7 @@ import net.minecraftforge.fmllegacy.RegistryObject;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryBuilder;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@ -251,49 +257,32 @@ public final class Registry
|
||||
() -> new ItemBlockCable.WiredModem( ModBlocks.CABLE.get(), properties() ) );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerItems( RegistryEvent.Register<Item> event )
|
||||
public static class ModTurtleSerialisers
|
||||
{
|
||||
registerTurtleUpgrades();
|
||||
registerPocketUpgrades();
|
||||
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, ComputerCraft.MOD_ID );
|
||||
|
||||
public static final RegistryObject<TurtleUpgradeSerialiser<TurtleSpeaker>> SPEAKER =
|
||||
SERIALISERS.register( "speaker", () -> TurtleUpgradeSerialiser.simpleWithCustomItem( TurtleSpeaker::new ) );
|
||||
public static final RegistryObject<TurtleUpgradeSerialiser<TurtleCraftingTable>> WORKBENCH =
|
||||
SERIALISERS.register( "workbench", () -> TurtleUpgradeSerialiser.simpleWithCustomItem( TurtleCraftingTable::new ) );
|
||||
public static final RegistryObject<TurtleUpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_NORMAL =
|
||||
SERIALISERS.register( "wireless_modem_normal", () -> TurtleUpgradeSerialiser.simpleWithCustomItem( ( id, item ) -> new TurtleModem( id, item, false ) ) );
|
||||
public static final RegistryObject<TurtleUpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_ADVANCED =
|
||||
SERIALISERS.register( "wireless_modem_advanced", () -> TurtleUpgradeSerialiser.simpleWithCustomItem( ( id, item ) -> new TurtleModem( id, item, true ) ) );
|
||||
|
||||
public static final RegistryObject<TurtleUpgradeSerialiser<TurtleTool>> TOOL = SERIALISERS.register( "tool", () -> TurtleToolSerialiser.INSTANCE );
|
||||
}
|
||||
|
||||
private static void registerTurtleUpgrades()
|
||||
public static class ModPocketUpgradeSerialisers
|
||||
{
|
||||
// Upgrades
|
||||
ComputerCraft.TurtleUpgrades.wirelessModemNormal = new TurtleModem( false, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.wirelessModemNormal );
|
||||
static final DeferredRegister<PocketUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( PocketUpgradeSerialiser.TYPE, ComputerCraft.MOD_ID );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.wirelessModemAdvanced = new TurtleModem( true, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.wirelessModemAdvanced );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.speaker = new TurtleSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ) );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.speaker );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.craftingTable = new TurtleCraftingTable( new ResourceLocation( "minecraft", "crafting_table" ) );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.craftingTable );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.diamondSword = new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondSword );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondShovel );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.diamondPickaxe = new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondPickaxe );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.diamondAxe = new TurtleAxe( new ResourceLocation( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondAxe );
|
||||
|
||||
ComputerCraft.TurtleUpgrades.diamondHoe = new TurtleHoe( new ResourceLocation( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE );
|
||||
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.diamondHoe );
|
||||
}
|
||||
|
||||
private static void registerPocketUpgrades()
|
||||
{
|
||||
ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.wirelessModemNormal = new PocketModem( false ) );
|
||||
ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.wirelessModemAdvanced = new PocketModem( true ) );
|
||||
ComputerCraftAPI.registerPocketUpgrade( ComputerCraft.PocketUpgrades.speaker = new PocketSpeaker() );
|
||||
public static final RegistryObject<PocketUpgradeSerialiser<PocketSpeaker>> SPEAKER =
|
||||
SERIALISERS.register( "speaker", () -> PocketUpgradeSerialiser.simpleWithCustomItem( PocketSpeaker::new ) );
|
||||
public static final RegistryObject<PocketUpgradeSerialiser<PocketModem>> WIRELESS_MODEM_NORMAL =
|
||||
SERIALISERS.register( "wireless_modem_normal", () -> PocketUpgradeSerialiser.simpleWithCustomItem( ( id, item ) -> new PocketModem( id, item, false ) ) );
|
||||
public static final RegistryObject<PocketUpgradeSerialiser<PocketModem>> WIRELESS_MODEM_ADVANCED =
|
||||
SERIALISERS.register( "wireless_modem_advanced", () -> PocketUpgradeSerialiser.simpleWithCustomItem( ( id, item ) -> new PocketModem( id, item, true ) ) );
|
||||
}
|
||||
|
||||
public static class ModEntities
|
||||
@ -337,6 +326,20 @@ public final class Registry
|
||||
() -> ContainerData.toType( ViewComputerContainerData::new, ContainerViewComputer::new ) );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerRegistries( RegistryEvent.NewRegistry event )
|
||||
{
|
||||
new RegistryBuilder<TurtleUpgradeSerialiser<?>>()
|
||||
.setName( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_upgrade_serialiser" ) )
|
||||
.setType( TurtleUpgradeSerialiser.TYPE )
|
||||
.disableSaving().disableSync().create();
|
||||
|
||||
new RegistryBuilder<PocketUpgradeSerialiser<?>>()
|
||||
.setName( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_upgrade_serialiser" ) )
|
||||
.setType( PocketUpgradeSerialiser.TYPE )
|
||||
.disableSaving().disableSync().create();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerRecipeSerializers( RegistryEvent.Register<RecipeSerializer<?>> event )
|
||||
{
|
||||
@ -423,6 +426,8 @@ public final class Registry
|
||||
ModBlocks.BLOCKS.register( bus );
|
||||
ModBlockEntities.TILES.register( bus );
|
||||
ModItems.ITEMS.register( bus );
|
||||
ModTurtleSerialisers.SERIALISERS.register( bus );
|
||||
ModPocketUpgradeSerialisers.SERIALISERS.register( bus );
|
||||
ModEntities.ENTITIES.register( bus );
|
||||
ModContainers.CONTAINERS.register( bus );
|
||||
}
|
||||
|
@ -7,177 +7,27 @@ package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class TurtleUpgrades
|
||||
{
|
||||
private static class Wrapper
|
||||
{
|
||||
final ITurtleUpgrade upgrade;
|
||||
final String id;
|
||||
final String modId;
|
||||
boolean enabled;
|
||||
|
||||
Wrapper( ITurtleUpgrade upgrade )
|
||||
{
|
||||
this.upgrade = upgrade;
|
||||
id = upgrade.getUpgradeID().toString();
|
||||
ModContainer mc = ModLoadingContext.get().getActiveContainer();
|
||||
modId = mc != null && mc.getModId() != null ? mc.getModId() : ComputerCraft.MOD_ID;
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static ITurtleUpgrade[] vanilla;
|
||||
|
||||
private static final Map<String, ITurtleUpgrade> upgrades = new HashMap<>();
|
||||
private static final Map<ITurtleUpgrade, Wrapper> wrappers = new Object2ObjectLinkedOpenCustomHashMap<>( Util.identityStrategy() );
|
||||
private static boolean needsRebuild;
|
||||
private static final UpgradeManager<TurtleUpgradeSerialiser<?>, ITurtleUpgrade> registry = new UpgradeManager<>(
|
||||
"turtle upgrade", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.TYPE
|
||||
);
|
||||
|
||||
private TurtleUpgrades() {}
|
||||
|
||||
public static void register( @Nonnull ITurtleUpgrade upgrade )
|
||||
public static UpgradeManager<TurtleUpgradeSerialiser<?>, ITurtleUpgrade> instance()
|
||||
{
|
||||
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
|
||||
rebuild();
|
||||
|
||||
Wrapper wrapper = new Wrapper( upgrade );
|
||||
String id = wrapper.id;
|
||||
ITurtleUpgrade existing = upgrades.get( id );
|
||||
if( existing != null )
|
||||
{
|
||||
throw new IllegalStateException( "Error registering '" + upgrade.getUnlocalisedAdjective() + " Turtle'. Upgrade ID '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" );
|
||||
}
|
||||
|
||||
upgrades.put( id, upgrade );
|
||||
wrappers.put( upgrade, wrapper );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ITurtleUpgrade get( String id )
|
||||
{
|
||||
rebuild();
|
||||
return upgrades.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;
|
||||
|
||||
for( Wrapper wrapper : wrappers.values() )
|
||||
{
|
||||
if( !wrapper.enabled ) continue;
|
||||
|
||||
ItemStack craftingStack = wrapper.upgrade.getCraftingItem();
|
||||
if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && wrapper.upgrade.isItemSuitable( stack ) )
|
||||
{
|
||||
return wrapper.upgrade;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return registry;
|
||||
}
|
||||
|
||||
public static Stream<ITurtleUpgrade> getVanillaUpgrades()
|
||||
{
|
||||
if( vanilla == null )
|
||||
{
|
||||
vanilla = new ITurtleUpgrade[] {
|
||||
// ComputerCraft upgrades
|
||||
ComputerCraft.TurtleUpgrades.wirelessModemNormal,
|
||||
ComputerCraft.TurtleUpgrades.wirelessModemAdvanced,
|
||||
ComputerCraft.TurtleUpgrades.speaker,
|
||||
|
||||
// Vanilla Minecraft upgrades
|
||||
ComputerCraft.TurtleUpgrades.diamondPickaxe,
|
||||
ComputerCraft.TurtleUpgrades.diamondAxe,
|
||||
ComputerCraft.TurtleUpgrades.diamondSword,
|
||||
ComputerCraft.TurtleUpgrades.diamondShovel,
|
||||
ComputerCraft.TurtleUpgrades.diamondHoe,
|
||||
ComputerCraft.TurtleUpgrades.craftingTable,
|
||||
};
|
||||
}
|
||||
|
||||
return Arrays.stream( vanilla ).filter( x -> x != null && wrappers.get( x ).enabled );
|
||||
}
|
||||
|
||||
public static Stream<ITurtleUpgrade> getUpgrades()
|
||||
{
|
||||
return wrappers.values().stream().filter( x -> x.enabled ).map( x -> x.upgrade );
|
||||
}
|
||||
|
||||
public static boolean suitableForFamily( ComputerFamily family, ITurtleUpgrade upgrade )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the cache of turtle upgrades. This is done before querying the cache or registering new upgrades.
|
||||
*/
|
||||
private static void rebuild()
|
||||
{
|
||||
if( !needsRebuild ) return;
|
||||
|
||||
upgrades.clear();
|
||||
for( Wrapper wrapper : wrappers.values() )
|
||||
{
|
||||
if( !wrapper.enabled ) continue;
|
||||
|
||||
ITurtleUpgrade existing = upgrades.get( wrapper.id );
|
||||
if( existing != null )
|
||||
{
|
||||
ComputerCraft.log.error( "Error registering '" + wrapper.upgrade.getUnlocalisedAdjective() + " Turtle'." +
|
||||
" Upgrade ID '" + wrapper.id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" );
|
||||
continue;
|
||||
}
|
||||
|
||||
upgrades.put( wrapper.id, wrapper.upgrade );
|
||||
}
|
||||
|
||||
needsRebuild = false;
|
||||
}
|
||||
|
||||
public static void enable( ITurtleUpgrade upgrade )
|
||||
{
|
||||
Wrapper wrapper = wrappers.get( upgrade );
|
||||
if( wrapper.enabled ) return;
|
||||
|
||||
wrapper.enabled = true;
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
public static void disable( ITurtleUpgrade upgrade )
|
||||
{
|
||||
Wrapper wrapper = wrappers.get( upgrade );
|
||||
if( !wrapper.enabled ) return;
|
||||
|
||||
wrapper.enabled = false;
|
||||
upgrades.remove( wrapper.id );
|
||||
}
|
||||
|
||||
public static void remove( ITurtleUpgrade upgrade )
|
||||
{
|
||||
wrappers.remove( upgrade );
|
||||
needsRebuild = true;
|
||||
return instance().getUpgradeWrappers().values().stream()
|
||||
.filter( x -> x.modId().equals( ComputerCraft.MOD_ID ) )
|
||||
.map( UpgradeManager.UpgradeWrapper::upgrade );
|
||||
}
|
||||
}
|
||||
|
152
src/main/java/dan200/computercraft/shared/UpgradeManager.java
Normal file
152
src/main/java/dan200/computercraft/shared/UpgradeManager.java
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import com.google.gson.*;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages turtle and pocket computer upgrades.
|
||||
*
|
||||
* @param <R> The type of upgrade serialisers.
|
||||
* @param <T> The type of upgrade.
|
||||
* @see TurtleUpgrades
|
||||
* @see PocketUpgrades
|
||||
*/
|
||||
public class UpgradeManager<R extends UpgradeSerialiser<? extends T, R>, T extends IUpgradeBase> extends SimpleJsonResourceReloadListener
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create();
|
||||
|
||||
public static record UpgradeWrapper<R extends UpgradeSerialiser<? extends T, R>, T extends IUpgradeBase>(
|
||||
@Nonnull String id, @Nonnull T upgrade, @Nonnull R serialiser, @Nonnull String modId
|
||||
) {}
|
||||
|
||||
private final String kind;
|
||||
private final Class<R> klass;
|
||||
|
||||
private Map<String, UpgradeWrapper<R, T>> current = Collections.emptyMap();
|
||||
private Map<T, UpgradeWrapper<R, T>> currentWrappers = Collections.emptyMap();
|
||||
|
||||
public UpgradeManager( @Nonnull String kind, @Nonnull String path, @Nonnull Class<R> klass )
|
||||
{
|
||||
super( GSON, path );
|
||||
this.kind = kind;
|
||||
this.klass = klass;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T get( String id )
|
||||
{
|
||||
var wrapper = current.get( id );
|
||||
return wrapper == null ? null : wrapper.upgrade();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOwner( @Nonnull T upgrade )
|
||||
{
|
||||
var wrapper = currentWrappers.get( upgrade );
|
||||
return wrapper != null ? wrapper.modId() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T get( @Nonnull ItemStack stack )
|
||||
{
|
||||
if( stack.isEmpty() ) return null;
|
||||
|
||||
for( var wrapper : current.values() )
|
||||
{
|
||||
var craftingStack = wrapper.upgrade().getCraftingItem();
|
||||
if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && wrapper.upgrade().isItemSuitable( stack ) )
|
||||
{
|
||||
return wrapper.upgrade();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Collection<T> getUpgrades()
|
||||
{
|
||||
return currentWrappers.keySet();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<String, UpgradeWrapper<R, T>> getUpgradeWrappers()
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply( @Nonnull Map<ResourceLocation, JsonElement> upgrades, @Nonnull ResourceManager manager, @Nonnull ProfilerFiller profiler )
|
||||
{
|
||||
Map<String, UpgradeWrapper<R, T>> newUpgrades = new HashMap<>();
|
||||
for( var element : upgrades.entrySet() )
|
||||
{
|
||||
try
|
||||
{
|
||||
loadUpgrade( newUpgrades, element.getKey(), element.getValue() );
|
||||
}
|
||||
catch( IllegalArgumentException | JsonParseException e )
|
||||
{
|
||||
LOGGER.error( "Error loading {} {} from JSON file", kind, element.getKey(), e );
|
||||
}
|
||||
}
|
||||
|
||||
current = Collections.unmodifiableMap( newUpgrades );
|
||||
currentWrappers = newUpgrades.values().stream().collect( Collectors.toUnmodifiableMap( UpgradeWrapper::upgrade, x -> x ) );
|
||||
LOGGER.info( "Loaded {} {}s", current.size(), kind );
|
||||
}
|
||||
|
||||
private void loadUpgrade( Map<String, UpgradeWrapper<R, T>> current, ResourceLocation id, JsonElement json )
|
||||
{
|
||||
var root = GsonHelper.convertToJsonObject( json, "top element" );
|
||||
var serialiserId = new ResourceLocation( GsonHelper.getAsString( root, "type" ) );
|
||||
|
||||
var serialiser = RegistryManager.ACTIVE.getRegistry( klass ).getValue( serialiserId );
|
||||
if( serialiser == null ) throw new JsonSyntaxException( "Unknown upgrade type '" + serialiserId + "'" );
|
||||
|
||||
// TODO: Can we track which mod this resource came from and use that instead? It's theoretically possible,
|
||||
// but maybe not ideal for datapacks.
|
||||
var modId = id.getNamespace();
|
||||
if( modId.equals( "minecraft" ) || modId.equals( "" ) ) modId = ComputerCraft.MOD_ID;
|
||||
|
||||
var upgrade = serialiser.fromJson( id, root );
|
||||
if( !upgrade.getUpgradeID().equals( id ) )
|
||||
{
|
||||
throw new IllegalArgumentException( "Upgrade " + id + " from " + serialiser + " was incorrectly given id " + upgrade.getUpgradeID() );
|
||||
}
|
||||
|
||||
UpgradeWrapper<R, T> result = new UpgradeWrapper<>( id.toString(), upgrade, serialiser, modId );
|
||||
current.put( result.id(), result );
|
||||
}
|
||||
|
||||
public void loadFromNetwork( @Nonnull Map<String, UpgradeWrapper<R, T>> newUpgrades )
|
||||
{
|
||||
current = Collections.unmodifiableMap( newUpgrades );
|
||||
currentWrappers = newUpgrades.values().stream().collect( Collectors.toUnmodifiableMap( UpgradeWrapper::upgrade, x -> x ) );
|
||||
}
|
||||
}
|
@ -76,18 +76,21 @@ public class JEIComputerCraft implements IModPlugin
|
||||
List<ItemStack> upgradeItems = new ArrayList<>();
|
||||
for( ComputerFamily family : MAIN_FAMILIES )
|
||||
{
|
||||
TurtleUpgrades.getUpgrades()
|
||||
.filter( x -> TurtleUpgrades.suitableForFamily( family, x ) )
|
||||
.map( x -> TurtleItemFactory.create( -1, null, -1, family, null, x, 0, null ) )
|
||||
.forEach( upgradeItems::add );
|
||||
for( ITurtleUpgrade upgrade : TurtleUpgrades.instance().getUpgrades() )
|
||||
{
|
||||
upgradeItems.add( TurtleItemFactory.create( -1, null, -1, family, null, upgrade, 0, null ) );
|
||||
}
|
||||
|
||||
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() )
|
||||
for( IPocketUpgrade upgrade : PocketUpgrades.instance().getUpgrades() )
|
||||
{
|
||||
upgradeItems.add( PocketComputerItemFactory.create( -1, null, -1, family, upgrade ) );
|
||||
}
|
||||
}
|
||||
|
||||
runtime.getIngredientManager().addIngredientsAtRuntime( VanillaTypes.ITEM, upgradeItems );
|
||||
if( !upgradeItems.isEmpty() )
|
||||
{
|
||||
runtime.getIngredientManager().addIngredientsAtRuntime( VanillaTypes.ITEM, upgradeItems );
|
||||
}
|
||||
|
||||
// Hide all upgrade recipes
|
||||
IRecipeCategory<?> category = registry.getRecipeCategory( VanillaRecipeCategoryUid.CRAFTING, false );
|
||||
|
@ -6,7 +6,7 @@
|
||||
package dan200.computercraft.shared.integration.jei;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
@ -52,16 +52,17 @@ class RecipeResolver implements IRecipeManagerPlugin
|
||||
if( initialised ) return;
|
||||
initialised = true;
|
||||
|
||||
TurtleUpgrades.getUpgrades().forEach( upgrade -> {
|
||||
for( ITurtleUpgrade upgrade : TurtleUpgrades.instance().getUpgrades() )
|
||||
{
|
||||
ItemStack stack = upgrade.getCraftingItem();
|
||||
if( stack.isEmpty() ) return;
|
||||
|
||||
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.instance().getUpgrades() )
|
||||
{
|
||||
ItemStack stack = upgrade.getCraftingItem();
|
||||
if( stack.isEmpty() ) continue;
|
||||
@ -356,7 +357,7 @@ class RecipeResolver implements IRecipeManagerPlugin
|
||||
recipes = this.recipes = new ArrayList<>( 4 );
|
||||
for( ComputerFamily family : MAIN_FAMILIES )
|
||||
{
|
||||
if( turtle != null && TurtleUpgrades.suitableForFamily( family, turtle ) )
|
||||
if( turtle != null )
|
||||
{
|
||||
recipes.add( horizontal(
|
||||
of( Ingredient.EMPTY, ingredient, of( TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ) ),
|
||||
|
@ -61,6 +61,7 @@ public final class NetworkHandler
|
||||
registerMainThread( 17, NetworkDirection.PLAY_TO_CLIENT, SpeakerStopClientMessage.class, SpeakerStopClientMessage::new );
|
||||
registerMainThread( 18, NetworkDirection.PLAY_TO_CLIENT, SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new );
|
||||
registerMainThread( 19, NetworkDirection.PLAY_TO_CLIENT, UploadResultMessage.class, UploadResultMessage::new );
|
||||
registerMainThread( 20, NetworkDirection.PLAY_TO_CLIENT, UpgradesLoadedMessage.class, UpgradesLoadedMessage::new );
|
||||
}
|
||||
|
||||
public static void sendToPlayer( Player player, NetworkMessage packet )
|
||||
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.shared.PocketUpgrades;
|
||||
import dan200.computercraft.shared.TurtleUpgrades;
|
||||
import dan200.computercraft.shared.UpgradeManager;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.fmllegacy.network.NetworkEvent;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Syncs turtle and pocket upgrades to the client.
|
||||
*/
|
||||
public class UpgradesLoadedMessage implements NetworkMessage
|
||||
{
|
||||
private final Map<String, UpgradeManager.UpgradeWrapper<TurtleUpgradeSerialiser<?>, ITurtleUpgrade>> turtleUpgrades;
|
||||
private final Map<String, UpgradeManager.UpgradeWrapper<PocketUpgradeSerialiser<?>, IPocketUpgrade>> pocketUpgrades;
|
||||
|
||||
public UpgradesLoadedMessage()
|
||||
{
|
||||
turtleUpgrades = TurtleUpgrades.instance().getUpgradeWrappers();
|
||||
pocketUpgrades = PocketUpgrades.instance().getUpgradeWrappers();
|
||||
}
|
||||
|
||||
public UpgradesLoadedMessage( @Nonnull FriendlyByteBuf buf )
|
||||
{
|
||||
turtleUpgrades = fromBytes( buf, RegistryManager.ACTIVE.getRegistry( TurtleUpgradeSerialiser.TYPE ) );
|
||||
pocketUpgrades = fromBytes( buf, RegistryManager.ACTIVE.getRegistry( PocketUpgradeSerialiser.TYPE ) );
|
||||
}
|
||||
|
||||
private <R extends UpgradeSerialiser<? extends T, R>, T extends IUpgradeBase> Map<String, UpgradeManager.UpgradeWrapper<R, T>> fromBytes(
|
||||
@Nonnull FriendlyByteBuf buf, @Nonnull IForgeRegistry<R> registry
|
||||
)
|
||||
{
|
||||
int size = buf.readVarInt();
|
||||
Map<String, UpgradeManager.UpgradeWrapper<R, T>> upgrades = new HashMap<>( size );
|
||||
for( int i = 0; i < size; i++ )
|
||||
{
|
||||
String id = buf.readUtf();
|
||||
|
||||
ResourceLocation serialiserId = buf.readResourceLocation();
|
||||
R serialiser = registry.getValue( serialiserId );
|
||||
if( serialiser == null ) throw new IllegalStateException( "Unknown serialiser " + serialiserId );
|
||||
|
||||
T upgrade = serialiser.fromNetwork( new ResourceLocation( id ), buf );
|
||||
String modId = buf.readUtf();
|
||||
|
||||
upgrades.put( id, new UpgradeManager.UpgradeWrapper<R, T>( id, upgrade, serialiser, modId ) );
|
||||
}
|
||||
|
||||
return upgrades;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes( @Nonnull FriendlyByteBuf buf )
|
||||
{
|
||||
toBytes( buf, turtleUpgrades );
|
||||
toBytes( buf, pocketUpgrades );
|
||||
}
|
||||
|
||||
private <R extends UpgradeSerialiser<? extends T, R>, T extends IUpgradeBase> void toBytes(
|
||||
@Nonnull FriendlyByteBuf buf, Map<String, UpgradeManager.UpgradeWrapper<R, T>> upgrades
|
||||
)
|
||||
{
|
||||
buf.writeVarInt( upgrades.size() );
|
||||
for( var entry : upgrades.entrySet() )
|
||||
{
|
||||
buf.writeUtf( entry.getKey() );
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
var serialiser = (UpgradeSerialiser<T, R>) entry.getValue().serialiser();
|
||||
|
||||
buf.writeResourceLocation( Objects.requireNonNull( serialiser.getRegistryName(), "Serialiser is not registered!" ) );
|
||||
serialiser.toNetwork( buf, entry.getValue().upgrade() );
|
||||
|
||||
buf.writeUtf( entry.getValue().modId() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( NetworkEvent.Context context )
|
||||
{
|
||||
TurtleUpgrades.instance().loadFromNetwork( turtleUpgrades );
|
||||
PocketUpgrades.instance().loadFromNetwork( pocketUpgrades );
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public abstract class WirelessModemPeripheral extends ModemPeripheral
|
||||
{
|
||||
public static final String NORMAL_ADJECTIVE = "upgrade.computercraft.wireless_modem_normal.adjective";
|
||||
public static final String ADVANCED_ADJECTIVE = "upgrade.computercraft.wireless_modem_advanced.adjective";
|
||||
|
||||
private final boolean advanced;
|
||||
|
||||
public WirelessModemPeripheral( ModemState state, boolean advanced )
|
||||
|
@ -20,6 +20,8 @@ import java.util.UUID;
|
||||
*/
|
||||
public abstract class UpgradeSpeakerPeripheral extends SpeakerPeripheral
|
||||
{
|
||||
public static final String ADJECTIVE = "upgrade.computercraft.speaker.adjective";
|
||||
|
||||
private final UUID source = UUID.randomUUID();
|
||||
|
||||
@Override
|
||||
|
@ -135,7 +135,7 @@ public class PocketAPI implements ILuaAPI
|
||||
ItemStack invStack = inv.get( (i + start) % inv.size() );
|
||||
if( !invStack.isEmpty() )
|
||||
{
|
||||
IPocketUpgrade newUpgrade = PocketUpgrades.get( invStack );
|
||||
IPocketUpgrade newUpgrade = PocketUpgrades.instance().get( invStack );
|
||||
|
||||
if( newUpgrade != null && newUpgrade != previous )
|
||||
{
|
||||
|
@ -77,10 +77,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
||||
{
|
||||
if( !allowdedIn( group ) ) return;
|
||||
stacks.add( create( -1, null, -1, null ) );
|
||||
for( IPocketUpgrade upgrade : PocketUpgrades.getVanillaUpgrades() )
|
||||
{
|
||||
stacks.add( create( -1, null, -1, upgrade ) );
|
||||
}
|
||||
PocketUpgrades.getVanillaUpgrades().map( x -> create( -1, null, -1, x ) ).forEach( stacks::add );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -203,7 +200,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
||||
{
|
||||
// If we're a non-vanilla, non-CC upgrade then return whichever mod this upgrade
|
||||
// belongs to.
|
||||
String mod = PocketUpgrades.getOwner( upgrade );
|
||||
String mod = PocketUpgrades.instance().getOwner( upgrade );
|
||||
if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod;
|
||||
}
|
||||
|
||||
@ -384,8 +381,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
||||
{
|
||||
CompoundTag compound = stack.getTag();
|
||||
return compound != null && compound.contains( NBT_UPGRADE )
|
||||
? PocketUpgrades.get( compound.getString( NBT_UPGRADE ) ) : null;
|
||||
|
||||
? PocketUpgrades.instance().get( compound.getString( NBT_UPGRADE ) ) : null;
|
||||
}
|
||||
|
||||
public static void setUpgrade( @Nonnull ItemStack stack, IPocketUpgrade upgrade )
|
||||
|
@ -8,10 +8,11 @@ package dan200.computercraft.shared.pocket.peripherals;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
|
||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -20,14 +21,9 @@ public class PocketModem extends AbstractPocketUpgrade
|
||||
{
|
||||
private final boolean advanced;
|
||||
|
||||
public PocketModem( boolean advanced )
|
||||
public PocketModem( ResourceLocation id, ItemStack stack, boolean advanced )
|
||||
{
|
||||
super(
|
||||
new ResourceLocation( "computercraft", advanced ? "wireless_modem_advanced" : "wireless_modem_normal" ),
|
||||
advanced
|
||||
? Registry.ModBlocks.WIRELESS_MODEM_ADVANCED
|
||||
: Registry.ModBlocks.WIRELESS_MODEM_NORMAL
|
||||
);
|
||||
super( id, advanced ? WirelessModemPeripheral.ADVANCED_ADJECTIVE : WirelessModemPeripheral.NORMAL_ADJECTIVE, stack );
|
||||
this.advanced = advanced;
|
||||
}
|
||||
|
||||
|
@ -8,18 +8,19 @@ package dan200.computercraft.shared.pocket.peripherals;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
|
||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PocketSpeaker extends AbstractPocketUpgrade
|
||||
{
|
||||
public PocketSpeaker()
|
||||
public PocketSpeaker( ResourceLocation id, ItemStack item )
|
||||
{
|
||||
super( new ResourceLocation( "computercraft", "speaker" ), Registry.ModBlocks.SPEAKER );
|
||||
super( id, UpgradeSpeakerPeripheral.ADJECTIVE, item );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -86,7 +86,7 @@ public final class PocketComputerUpgradeRecipe extends CustomRecipe
|
||||
|
||||
if( x == computerX && y == computerY - 1 )
|
||||
{
|
||||
upgrade = PocketUpgrades.get( item );
|
||||
upgrade = PocketUpgrades.instance().get( item );
|
||||
if( upgrade == null ) return ItemStack.EMPTY;
|
||||
}
|
||||
else if( !item.isEmpty() )
|
||||
|
@ -695,7 +695,7 @@ public class TurtleAPI implements ILuaAPI
|
||||
* @cc.usage <pre>{@code
|
||||
* local has_block, data = turtle.inspect()
|
||||
* if has_block then
|
||||
* print(textutils.serialize(data))
|
||||
* print(textutils.serialise(data))
|
||||
* -- {
|
||||
* -- name = "minecraft:oak_log",
|
||||
* -- state = { axis = "x" },
|
||||
@ -753,7 +753,7 @@ public class TurtleAPI implements ILuaAPI
|
||||
* @cc.usage Print the current slot, assuming it contains 13 dirt.
|
||||
*
|
||||
* <pre>{@code
|
||||
* print(textutils.serialize(turtle.getItemDetail()))
|
||||
* print(textutils.serialise(turtle.getItemDetail()))
|
||||
* -- => {
|
||||
* -- name = "minecraft:dirt",
|
||||
* -- count = 13,
|
||||
|
@ -160,8 +160,8 @@ public class TurtleBrain implements ITurtleAccess
|
||||
overlay = nbt.contains( NBT_OVERLAY ) ? new ResourceLocation( nbt.getString( NBT_OVERLAY ) ) : null;
|
||||
|
||||
// Read upgrades
|
||||
setUpgradeDirect( TurtleSide.LEFT, nbt.contains( NBT_LEFT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_LEFT_UPGRADE ) ) : null );
|
||||
setUpgradeDirect( TurtleSide.RIGHT, nbt.contains( NBT_RIGHT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_RIGHT_UPGRADE ) ) : null );
|
||||
setUpgradeDirect( TurtleSide.LEFT, nbt.contains( NBT_LEFT_UPGRADE ) ? TurtleUpgrades.instance().get( nbt.getString( NBT_LEFT_UPGRADE ) ) : null );
|
||||
setUpgradeDirect( TurtleSide.RIGHT, nbt.contains( NBT_RIGHT_UPGRADE ) ? TurtleUpgrades.instance().get( nbt.getString( NBT_RIGHT_UPGRADE ) ) : null );
|
||||
|
||||
// NBT
|
||||
upgradeNBTData.clear();
|
||||
|
@ -36,11 +36,8 @@ public class TurtleEquipCommand implements ITurtleCommand
|
||||
if( !selectedStack.isEmpty() )
|
||||
{
|
||||
newUpgradeStack = selectedStack.copy();
|
||||
newUpgrade = TurtleUpgrades.get( newUpgradeStack );
|
||||
if( newUpgrade == null || !TurtleUpgrades.suitableForFamily( ((TurtleBrain) turtle).getFamily(), newUpgrade ) )
|
||||
{
|
||||
return TurtleCommandResult.failure( "Not a valid upgrade" );
|
||||
}
|
||||
newUpgrade = TurtleUpgrades.instance().get( newUpgradeStack );
|
||||
if( newUpgrade == null ) return TurtleCommandResult.failure( "Not a valid upgrade" );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -69,7 +69,6 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem
|
||||
|
||||
list.add( create( -1, null, -1, null, null, 0, null ) );
|
||||
TurtleUpgrades.getVanillaUpgrades()
|
||||
.filter( x -> TurtleUpgrades.suitableForFamily( family, x ) )
|
||||
.map( x -> create( -1, null, -1, null, x, 0, null ) )
|
||||
.forEach( list::add );
|
||||
}
|
||||
@ -116,14 +115,14 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem
|
||||
ITurtleUpgrade left = getUpgrade( stack, TurtleSide.LEFT );
|
||||
if( left != null )
|
||||
{
|
||||
String mod = TurtleUpgrades.getOwner( left );
|
||||
String mod = TurtleUpgrades.instance().getOwner( left );
|
||||
if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod;
|
||||
}
|
||||
|
||||
ITurtleUpgrade right = getUpgrade( stack, TurtleSide.RIGHT );
|
||||
if( right != null )
|
||||
{
|
||||
String mod = TurtleUpgrades.getOwner( right );
|
||||
String mod = TurtleUpgrades.instance().getOwner( right );
|
||||
if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod;
|
||||
}
|
||||
|
||||
@ -148,7 +147,7 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem
|
||||
if( tag == null ) return null;
|
||||
|
||||
String key = side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE : NBT_RIGHT_UPGRADE;
|
||||
return tag.contains( key ) ? TurtleUpgrades.get( tag.getString( key ) ) : null;
|
||||
return tag.contains( key ) ? TurtleUpgrades.instance().get( tag.getString( key ) ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,19 +152,8 @@ public final class TurtleUpgradeRecipe extends CustomRecipe
|
||||
{
|
||||
if( !items[i].isEmpty() )
|
||||
{
|
||||
ITurtleUpgrade itemUpgrade = TurtleUpgrades.get( items[i] );
|
||||
if( itemUpgrade == null )
|
||||
{
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
if( upgrades[i] != null )
|
||||
{
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
if( !TurtleUpgrades.suitableForFamily( family, itemUpgrade ) )
|
||||
{
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ITurtleUpgrade itemUpgrade = TurtleUpgrades.instance().get( items[i] );
|
||||
if( itemUpgrade == null || upgrades[i] != null ) return ItemStack.EMPTY;
|
||||
upgrades[i] = itemUpgrade;
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.turtle.upgrades;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class TurtleAxe extends TurtleTool
|
||||
{
|
||||
public TurtleAxe( ResourceLocation id, String adjective, Item item )
|
||||
{
|
||||
super( id, adjective, item );
|
||||
}
|
||||
|
||||
public TurtleAxe( ResourceLocation id, Item item )
|
||||
{
|
||||
super( id, item );
|
||||
}
|
||||
|
||||
public TurtleAxe( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
|
||||
{
|
||||
super( id, craftItem, toolItem );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDamageMultiplier()
|
||||
{
|
||||
return 6.0f;
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@ -24,9 +24,9 @@ public class TurtleCraftingTable extends AbstractTurtleUpgrade
|
||||
private static final ModelResourceLocation leftModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_left", "inventory" );
|
||||
private static final ModelResourceLocation rightModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_right", "inventory" );
|
||||
|
||||
public TurtleCraftingTable( ResourceLocation id )
|
||||
public TurtleCraftingTable( ResourceLocation id, ItemStack stack )
|
||||
{
|
||||
super( id, TurtleUpgradeType.PERIPHERAL, Blocks.CRAFTING_TABLE );
|
||||
super( id, TurtleUpgradeType.PERIPHERAL, "upgrade.minecraft.crafting_table.adjective", stack );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.turtle.upgrades;
|
||||
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleCommandResult;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleVerb;
|
||||
import dan200.computercraft.shared.ComputerCraftTags;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TurtleHoe extends TurtleTool
|
||||
{
|
||||
public TurtleHoe( ResourceLocation id, String adjective, Item item )
|
||||
{
|
||||
super( id, adjective, item );
|
||||
}
|
||||
|
||||
public TurtleHoe( ResourceLocation id, Item item )
|
||||
{
|
||||
super( id, item );
|
||||
}
|
||||
|
||||
public TurtleHoe( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
|
||||
{
|
||||
super( id, craftItem, toolItem );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TurtleCommandResult checkBlockBreakable( BlockState state, Level world, BlockPos pos, TurtlePlayer player )
|
||||
{
|
||||
TurtleCommandResult result = super.checkBlockBreakable( state, world, pos, player );
|
||||
if( !result.isSuccess() ) return result;
|
||||
|
||||
return state.is( ComputerCraftTags.Blocks.TURTLE_HOE_BREAKABLE )
|
||||
|| isTriviallyBreakable( world, pos, state )
|
||||
? result : INEFFECTIVE;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction )
|
||||
{
|
||||
if( verb == TurtleVerb.DIG )
|
||||
{
|
||||
if( TurtlePlaceCommand.deployCopiedItem( item.copy(), turtle, direction, null, null ) )
|
||||
{
|
||||
return TurtleCommandResult.success();
|
||||
}
|
||||
}
|
||||
return super.useTool( turtle, side, verb, direction );
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ package dan200.computercraft.shared.turtle.upgrades;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.turtle.*;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
@ -16,6 +15,7 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
@ -68,14 +68,9 @@ public class TurtleModem extends AbstractTurtleUpgrade
|
||||
private final ModelResourceLocation leftOnModel;
|
||||
private final ModelResourceLocation rightOnModel;
|
||||
|
||||
public TurtleModem( boolean advanced, ResourceLocation id )
|
||||
public TurtleModem( ResourceLocation id, ItemStack stack, boolean advanced )
|
||||
{
|
||||
super(
|
||||
id, TurtleUpgradeType.PERIPHERAL,
|
||||
advanced
|
||||
? Registry.ModBlocks.WIRELESS_MODEM_ADVANCED
|
||||
: Registry.ModBlocks.WIRELESS_MODEM_NORMAL
|
||||
);
|
||||
super( id, TurtleUpgradeType.PERIPHERAL, advanced ? WirelessModemPeripheral.ADVANCED_ADJECTIVE : WirelessModemPeripheral.NORMAL_ADJECTIVE, stack );
|
||||
this.advanced = advanced;
|
||||
|
||||
if( advanced )
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.turtle.upgrades;
|
||||
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleCommandResult;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleVerb;
|
||||
import dan200.computercraft.shared.ComputerCraftTags;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TurtleShovel extends TurtleTool
|
||||
{
|
||||
public TurtleShovel( ResourceLocation id, String adjective, Item item )
|
||||
{
|
||||
super( id, adjective, item );
|
||||
}
|
||||
|
||||
public TurtleShovel( ResourceLocation id, Item item )
|
||||
{
|
||||
super( id, item );
|
||||
}
|
||||
|
||||
public TurtleShovel( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
|
||||
{
|
||||
super( id, craftItem, toolItem );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TurtleCommandResult checkBlockBreakable( BlockState state, Level world, BlockPos pos, TurtlePlayer player )
|
||||
{
|
||||
TurtleCommandResult result = super.checkBlockBreakable( state, world, pos, player );
|
||||
if( !result.isSuccess() ) return result;
|
||||
|
||||
return state.is( ComputerCraftTags.Blocks.TURTLE_SHOVEL_BREAKABLE )
|
||||
|| isTriviallyBreakable( world, pos, state )
|
||||
? result : INEFFECTIVE;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction )
|
||||
{
|
||||
if( verb == TurtleVerb.DIG )
|
||||
{
|
||||
if( TurtlePlaceCommand.deployCopiedItem( item.copy(), turtle, direction, null, null ) )
|
||||
{
|
||||
return TurtleCommandResult.success();
|
||||
}
|
||||
}
|
||||
return super.useTool( turtle, side, verb, direction );
|
||||
}
|
||||
}
|
@ -11,11 +11,11 @@ import dan200.computercraft.api.turtle.AbstractTurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
@ -57,9 +57,9 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade
|
||||
}
|
||||
}
|
||||
|
||||
public TurtleSpeaker( ResourceLocation id )
|
||||
public TurtleSpeaker( ResourceLocation id, ItemStack item )
|
||||
{
|
||||
super( id, TurtleUpgradeType.PERIPHERAL, Registry.ModBlocks.SPEAKER );
|
||||
super( id, TurtleUpgradeType.PERIPHERAL, UpgradeSpeakerPeripheral.ADJECTIVE, item );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.turtle.upgrades;
|
||||
|
||||
import dan200.computercraft.api.turtle.TurtleCommandResult;
|
||||
import dan200.computercraft.shared.ComputerCraftTags;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class TurtleSword extends TurtleTool
|
||||
{
|
||||
public TurtleSword( ResourceLocation id, String adjective, Item item )
|
||||
{
|
||||
super( id, adjective, item );
|
||||
}
|
||||
|
||||
public TurtleSword( ResourceLocation id, Item item )
|
||||
{
|
||||
super( id, item );
|
||||
}
|
||||
|
||||
public TurtleSword( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
|
||||
{
|
||||
super( id, craftItem, toolItem );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TurtleCommandResult checkBlockBreakable( BlockState state, Level world, BlockPos pos, TurtlePlayer player )
|
||||
{
|
||||
TurtleCommandResult result = super.checkBlockBreakable( state, world, pos, player );
|
||||
if( !result.isSuccess() ) return result;
|
||||
|
||||
return state.is( ComputerCraftTags.Blocks.TURTLE_SWORD_BREAKABLE )
|
||||
|| isTriviallyBreakable( world, pos, state )
|
||||
? result : INEFFECTIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDamageMultiplier()
|
||||
{
|
||||
return 9.0f;
|
||||
}
|
||||
}
|
@ -8,11 +8,12 @@ package dan200.computercraft.shared.turtle.upgrades;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftTags;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.*;
|
||||
import dan200.computercraft.shared.ComputerCraftTags;
|
||||
import dan200.computercraft.shared.TurtlePermissions;
|
||||
import dan200.computercraft.shared.turtle.core.TurtleBrain;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import dan200.computercraft.shared.util.DropConsumer;
|
||||
import dan200.computercraft.shared.util.InventoryUtil;
|
||||
@ -20,8 +21,8 @@ import dan200.computercraft.shared.util.WorldUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
@ -39,36 +40,37 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.ToolActions;
|
||||
import net.minecraftforge.event.entity.player.AttackEntityEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static net.minecraft.nbt.Tag.TAG_COMPOUND;
|
||||
import static net.minecraft.nbt.Tag.TAG_LIST;
|
||||
|
||||
public class TurtleTool extends AbstractTurtleUpgrade
|
||||
{
|
||||
protected static final TurtleCommandResult UNBREAKABLE = TurtleCommandResult.failure( "Unbreakable block detected" );
|
||||
protected static final TurtleCommandResult UNBREAKABLE = TurtleCommandResult.failure( "Cannot break unbreakable block" );
|
||||
protected static final TurtleCommandResult INEFFECTIVE = TurtleCommandResult.failure( "Cannot break block with this tool" );
|
||||
|
||||
protected final ItemStack item;
|
||||
final ItemStack item;
|
||||
final float damageMulitiplier;
|
||||
@Nullable
|
||||
final ResourceLocation breakableName;
|
||||
@Nullable
|
||||
final Tag<Block> breakable;
|
||||
|
||||
public TurtleTool( ResourceLocation id, String adjective, Item item )
|
||||
public TurtleTool( ResourceLocation id, String adjective, Item craftItem, ItemStack toolItem, float damageMulitiplier, @Nullable ResourceLocation breakableName, @Nullable Tag<Block> breakable )
|
||||
{
|
||||
super( id, TurtleUpgradeType.TOOL, adjective, item );
|
||||
this.item = new ItemStack( item );
|
||||
}
|
||||
|
||||
public TurtleTool( ResourceLocation id, Item item )
|
||||
{
|
||||
super( id, TurtleUpgradeType.TOOL, item );
|
||||
this.item = new ItemStack( item );
|
||||
}
|
||||
|
||||
public TurtleTool( ResourceLocation id, ItemStack craftItem, ItemStack toolItem )
|
||||
{
|
||||
super( id, TurtleUpgradeType.TOOL, craftItem );
|
||||
super( id, TurtleUpgradeType.TOOL, adjective, new ItemStack( craftItem ) );
|
||||
item = toolItem;
|
||||
this.damageMulitiplier = damageMulitiplier;
|
||||
this.breakableName = breakableName;
|
||||
this.breakable = breakable;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,8 +82,8 @@ public class TurtleTool extends AbstractTurtleUpgrade
|
||||
// Check we've not got anything vaguely interesting on the item. We allow other mods to add their
|
||||
// own NBT, with the understanding such details will be lost to the mist of time.
|
||||
if( stack.isDamaged() || stack.isEnchanted() || stack.hasCustomHoverName() ) return false;
|
||||
if( tag.contains( "AttributeModifiers", Tag.TAG_LIST ) &&
|
||||
!tag.getList( "AttributeModifiers", Tag.TAG_COMPOUND ).isEmpty() )
|
||||
if( tag.contains( "AttributeModifiers", TAG_LIST ) &&
|
||||
!tag.getList( "AttributeModifiers", TAG_COMPOUND ).isEmpty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -104,9 +106,9 @@ public class TurtleTool extends AbstractTurtleUpgrade
|
||||
switch( verb )
|
||||
{
|
||||
case ATTACK:
|
||||
return attack( turtle, direction, side );
|
||||
return attack( turtle, direction );
|
||||
case DIG:
|
||||
return dig( turtle, direction, side );
|
||||
return dig( turtle, direction );
|
||||
default:
|
||||
return TurtleCommandResult.failure( "Unsupported action" );
|
||||
}
|
||||
@ -115,19 +117,18 @@ public class TurtleTool extends AbstractTurtleUpgrade
|
||||
protected TurtleCommandResult checkBlockBreakable( BlockState state, Level world, BlockPos pos, TurtlePlayer player )
|
||||
{
|
||||
Block block = state.getBlock();
|
||||
return !state.isAir()
|
||||
&& block != Blocks.BEDROCK
|
||||
&& state.getDestroyProgress( player, world, pos ) > 0
|
||||
&& block.canEntityDestroy( state, world, pos, player )
|
||||
? TurtleCommandResult.success() : UNBREAKABLE;
|
||||
if( state.isAir() || block == Blocks.BEDROCK
|
||||
|| state.getDestroyProgress( player, world, pos ) <= 0
|
||||
|| !block.canEntityDestroy( state, world, pos, player ) )
|
||||
{
|
||||
return UNBREAKABLE;
|
||||
}
|
||||
|
||||
return breakable == null || breakable.contains( state.getBlock() ) || isTriviallyBreakable( world, pos, state )
|
||||
? TurtleCommandResult.success() : INEFFECTIVE;
|
||||
}
|
||||
|
||||
protected float getDamageMultiplier()
|
||||
{
|
||||
return 3.0f;
|
||||
}
|
||||
|
||||
private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side )
|
||||
private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction )
|
||||
{
|
||||
// Create a fake player, and orient it appropriately
|
||||
Level world = turtle.getLevel();
|
||||
@ -162,9 +163,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
|
||||
boolean attacked = false;
|
||||
if( !hitEntity.skipAttackInteraction( turtlePlayer ) )
|
||||
{
|
||||
float damage = (float) turtlePlayer.getAttributeValue( Attributes.ATTACK_DAMAGE );
|
||||
damage *= getDamageMultiplier();
|
||||
ComputerCraft.log.info( "Dealing {} damage", damage );
|
||||
float damage = (float) turtlePlayer.getAttributeValue( Attributes.ATTACK_DAMAGE ) * damageMulitiplier;
|
||||
if( damage > 0.0f )
|
||||
{
|
||||
DamageSource source = DamageSource.playerAttack( turtlePlayer );
|
||||
@ -196,8 +195,17 @@ public class TurtleTool extends AbstractTurtleUpgrade
|
||||
return TurtleCommandResult.failure( "Nothing to attack here" );
|
||||
}
|
||||
|
||||
private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, TurtleSide side )
|
||||
private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction )
|
||||
{
|
||||
// TODO: HOE_TILL really, if it's ever implemented
|
||||
if( item.canPerformAction( ToolActions.SHOVEL_FLATTEN ) || item.canPerformAction( ToolActions.HOE_DIG ) )
|
||||
{
|
||||
if( TurtlePlaceCommand.deployCopiedItem( item.copy(), turtle, direction, null, null ) )
|
||||
{
|
||||
return TurtleCommandResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
// Get ready to dig
|
||||
Level world = turtle.getLevel();
|
||||
BlockPos turtlePosition = turtle.getPosition();
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.turtle.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.SerializationTags;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class TurtleToolSerialiser extends TurtleUpgradeSerialiser.Base<TurtleTool>
|
||||
{
|
||||
public static final TurtleToolSerialiser INSTANCE = new TurtleToolSerialiser();
|
||||
|
||||
private TurtleToolSerialiser() {}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public TurtleTool fromJson( @Nonnull ResourceLocation id, @Nonnull JsonObject object )
|
||||
{
|
||||
var adjective = GsonHelper.getAsString( object, "adjective", IUpgradeBase.getDefaultAdjective( id ) );
|
||||
var toolItem = GsonHelper.getAsItem( object, "item" );
|
||||
var craftingItem = GsonHelper.getAsItem( object, "craftingItem", toolItem );
|
||||
var damageMultiplier = GsonHelper.getAsFloat( object, "damageMultiplier", 3.0f );
|
||||
|
||||
ResourceLocation breakableName = null;
|
||||
Tag<Block> breakable = null;
|
||||
if( object.has( "breakable" ) )
|
||||
{
|
||||
breakableName = new ResourceLocation( GsonHelper.getAsString( object, "breakable" ) );
|
||||
breakable = SerializationTags.getInstance().getTagOrThrow(
|
||||
Registry.BLOCK_REGISTRY, breakableName,
|
||||
tagId -> new JsonSyntaxException( "Unknown item tag '" + tagId + "'" )
|
||||
);
|
||||
}
|
||||
|
||||
return new TurtleTool( id, adjective, craftingItem, new ItemStack( toolItem ), damageMultiplier, breakableName, breakable );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public TurtleTool fromNetwork( @Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer )
|
||||
{
|
||||
var adjective = buffer.readUtf();
|
||||
var craftingItem = buffer.readRegistryIdUnsafe( ForgeRegistries.ITEMS );
|
||||
var toolItem = buffer.readItem();
|
||||
// damageMultiplier and breakable aren't used by the client, but we need to construct the upgrade exactly
|
||||
// as otherwise syncing on an SP world will overwrite the (shared) upgrade registry with an invalid upgrade!
|
||||
var damageMultiplier = buffer.readFloat();
|
||||
|
||||
ResourceLocation breakableName = null;
|
||||
Tag<Block> breakable = null;
|
||||
if( buffer.readBoolean() )
|
||||
{
|
||||
breakableName = buffer.readResourceLocation();
|
||||
breakable = SerializationTags.getInstance().getOrEmpty( Registry.BLOCK_REGISTRY ).getTagOrEmpty( breakableName );
|
||||
}
|
||||
return new TurtleTool( id, adjective, craftingItem, toolItem, damageMultiplier, breakableName, breakable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNetwork( @Nonnull FriendlyByteBuf buffer, @Nonnull TurtleTool upgrade )
|
||||
{
|
||||
buffer.writeUtf( upgrade.getUnlocalisedAdjective() );
|
||||
buffer.writeRegistryIdUnsafe( ForgeRegistries.ITEMS, upgrade.getCraftingItem().getItem() );
|
||||
buffer.writeItem( upgrade.item );
|
||||
buffer.writeFloat( upgrade.damageMulitiplier );
|
||||
buffer.writeBoolean( upgrade.breakableName != null );
|
||||
if( upgrade.breakableName != null ) buffer.writeResourceLocation( upgrade.breakableName );
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"pack_format": 6,
|
||||
"pack_format": 7,
|
||||
"description": "CC: Tweaked"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"pack_format": 4,
|
||||
"pack_format": 7,
|
||||
"description": "CC: Test"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user