mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-11-03 23:22:59 +00:00 
			
		
		
		
	gradle=7.1.1, gradle migrateMappings
This commit is contained in:
		@@ -0,0 +1,168 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.apis;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.lua.ILuaAPI;
 | 
			
		||||
import dan200.computercraft.api.lua.LuaFunction;
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.shared.PocketUpgrades;
 | 
			
		||||
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
 | 
			
		||||
import dan200.computercraft.shared.util.InventoryUtil;
 | 
			
		||||
import dan200.computercraft.shared.util.ItemStorage;
 | 
			
		||||
import dan200.computercraft.shared.util.WorldUtil;
 | 
			
		||||
import net.minecraft.entity.Entity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.collection.DefaultedList;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Control the current pocket computer, adding or removing upgrades.
 | 
			
		||||
 *
 | 
			
		||||
 * This API is only available on pocket computers. As such, you may use its presence to determine what kind of computer you are using:
 | 
			
		||||
 *
 | 
			
		||||
 * <pre>
 | 
			
		||||
 * if pocket then
 | 
			
		||||
 *   print("On a pocket computer")
 | 
			
		||||
 * else
 | 
			
		||||
 *   print("On something else")
 | 
			
		||||
 * end
 | 
			
		||||
 * </pre>
 | 
			
		||||
 *
 | 
			
		||||
 * @cc.module pocket
 | 
			
		||||
 */
 | 
			
		||||
public class PocketAPI implements ILuaAPI
 | 
			
		||||
{
 | 
			
		||||
    private final PocketServerComputer computer;
 | 
			
		||||
 | 
			
		||||
    public PocketAPI( PocketServerComputer computer )
 | 
			
		||||
    {
 | 
			
		||||
        this.computer = computer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String[] getNames()
 | 
			
		||||
    {
 | 
			
		||||
        return new String[] { "pocket" };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Search the player's inventory for another upgrade, replacing the existing one with that item if found.
 | 
			
		||||
     *
 | 
			
		||||
     * This inventory search starts from the player's currently selected slot, allowing you to prioritise upgrades.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The result of equipping.
 | 
			
		||||
     * @cc.treturn boolean If an item was equipped.
 | 
			
		||||
     * @cc.treturn string|nil The reason an item was not equipped.
 | 
			
		||||
     */
 | 
			
		||||
    @LuaFunction( mainThread = true )
 | 
			
		||||
    public final Object[] equipBack()
 | 
			
		||||
    {
 | 
			
		||||
        Entity entity = computer.getEntity();
 | 
			
		||||
        if( !(entity instanceof PlayerEntity) )
 | 
			
		||||
        {
 | 
			
		||||
            return new Object[] { false, "Cannot find player" };
 | 
			
		||||
        }
 | 
			
		||||
        PlayerEntity player = (PlayerEntity) entity;
 | 
			
		||||
        PlayerInventory inventory = player.inventory;
 | 
			
		||||
        IPocketUpgrade previousUpgrade = computer.getUpgrade();
 | 
			
		||||
 | 
			
		||||
        // Attempt to find the upgrade, starting in the main segment, and then looking in the opposite
 | 
			
		||||
        // one. We start from the position the item is currently in and loop round to the start.
 | 
			
		||||
        IPocketUpgrade newUpgrade = findUpgrade( inventory.main, inventory.selectedSlot, previousUpgrade );
 | 
			
		||||
        if( newUpgrade == null )
 | 
			
		||||
        {
 | 
			
		||||
            newUpgrade = findUpgrade( inventory.offHand, 0, previousUpgrade );
 | 
			
		||||
        }
 | 
			
		||||
        if( newUpgrade == null )
 | 
			
		||||
        {
 | 
			
		||||
            return new Object[] { false, "Cannot find a valid upgrade" };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Remove the current upgrade
 | 
			
		||||
        if( previousUpgrade != null )
 | 
			
		||||
        {
 | 
			
		||||
            ItemStack stack = previousUpgrade.getCraftingItem();
 | 
			
		||||
            if( !stack.isEmpty() )
 | 
			
		||||
            {
 | 
			
		||||
                stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot );
 | 
			
		||||
                if( !stack.isEmpty() )
 | 
			
		||||
                {
 | 
			
		||||
                    WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Set the new upgrade
 | 
			
		||||
        computer.setUpgrade( newUpgrade );
 | 
			
		||||
 | 
			
		||||
        return new Object[] { true };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static IPocketUpgrade findUpgrade( DefaultedList<ItemStack> inv, int start, IPocketUpgrade previous )
 | 
			
		||||
    {
 | 
			
		||||
        for( int i = 0; i < inv.size(); i++ )
 | 
			
		||||
        {
 | 
			
		||||
            ItemStack invStack = inv.get( (i + start) % inv.size() );
 | 
			
		||||
            if( !invStack.isEmpty() )
 | 
			
		||||
            {
 | 
			
		||||
                IPocketUpgrade newUpgrade = PocketUpgrades.get( invStack );
 | 
			
		||||
 | 
			
		||||
                if( newUpgrade != null && newUpgrade != previous )
 | 
			
		||||
                {
 | 
			
		||||
                    // Consume an item from this stack and exit the loop
 | 
			
		||||
                    invStack = invStack.copy();
 | 
			
		||||
                    invStack.decrement( 1 );
 | 
			
		||||
                    inv.set( (i + start) % inv.size(), invStack.isEmpty() ? ItemStack.EMPTY : invStack );
 | 
			
		||||
 | 
			
		||||
                    return newUpgrade;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Remove the pocket computer's current upgrade.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The result of unequipping.
 | 
			
		||||
     * @cc.treturn boolean If the upgrade was unequipped.
 | 
			
		||||
     * @cc.treturn string|nil The reason an upgrade was not unequipped.
 | 
			
		||||
     */
 | 
			
		||||
    @LuaFunction( mainThread = true )
 | 
			
		||||
    public final Object[] unequipBack()
 | 
			
		||||
    {
 | 
			
		||||
        Entity entity = computer.getEntity();
 | 
			
		||||
        if( !(entity instanceof PlayerEntity) )
 | 
			
		||||
        {
 | 
			
		||||
            return new Object[] { false, "Cannot find player" };
 | 
			
		||||
        }
 | 
			
		||||
        PlayerEntity player = (PlayerEntity) entity;
 | 
			
		||||
        PlayerInventory inventory = player.inventory;
 | 
			
		||||
        IPocketUpgrade previousUpgrade = computer.getUpgrade();
 | 
			
		||||
 | 
			
		||||
        if( previousUpgrade == null )
 | 
			
		||||
        {
 | 
			
		||||
            return new Object[] { false, "Nothing to unequip" };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        computer.setUpgrade( null );
 | 
			
		||||
 | 
			
		||||
        ItemStack stack = previousUpgrade.getCraftingItem();
 | 
			
		||||
        if( !stack.isEmpty() )
 | 
			
		||||
        {
 | 
			
		||||
            stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot );
 | 
			
		||||
            if( stack.isEmpty() )
 | 
			
		||||
            {
 | 
			
		||||
                WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new Object[] { true };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,210 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.core;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketAccess;
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.core.computer.ComputerSide;
 | 
			
		||||
import dan200.computercraft.shared.common.IColouredItem;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ServerComputer;
 | 
			
		||||
import dan200.computercraft.shared.network.NetworkHandler;
 | 
			
		||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
 | 
			
		||||
import dan200.computercraft.shared.util.NBTUtil;
 | 
			
		||||
import net.minecraft.entity.Entity;
 | 
			
		||||
import net.minecraft.entity.LivingEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT;
 | 
			
		||||
 | 
			
		||||
public class PocketServerComputer extends ServerComputer implements IPocketAccess
 | 
			
		||||
{
 | 
			
		||||
    private IPocketUpgrade upgrade;
 | 
			
		||||
    private Entity entity;
 | 
			
		||||
    private ItemStack stack;
 | 
			
		||||
 | 
			
		||||
    public PocketServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family )
 | 
			
		||||
    {
 | 
			
		||||
        super( world, computerID, label, instanceID, family, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public Entity getEntity()
 | 
			
		||||
    {
 | 
			
		||||
        Entity entity = this.entity;
 | 
			
		||||
        if( entity == null || stack == null || !entity.isAlive() )
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( entity instanceof PlayerEntity )
 | 
			
		||||
        {
 | 
			
		||||
            PlayerInventory inventory = ((PlayerEntity) entity).inventory;
 | 
			
		||||
            return inventory.main.contains( stack ) || inventory.offHand.contains( stack ) ? entity : null;
 | 
			
		||||
        }
 | 
			
		||||
        else if( entity instanceof LivingEntity )
 | 
			
		||||
        {
 | 
			
		||||
            LivingEntity living = (LivingEntity) entity;
 | 
			
		||||
            return living.getMainHandStack() == stack || living.getOffHandStack() == stack ? entity : null;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getColour()
 | 
			
		||||
    {
 | 
			
		||||
        return IColouredItem.getColourBasic( stack );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setColour( int colour )
 | 
			
		||||
    {
 | 
			
		||||
        IColouredItem.setColourBasic( stack, colour );
 | 
			
		||||
        updateUpgradeNBTData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getLight()
 | 
			
		||||
    {
 | 
			
		||||
        NbtCompound tag = getUserData();
 | 
			
		||||
        return tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_LIGHT ) : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setLight( int colour )
 | 
			
		||||
    {
 | 
			
		||||
        NbtCompound tag = getUserData();
 | 
			
		||||
        if( colour >= 0 && colour <= 0xFFFFFF )
 | 
			
		||||
        {
 | 
			
		||||
            if( !tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) || tag.getInt( NBT_LIGHT ) != colour )
 | 
			
		||||
            {
 | 
			
		||||
                tag.putInt( NBT_LIGHT, colour );
 | 
			
		||||
                updateUserData();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if( tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) )
 | 
			
		||||
        {
 | 
			
		||||
            tag.remove( NBT_LIGHT );
 | 
			
		||||
            updateUserData();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public NbtCompound getUpgradeNBTData()
 | 
			
		||||
    {
 | 
			
		||||
        return ItemPocketComputer.getUpgradeInfo( stack );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateUpgradeNBTData()
 | 
			
		||||
    {
 | 
			
		||||
        if( entity instanceof PlayerEntity )
 | 
			
		||||
        {
 | 
			
		||||
            ((PlayerEntity) entity).inventory.markDirty();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void invalidatePeripheral()
 | 
			
		||||
    {
 | 
			
		||||
        IPeripheral peripheral = upgrade == null ? null : upgrade.createPeripheral( this );
 | 
			
		||||
        setPeripheral( ComputerSide.BACK, peripheral );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public Map<Identifier, IPeripheral> getUpgrades()
 | 
			
		||||
    {
 | 
			
		||||
        return upgrade == null ? Collections.emptyMap() : Collections.singletonMap( upgrade.getUpgradeID(), getPeripheral( ComputerSide.BACK ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public IPocketUpgrade getUpgrade()
 | 
			
		||||
    {
 | 
			
		||||
        return upgrade;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the upgrade for this pocket computer, also updating the item stack.
 | 
			
		||||
     *
 | 
			
		||||
     * Note this method is not thread safe - it must be called from the server thread.
 | 
			
		||||
     *
 | 
			
		||||
     * @param upgrade The new upgrade to set it to, may be {@code null}.
 | 
			
		||||
     */
 | 
			
		||||
    public void setUpgrade( IPocketUpgrade upgrade )
 | 
			
		||||
    {
 | 
			
		||||
        if( this.upgrade == upgrade )
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        synchronized( this )
 | 
			
		||||
        {
 | 
			
		||||
            ItemPocketComputer.setUpgrade( stack, upgrade );
 | 
			
		||||
            updateUpgradeNBTData();
 | 
			
		||||
            this.upgrade = upgrade;
 | 
			
		||||
            invalidatePeripheral();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public synchronized void updateValues( Entity entity, @Nonnull ItemStack stack, IPocketUpgrade upgrade )
 | 
			
		||||
    {
 | 
			
		||||
        if( entity != null )
 | 
			
		||||
        {
 | 
			
		||||
            setWorld( entity.getEntityWorld() );
 | 
			
		||||
            setPosition( entity.getBlockPos() );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If a new entity has picked it up then rebroadcast the terminal to them
 | 
			
		||||
        if( entity != this.entity && entity instanceof ServerPlayerEntity )
 | 
			
		||||
        {
 | 
			
		||||
            markTerminalChanged();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.entity = entity;
 | 
			
		||||
        this.stack = stack;
 | 
			
		||||
 | 
			
		||||
        if( this.upgrade != upgrade )
 | 
			
		||||
        {
 | 
			
		||||
            this.upgrade = upgrade;
 | 
			
		||||
            invalidatePeripheral();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void broadcastState( boolean force )
 | 
			
		||||
    {
 | 
			
		||||
        super.broadcastState( force );
 | 
			
		||||
 | 
			
		||||
        if( (hasTerminalChanged() || force) && entity instanceof ServerPlayerEntity )
 | 
			
		||||
        {
 | 
			
		||||
            // Broadcast the state to the current entity if they're not already interacting with it.
 | 
			
		||||
            ServerPlayerEntity player = (ServerPlayerEntity) entity;
 | 
			
		||||
            if( player.networkHandler != null && !isInteracting( player ) )
 | 
			
		||||
            {
 | 
			
		||||
                NetworkHandler.sendToPlayer( player, createTerminalPacket() );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,78 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.inventory;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.shared.ComputerCraftRegistry;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ServerComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
 | 
			
		||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
 | 
			
		||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.network.PacketByteBuf;
 | 
			
		||||
import net.minecraft.screen.ScreenHandler;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.Hand;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
public final class ContainerPocketComputer extends ContainerComputerBase
 | 
			
		||||
{
 | 
			
		||||
    private ContainerPocketComputer( int id, ServerComputer computer, ItemPocketComputer item, Hand hand )
 | 
			
		||||
    {
 | 
			
		||||
        super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, p -> {
 | 
			
		||||
            ItemStack stack = p.getStackInHand( hand );
 | 
			
		||||
            return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer;
 | 
			
		||||
        }, computer, item.getFamily() );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ContainerPocketComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf )
 | 
			
		||||
    {
 | 
			
		||||
        super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, player, packetByteBuf );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Factory implements ExtendedScreenHandlerFactory
 | 
			
		||||
    {
 | 
			
		||||
        private final ServerComputer computer;
 | 
			
		||||
        private final Text name;
 | 
			
		||||
        private final ItemPocketComputer item;
 | 
			
		||||
        private final Hand hand;
 | 
			
		||||
 | 
			
		||||
        public Factory( ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand )
 | 
			
		||||
        {
 | 
			
		||||
            this.computer = computer;
 | 
			
		||||
            name = stack.getName();
 | 
			
		||||
            this.item = item;
 | 
			
		||||
            this.hand = hand;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        @Nonnull
 | 
			
		||||
        @Override
 | 
			
		||||
        public Text getDisplayName()
 | 
			
		||||
        {
 | 
			
		||||
            return name;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Nullable
 | 
			
		||||
        @Override
 | 
			
		||||
        public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity )
 | 
			
		||||
        {
 | 
			
		||||
            return new ContainerPocketComputer( id, computer, item, hand );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf )
 | 
			
		||||
        {
 | 
			
		||||
            packetByteBuf.writeInt( computer.getInstanceID() );
 | 
			
		||||
            packetByteBuf.writeEnumConstant( computer.getFamily() );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,437 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.items;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Objects;
 | 
			
		||||
import dan200.computercraft.ComputerCraft;
 | 
			
		||||
import dan200.computercraft.api.ComputerCraftAPI;
 | 
			
		||||
import dan200.computercraft.api.filesystem.IMount;
 | 
			
		||||
import dan200.computercraft.api.media.IMedia;
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.core.computer.ComputerSide;
 | 
			
		||||
import dan200.computercraft.shared.PocketUpgrades;
 | 
			
		||||
import dan200.computercraft.shared.common.IColouredItem;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ClientComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerState;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ServerComputer;
 | 
			
		||||
import dan200.computercraft.shared.computer.items.IComputerItem;
 | 
			
		||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
 | 
			
		||||
import dan200.computercraft.shared.pocket.apis.PocketAPI;
 | 
			
		||||
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
 | 
			
		||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.minecraft.client.item.TooltipContext;
 | 
			
		||||
import net.minecraft.entity.Entity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemGroup;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.text.LiteralText;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.text.TranslatableText;
 | 
			
		||||
import net.minecraft.util.ActionResult;
 | 
			
		||||
import net.minecraft.util.Formatting;
 | 
			
		||||
import net.minecraft.util.Hand;
 | 
			
		||||
import net.minecraft.util.TypedActionResult;
 | 
			
		||||
import net.minecraft.util.collection.DefaultedList;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class ItemPocketComputer extends Item implements IComputerItem, IMedia, IColouredItem
 | 
			
		||||
{
 | 
			
		||||
    public static final String NBT_LIGHT = "Light";
 | 
			
		||||
    private static final String NBT_UPGRADE = "Upgrade";
 | 
			
		||||
    private static final String NBT_UPGRADE_INFO = "UpgradeInfo";
 | 
			
		||||
    private static final String NBT_INSTANCE = "Instanceid";
 | 
			
		||||
    private static final String NBT_SESSION = "SessionId";
 | 
			
		||||
 | 
			
		||||
    private final ComputerFamily family;
 | 
			
		||||
 | 
			
		||||
    public ItemPocketComputer( Settings settings, ComputerFamily family )
 | 
			
		||||
    {
 | 
			
		||||
        super( settings );
 | 
			
		||||
        this.family = family;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ServerComputer getServerComputer( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        int session = getSessionID( stack );
 | 
			
		||||
        if( session != ComputerCraft.serverComputerRegistry.getSessionID() ) return null;
 | 
			
		||||
 | 
			
		||||
        int instanceID = getInstanceID( stack );
 | 
			
		||||
        return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get( instanceID ) : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Environment( EnvType.CLIENT )
 | 
			
		||||
    public static ComputerState getState( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        ClientComputer computer = getClientComputer( stack );
 | 
			
		||||
        return computer == null ? ComputerState.OFF : computer.getState();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static ClientComputer getClientComputer( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        int instanceID = getInstanceID( stack );
 | 
			
		||||
        return instanceID >= 0 ? ComputerCraft.clientComputerRegistry.get( instanceID ) : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Environment( EnvType.CLIENT )
 | 
			
		||||
    public static int getLightState( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        ClientComputer computer = getClientComputer( stack );
 | 
			
		||||
        if( computer != null && computer.isOn() )
 | 
			
		||||
        {
 | 
			
		||||
            NbtCompound computerNBT = computer.getUserData();
 | 
			
		||||
            if( computerNBT != null && computerNBT.contains( NBT_LIGHT ) )
 | 
			
		||||
            {
 | 
			
		||||
                return computerNBT.getInt( NBT_LIGHT );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void setUpgrade( @Nonnull ItemStack stack, IPocketUpgrade upgrade )
 | 
			
		||||
    {
 | 
			
		||||
        NbtCompound compound = stack.getOrCreateNbt();
 | 
			
		||||
 | 
			
		||||
        if( upgrade == null )
 | 
			
		||||
        {
 | 
			
		||||
            compound.remove( NBT_UPGRADE );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            compound.putString( NBT_UPGRADE,
 | 
			
		||||
                upgrade.getUpgradeID()
 | 
			
		||||
                    .toString() );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        compound.remove( NBT_UPGRADE_INFO );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static NbtCompound getUpgradeInfo( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        return stack.getOrCreateSubNbt( NBT_UPGRADE_INFO );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //    @Nullable
 | 
			
		||||
    //    @Override
 | 
			
		||||
    //    public String getCreatorModId( ItemStack stack )
 | 
			
		||||
    //    {
 | 
			
		||||
    //        IPocketUpgrade upgrade = getUpgrade( stack );
 | 
			
		||||
    //        if( upgrade != null )
 | 
			
		||||
    //        {
 | 
			
		||||
    //            // If we're a non-vanilla, non-CC upgrade then return whichever mod this upgrade
 | 
			
		||||
    //            // belongs to.
 | 
			
		||||
    //            String mod = PocketUpgrades.getOwner( upgrade );
 | 
			
		||||
    //            if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod;
 | 
			
		||||
    //        }
 | 
			
		||||
    //
 | 
			
		||||
    //        return super.getCreatorModId( stack );
 | 
			
		||||
    //    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public TypedActionResult<ItemStack> use( World world, PlayerEntity player, @Nonnull Hand hand )
 | 
			
		||||
    {
 | 
			
		||||
        ItemStack stack = player.getStackInHand( hand );
 | 
			
		||||
        if( !world.isClient )
 | 
			
		||||
        {
 | 
			
		||||
            PocketServerComputer computer = createServerComputer( world, player.inventory, player, stack );
 | 
			
		||||
 | 
			
		||||
            boolean stop = false;
 | 
			
		||||
            if( computer != null )
 | 
			
		||||
            {
 | 
			
		||||
                computer.turnOn();
 | 
			
		||||
 | 
			
		||||
                IPocketUpgrade upgrade = getUpgrade( stack );
 | 
			
		||||
                if( upgrade != null )
 | 
			
		||||
                {
 | 
			
		||||
                    computer.updateValues( player, stack, upgrade );
 | 
			
		||||
                    stop = upgrade.onRightClick( world, computer, computer.getPeripheral( ComputerSide.BACK ) );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if( !stop && computer != null )
 | 
			
		||||
            {
 | 
			
		||||
                computer.sendTerminalState( player );
 | 
			
		||||
                new ComputerContainerData( computer ).open( player, new ContainerPocketComputer.Factory( computer, stack, this, hand ) );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return new TypedActionResult<>( ActionResult.SUCCESS, stack );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void inventoryTick( @Nonnull ItemStack stack, World world, @Nonnull Entity entity, int slotNum, boolean selected )
 | 
			
		||||
    {
 | 
			
		||||
        if( !world.isClient )
 | 
			
		||||
        {
 | 
			
		||||
            // Server side
 | 
			
		||||
            Inventory inventory = entity instanceof PlayerEntity ? ((PlayerEntity) entity).inventory : null;
 | 
			
		||||
            PocketServerComputer computer = createServerComputer( world, inventory, entity, stack );
 | 
			
		||||
            if( computer != null )
 | 
			
		||||
            {
 | 
			
		||||
                IPocketUpgrade upgrade = getUpgrade( stack );
 | 
			
		||||
 | 
			
		||||
                // Ping computer
 | 
			
		||||
                computer.keepAlive();
 | 
			
		||||
                computer.setWorld( world );
 | 
			
		||||
                computer.updateValues( entity, stack, upgrade );
 | 
			
		||||
 | 
			
		||||
                // Sync ID
 | 
			
		||||
                int id = computer.getID();
 | 
			
		||||
                if( id != getComputerID( stack ) )
 | 
			
		||||
                {
 | 
			
		||||
                    setComputerID( stack, id );
 | 
			
		||||
                    if( inventory != null )
 | 
			
		||||
                    {
 | 
			
		||||
                        inventory.markDirty();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Sync label
 | 
			
		||||
                String label = computer.getLabel();
 | 
			
		||||
                if( !Objects.equal( label, getLabel( stack ) ) )
 | 
			
		||||
                {
 | 
			
		||||
                    setLabel( stack, label );
 | 
			
		||||
                    if( inventory != null )
 | 
			
		||||
                    {
 | 
			
		||||
                        inventory.markDirty();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Update pocket upgrade
 | 
			
		||||
                if( upgrade != null )
 | 
			
		||||
                {
 | 
			
		||||
                    upgrade.update( computer, computer.getPeripheral( ComputerSide.BACK ) );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // Client side
 | 
			
		||||
            createClientComputer( stack );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List<Text> list, TooltipContext flag )
 | 
			
		||||
    {
 | 
			
		||||
        if( flag.isAdvanced() || getLabel( stack ) == null )
 | 
			
		||||
        {
 | 
			
		||||
            int id = getComputerID( stack );
 | 
			
		||||
            if( id >= 0 )
 | 
			
		||||
            {
 | 
			
		||||
                list.add( new TranslatableText( "gui.computercraft.tooltip.computer_id", id ).formatted( Formatting.GRAY ) );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public Text getName( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        String baseString = getTranslationKey( stack );
 | 
			
		||||
        IPocketUpgrade upgrade = getUpgrade( stack );
 | 
			
		||||
        if( upgrade != null )
 | 
			
		||||
        {
 | 
			
		||||
            return new TranslatableText( baseString + ".upgraded", new TranslatableText( upgrade.getUnlocalisedAdjective() ) );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return super.getName( stack );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // IComputerItem implementation
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList<ItemStack> stacks )
 | 
			
		||||
    {
 | 
			
		||||
        if( !isIn( group ) )
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        stacks.add( create( -1, null, -1, null ) );
 | 
			
		||||
        for( IPocketUpgrade upgrade : PocketUpgrades.getVanillaUpgrades() )
 | 
			
		||||
        {
 | 
			
		||||
            stacks.add( create( -1, null, -1, upgrade ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack create( int id, String label, int colour, IPocketUpgrade upgrade )
 | 
			
		||||
    {
 | 
			
		||||
        ItemStack result = new ItemStack( this );
 | 
			
		||||
        if( id >= 0 )
 | 
			
		||||
        {
 | 
			
		||||
            result.getOrCreateNbt()
 | 
			
		||||
                .putInt( NBT_ID, id );
 | 
			
		||||
        }
 | 
			
		||||
        if( label != null )
 | 
			
		||||
        {
 | 
			
		||||
            result.setCustomName( new LiteralText( label ) );
 | 
			
		||||
        }
 | 
			
		||||
        if( upgrade != null )
 | 
			
		||||
        {
 | 
			
		||||
            result.getOrCreateNbt()
 | 
			
		||||
                .putString( NBT_UPGRADE,
 | 
			
		||||
                    upgrade.getUpgradeID()
 | 
			
		||||
                        .toString() );
 | 
			
		||||
        }
 | 
			
		||||
        if( colour != -1 )
 | 
			
		||||
        {
 | 
			
		||||
            result.getOrCreateNbt()
 | 
			
		||||
                .putInt( NBT_COLOUR, colour );
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public PocketServerComputer createServerComputer( final World world, Inventory inventory, Entity entity, @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        if( world.isClient )
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        PocketServerComputer computer;
 | 
			
		||||
        int instanceID = getInstanceID( stack );
 | 
			
		||||
        int sessionID = getSessionID( stack );
 | 
			
		||||
        int correctSessionID = ComputerCraft.serverComputerRegistry.getSessionID();
 | 
			
		||||
 | 
			
		||||
        if( instanceID >= 0 && sessionID == correctSessionID && ComputerCraft.serverComputerRegistry.contains( instanceID ) )
 | 
			
		||||
        {
 | 
			
		||||
            computer = (PocketServerComputer) ComputerCraft.serverComputerRegistry.get( instanceID );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if( instanceID < 0 || sessionID != correctSessionID )
 | 
			
		||||
            {
 | 
			
		||||
                instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID();
 | 
			
		||||
                setInstanceID( stack, instanceID );
 | 
			
		||||
                setSessionID( stack, correctSessionID );
 | 
			
		||||
            }
 | 
			
		||||
            int computerID = getComputerID( stack );
 | 
			
		||||
            if( computerID < 0 )
 | 
			
		||||
            {
 | 
			
		||||
                computerID = ComputerCraftAPI.createUniqueNumberedSaveDir( world, "computer" );
 | 
			
		||||
                setComputerID( stack, computerID );
 | 
			
		||||
            }
 | 
			
		||||
            computer = new PocketServerComputer( world, computerID, getLabel( stack ), instanceID, getFamily() );
 | 
			
		||||
            computer.updateValues( entity, stack, getUpgrade( stack ) );
 | 
			
		||||
            computer.addAPI( new PocketAPI( computer ) );
 | 
			
		||||
            ComputerCraft.serverComputerRegistry.add( instanceID, computer );
 | 
			
		||||
            if( inventory != null )
 | 
			
		||||
            {
 | 
			
		||||
                inventory.markDirty();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        computer.setWorld( world );
 | 
			
		||||
        return computer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static IPocketUpgrade getUpgrade( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        NbtCompound compound = stack.getNbt();
 | 
			
		||||
        return compound != null && compound.contains( NBT_UPGRADE ) ? PocketUpgrades.get( compound.getString( NBT_UPGRADE ) ) : null;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // IMedia
 | 
			
		||||
 | 
			
		||||
    private static void setComputerID( @Nonnull ItemStack stack, int computerID )
 | 
			
		||||
    {
 | 
			
		||||
        stack.getOrCreateNbt()
 | 
			
		||||
            .putInt( NBT_ID, computerID );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getLabel( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        return IComputerItem.super.getLabel( stack );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ComputerFamily getFamily()
 | 
			
		||||
    {
 | 
			
		||||
        return family;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family )
 | 
			
		||||
    {
 | 
			
		||||
        return PocketComputerItemFactory.create( getComputerID( stack ), getLabel( stack ), getColour( stack ), family, getUpgrade( stack ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean setLabel( @Nonnull ItemStack stack, String label )
 | 
			
		||||
    {
 | 
			
		||||
        if( label != null )
 | 
			
		||||
        {
 | 
			
		||||
            stack.setCustomName( new LiteralText( label ) );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            stack.removeCustomName();
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ClientComputer createClientComputer( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        int instanceID = getInstanceID( stack );
 | 
			
		||||
        if( instanceID >= 0 )
 | 
			
		||||
        {
 | 
			
		||||
            if( !ComputerCraft.clientComputerRegistry.contains( instanceID ) )
 | 
			
		||||
            {
 | 
			
		||||
                ComputerCraft.clientComputerRegistry.add( instanceID, new ClientComputer( instanceID ) );
 | 
			
		||||
            }
 | 
			
		||||
            return ComputerCraft.clientComputerRegistry.get( instanceID );
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int getInstanceID( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        NbtCompound nbt = stack.getNbt();
 | 
			
		||||
        return nbt != null && nbt.contains( NBT_INSTANCE ) ? nbt.getInt( NBT_INSTANCE ) : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int getSessionID( @Nonnull ItemStack stack )
 | 
			
		||||
    {
 | 
			
		||||
        NbtCompound nbt = stack.getNbt();
 | 
			
		||||
        return nbt != null && nbt.contains( NBT_SESSION ) ? nbt.getInt( NBT_SESSION ) : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void setInstanceID( @Nonnull ItemStack stack, int instanceID )
 | 
			
		||||
    {
 | 
			
		||||
        stack.getOrCreateNbt()
 | 
			
		||||
            .putInt( NBT_INSTANCE, instanceID );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void setSessionID( @Nonnull ItemStack stack, int sessionID )
 | 
			
		||||
    {
 | 
			
		||||
        stack.getOrCreateNbt()
 | 
			
		||||
            .putInt( NBT_SESSION, sessionID );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world )
 | 
			
		||||
    {
 | 
			
		||||
        int id = getComputerID( stack );
 | 
			
		||||
        if( id >= 0 )
 | 
			
		||||
        {
 | 
			
		||||
            return ComputerCraftAPI.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit );
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,33 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.items;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.shared.ComputerCraftRegistry;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public final class PocketComputerItemFactory
 | 
			
		||||
{
 | 
			
		||||
    private PocketComputerItemFactory() {}
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static ItemStack create( int id, String label, int colour, ComputerFamily family, IPocketUpgrade upgrade )
 | 
			
		||||
    {
 | 
			
		||||
        switch( family )
 | 
			
		||||
        {
 | 
			
		||||
            case NORMAL:
 | 
			
		||||
                return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.create( id, label, colour, upgrade );
 | 
			
		||||
            case ADVANCED:
 | 
			
		||||
                return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.create( id, label, colour, upgrade );
 | 
			
		||||
            default:
 | 
			
		||||
                return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,61 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.peripherals;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketAccess;
 | 
			
		||||
import dan200.computercraft.shared.ComputerCraftRegistry;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
 | 
			
		||||
import net.minecraft.entity.Entity;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
public class PocketModem extends AbstractPocketUpgrade
 | 
			
		||||
{
 | 
			
		||||
    private final boolean advanced;
 | 
			
		||||
 | 
			
		||||
    public PocketModem( boolean advanced )
 | 
			
		||||
    {
 | 
			
		||||
        super( new Identifier( "computercraft", advanced ? "wireless_modem_advanced" : "wireless_modem_normal" ),
 | 
			
		||||
            advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL );
 | 
			
		||||
        this.advanced = advanced;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPeripheral createPeripheral( @Nonnull IPocketAccess access )
 | 
			
		||||
    {
 | 
			
		||||
        return new PocketModemPeripheral( advanced );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
 | 
			
		||||
    {
 | 
			
		||||
        if( !(peripheral instanceof PocketModemPeripheral) )
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Entity entity = access.getEntity();
 | 
			
		||||
 | 
			
		||||
        PocketModemPeripheral modem = (PocketModemPeripheral) peripheral;
 | 
			
		||||
 | 
			
		||||
        if( entity != null )
 | 
			
		||||
        {
 | 
			
		||||
            modem.setLocation( entity.getEntityWorld(), entity.getCameraPosVec( 1 ) );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ModemState state = modem.getModemState();
 | 
			
		||||
        if( state.pollChanged() )
 | 
			
		||||
        {
 | 
			
		||||
            access.setLight( state.isOpen() ? 0xBA0000 : -1 );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.peripherals;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral;
 | 
			
		||||
import net.minecraft.util.math.Vec3d;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public class PocketModemPeripheral extends WirelessModemPeripheral
 | 
			
		||||
{
 | 
			
		||||
    private World world = null;
 | 
			
		||||
    private Vec3d position = Vec3d.ZERO;
 | 
			
		||||
 | 
			
		||||
    public PocketModemPeripheral( boolean advanced )
 | 
			
		||||
    {
 | 
			
		||||
        super( new ModemState(), advanced );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setLocation( World world, Vec3d position )
 | 
			
		||||
    {
 | 
			
		||||
        this.position = position;
 | 
			
		||||
        this.world = world;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public World getWorld()
 | 
			
		||||
    {
 | 
			
		||||
        return world;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public Vec3d getPosition()
 | 
			
		||||
    {
 | 
			
		||||
        return position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals( IPeripheral other )
 | 
			
		||||
    {
 | 
			
		||||
        return other instanceof PocketModemPeripheral;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.peripherals;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketAccess;
 | 
			
		||||
import dan200.computercraft.shared.ComputerCraftRegistry;
 | 
			
		||||
import net.minecraft.entity.Entity;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
public class PocketSpeaker extends AbstractPocketUpgrade
 | 
			
		||||
{
 | 
			
		||||
    public PocketSpeaker()
 | 
			
		||||
    {
 | 
			
		||||
        super( new Identifier( "computercraft", "speaker" ), ComputerCraftRegistry.ModBlocks.SPEAKER );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPeripheral createPeripheral( @Nonnull IPocketAccess access )
 | 
			
		||||
    {
 | 
			
		||||
        return new PocketSpeakerPeripheral();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
 | 
			
		||||
    {
 | 
			
		||||
        if( !(peripheral instanceof PocketSpeakerPeripheral) )
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        PocketSpeakerPeripheral speaker = (PocketSpeakerPeripheral) peripheral;
 | 
			
		||||
 | 
			
		||||
        Entity entity = access.getEntity();
 | 
			
		||||
        if( entity != null )
 | 
			
		||||
        {
 | 
			
		||||
            speaker.setLocation( entity.getEntityWorld(), entity.getCameraPosVec( 1 ) );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        speaker.update();
 | 
			
		||||
        access.setLight( speaker.madeSound( 20 ) ? 0x3320fc : -1 );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,42 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.peripherals;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.peripheral.IPeripheral;
 | 
			
		||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral;
 | 
			
		||||
import net.minecraft.util.math.Vec3d;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
public class PocketSpeakerPeripheral extends SpeakerPeripheral
 | 
			
		||||
{
 | 
			
		||||
    private World world = null;
 | 
			
		||||
    private Vec3d position = Vec3d.ZERO;
 | 
			
		||||
 | 
			
		||||
    void setLocation( World world, Vec3d position )
 | 
			
		||||
    {
 | 
			
		||||
        this.position = position;
 | 
			
		||||
        this.world = world;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public World getWorld()
 | 
			
		||||
    {
 | 
			
		||||
        return world;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Vec3d getPosition()
 | 
			
		||||
    {
 | 
			
		||||
        return world != null ? position : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals( IPeripheral other )
 | 
			
		||||
    {
 | 
			
		||||
        return other instanceof PocketSpeakerPeripheral;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,133 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.pocket.recipes;
 | 
			
		||||
 | 
			
		||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
 | 
			
		||||
import dan200.computercraft.shared.PocketUpgrades;
 | 
			
		||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
 | 
			
		||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
 | 
			
		||||
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
 | 
			
		||||
import net.minecraft.inventory.CraftingInventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.recipe.RecipeSerializer;
 | 
			
		||||
import net.minecraft.recipe.SpecialCraftingRecipe;
 | 
			
		||||
import net.minecraft.recipe.SpecialRecipeSerializer;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
 | 
			
		||||
public final class PocketComputerUpgradeRecipe extends SpecialCraftingRecipe
 | 
			
		||||
{
 | 
			
		||||
    public static final RecipeSerializer<PocketComputerUpgradeRecipe> SERIALIZER = new SpecialRecipeSerializer<>( PocketComputerUpgradeRecipe::new );
 | 
			
		||||
 | 
			
		||||
    private PocketComputerUpgradeRecipe( Identifier identifier )
 | 
			
		||||
    {
 | 
			
		||||
        super( identifier );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack getOutput()
 | 
			
		||||
    {
 | 
			
		||||
        return PocketComputerItemFactory.create( -1, null, -1, ComputerFamily.NORMAL, null );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world )
 | 
			
		||||
    {
 | 
			
		||||
        return !craft( inventory ).isEmpty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack craft( @Nonnull CraftingInventory inventory )
 | 
			
		||||
    {
 | 
			
		||||
        // Scan the grid for a pocket computer
 | 
			
		||||
        ItemStack computer = ItemStack.EMPTY;
 | 
			
		||||
        int computerX = -1;
 | 
			
		||||
        int computerY = -1;
 | 
			
		||||
        computer:
 | 
			
		||||
        for( int y = 0; y < inventory.getHeight(); y++ )
 | 
			
		||||
        {
 | 
			
		||||
            for( int x = 0; x < inventory.getWidth(); x++ )
 | 
			
		||||
            {
 | 
			
		||||
                ItemStack item = inventory.getStack( x + y * inventory.getWidth() );
 | 
			
		||||
                if( !item.isEmpty() && item.getItem() instanceof ItemPocketComputer )
 | 
			
		||||
                {
 | 
			
		||||
                    computer = item;
 | 
			
		||||
                    computerX = x;
 | 
			
		||||
                    computerY = y;
 | 
			
		||||
                    break computer;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( computer.isEmpty() )
 | 
			
		||||
        {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ItemPocketComputer itemComputer = (ItemPocketComputer) computer.getItem();
 | 
			
		||||
        if( ItemPocketComputer.getUpgrade( computer ) != null )
 | 
			
		||||
        {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check for upgrades around the item
 | 
			
		||||
        IPocketUpgrade upgrade = null;
 | 
			
		||||
        for( int y = 0; y < inventory.getHeight(); y++ )
 | 
			
		||||
        {
 | 
			
		||||
            for( int x = 0; x < inventory.getWidth(); x++ )
 | 
			
		||||
            {
 | 
			
		||||
                ItemStack item = inventory.getStack( x + y * inventory.getWidth() );
 | 
			
		||||
                if( x == computerX && y == computerY )
 | 
			
		||||
                {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if( x == computerX && y == computerY - 1 )
 | 
			
		||||
                {
 | 
			
		||||
                    upgrade = PocketUpgrades.get( item );
 | 
			
		||||
                    if( upgrade == null )
 | 
			
		||||
                    {
 | 
			
		||||
                        return ItemStack.EMPTY;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if( !item.isEmpty() )
 | 
			
		||||
                {
 | 
			
		||||
                    return ItemStack.EMPTY;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( upgrade == null )
 | 
			
		||||
        {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Construct the new stack
 | 
			
		||||
        ComputerFamily family = itemComputer.getFamily();
 | 
			
		||||
        int computerID = itemComputer.getComputerID( computer );
 | 
			
		||||
        String label = itemComputer.getLabel( computer );
 | 
			
		||||
        int colour = itemComputer.getColour( computer );
 | 
			
		||||
        return PocketComputerItemFactory.create( computerID, label, colour, family, upgrade );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean fits( int x, int y )
 | 
			
		||||
    {
 | 
			
		||||
        return x >= 2 && y >= 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public RecipeSerializer<?> getSerializer()
 | 
			
		||||
    {
 | 
			
		||||
        return SERIALIZER;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user