mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-20 23:34:48 +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:
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +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;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
public class ComputerCraftTags
|
||||
{
|
||||
public static class Items
|
||||
{
|
||||
public static final Tag.Named<Item> COMPUTER = make( "computer" );
|
||||
public static final Tag.Named<Item> TURTLE = make( "turtle" );
|
||||
public static final Tag.Named<Item> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final Tag.Named<Item> MONITOR = make( "monitor" );
|
||||
|
||||
private static Tag.Named<Item> make( String name )
|
||||
{
|
||||
return ItemTags.bind( new ResourceLocation( ComputerCraft.MOD_ID, name ).toString() );
|
||||
}
|
||||
}
|
||||
|
||||
public static class Blocks
|
||||
{
|
||||
public static final Tag.Named<Block> COMPUTER = make( "computer" );
|
||||
public static final Tag.Named<Block> TURTLE = make( "turtle" );
|
||||
public static final Tag.Named<Block> WIRED_MODEM = make( "wired_modem" );
|
||||
public static final Tag.Named<Block> MONITOR = make( "monitor" );
|
||||
|
||||
public static final Tag.Named<Block> TURTLE_ALWAYS_BREAKABLE = make( "turtle_always_breakable" );
|
||||
public static final Tag.Named<Block> TURTLE_SHOVEL_BREAKABLE = make( "turtle_shovel_harvestable" );
|
||||
public static final Tag.Named<Block> TURTLE_SWORD_BREAKABLE = make( "turtle_sword_harvestable" );
|
||||
public static final Tag.Named<Block> TURTLE_HOE_BREAKABLE = make( "turtle_hoe_harvestable" );
|
||||
|
||||
private static Tag.Named<Block> make( String name )
|
||||
{
|
||||
return BlockTags.bind( new ResourceLocation( ComputerCraft.MOD_ID, name ).toString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user