This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
tattyseal's profile picture

Peripheral works even if it is not wrapped

Started by tattyseal, 12 July 2014 - 11:47 AM
tattyseal #1
Posted 12 July 2014 - 01:47 PM
Hey guys, I am making a peripheral for ComputerCraft, that queues an event when it is right clicked, but it works even if it is not been wrapped with peripheral.wrap

Block
Spoiler

package com.tattyseal.pp.block;

import com.tattyseal.pp.config.Config;
import com.tattyseal.pp.tileentity.TileEntityPlayerDetector;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChatMessageComponent;
import net.minecraft.util.Icon;
import net.minecraft.world.World;

/**
 * * @package com.tattyseal.pp.block
 * * @author tattyseal
 * *
 */
public class BlockPlayerDetector extends Block implements ITileEntityProvider
{
    public Icon sideIcon;
    public Icon baseIcon;

    public BlockPlayerDetector()
    {
        super(Config.playerDetector, Material.iron);
        setUnlocalizedName("pp.playerDetector");
        setCreativeTab(CreativeTabs.tabBlock);
    }

    @Override
    public Icon getIcon(int side, int meta)
    {
        switch(side)
        {
            case 0: return baseIcon;
            case 1: return baseIcon;
            default: return sideIcon;
        }
    }

    @Override
    public void registerIcons(IconRegister iconRegister)
    {
        sideIcon = iconRegister.registerIcon("pp:playerDetector");
        baseIcon = iconRegister.registerIcon("pp:base");
    }

    @Override
    public TileEntity createNewTileEntity(World world)
    {
        return new TileEntityPlayerDetector();
    }

    @Override
    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int i, float j, float k, float l)
    {
        if(world.isRemote) return false;

        TileEntity te = world.getBlockTileEntity(x, y, z);

        if(te instanceof TileEntityPlayerDetector)
        {
            TileEntityPlayerDetector detector = (TileEntityPlayerDetector) te;

            if(detector.sendPlayerToComputer(world, player))
            {
                return true;
            }
            else
            {
                ChatMessageComponent cmc = new ChatMessageComponent();

                cmc.addText("This peripheral is not connected to a computer!");

                player.sendChatToPlayer(cmc);

                return false;
            }
        }

        return false;
    }
}


TileEntity
Spoiler

package com.tattyseal.pp.tileentity;

import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

/**
 * * @package com.tattyseal.pp.tileentity
 * * @author tattyseal
 * *
 */
public class TileEntityPlayerDetector extends TileEntity implements IPeripheral
{
    public IComputerAccess computerAccess;

    @Override
    public String getType()
    {
        return "playerDetector";
    }

    @Override
    public String[] getMethodNames()
    {
        return new String[0];
    }

    @Override
    public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception
    {
        return new Object[0];
    }

    @Override
    public void attach(IComputerAccess computer)
    {
        computerAccess = computer;
    }

    @Override
    public void detach(IComputerAccess computer)
    {
        computerAccess = null;
    }

    @Override
    public boolean equals(IPeripheral other)
    {
        return false;
    }

    public boolean sendPlayerToComputer(World world, EntityPlayer player)
    {
        if(computerAccess == null) return false;

        String item = player.getHeldItem() == null ? "" : player.getHeldItem().getDisplayName().replace(" ", "");

        computerAccess.queueEvent("player", new String[] {player.getCommandSenderName(), item});

        return true;
    }
}


Peripheral Provider
Spoiler

package com.tattyseal.pp.cc;

import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import net.minecraft.world.World;

/**
 * * @package com.tattyseal.pp.cc
 * * @author tattyseal
 * *
 */
public class Provider implements IPeripheralProvider
{

    @Override
    public IPeripheral getPeripheral(World world, int x, int y, int z, int side)
    {
        if(world.getBlockTileEntity(x, y, z) instanceof IPeripheral)
        {
            return (IPeripheral) world.getBlockTileEntity(x, y, z);
        }

        return null;
    }
}


Thanks :)/>
theoriginalbit #2
Posted 12 July 2014 - 02:01 PM
Yes, that is how events work. Peripheral wrapping is simply a process of invoking methods on peripherals easier than having to do a peripheral.call each time.

If you do wish to only have 'registered' computers provided the event, I would probably suggest forcing the developer/user to invoke a method, lets say something like eventSubscribe and then keeping a copy of the IComputerAccess from the callMethod method, as this is the computer that the method has been invoked from. Obviously only retain this computer if it isn't already in the list though, or else you'll start getting duplicate events if they invoke your register method multiple times. I'd probably suggest providing a unregister method too. Then whenever you wish to queue an event, you'd loop through this list of 'registered' computers and queue the event to them.

Btw it should be noted that multiple computers can be attached to your peripheral, so you should retain a list of the computers, not just retain the last attached computer like you're currently doing.

// A list of all computers attached to this peripheral
protected ArrayList<IComputerAccess> computers = new ArrayList<IComputerAccess>();

@Override
public void attach(IComputerAccess computer) {
  computers.add(computer);
}

@Override
public void detach(IComputerAccess computer) {
  computers.remove(computer);
}

// a method for queueing events to all attached computers

protected void computerQueueEvent(String event, Object... args) {
  for (IComputerAccess computer : computers) {
	computer.queueEvent(event, args);
  }
}
Edited on 12 July 2014 - 12:02 PM
tattyseal #3
Posted 12 July 2014 - 03:55 PM
Yes, that is how events work. Peripheral wrapping is simply a process of invoking methods on peripherals easier than having to do a peripheral.call each time.

If you do wish to only have 'registered' computers provided the event, I would probably suggest forcing the developer/user to invoke a method, lets say something like eventSubscribe and then keeping a copy of the IComputerAccess from the callMethod method, as this is the computer that the method has been invoked from. Obviously only retain this computer if it isn't already in the list though, or else you'll start getting duplicate events if they invoke your register method multiple times. I'd probably suggest providing a unregister method too. Then whenever you wish to queue an event, you'd loop through this list of 'registered' computers and queue the event to them.

Btw it should be noted that multiple computers can be attached to your peripheral, so you should retain a list of the computers, not just retain the last attached computer like you're currently doing.

// A list of all computers attached to this peripheral
protected ArrayList<IComputerAccess> computers = new ArrayList<IComputerAccess>();

@Override
public void attach(IComputerAccess computer) {
  computers.add(computer);
}

@Override
public void detach(IComputerAccess computer) {
  computers.remove(computer);
}

// a method for queueing events to all attached computers

protected void computerQueueEvent(String event, Object... args) {
  for (IComputerAccess computer : computers) {
	computer.queueEvent(event, args);
  }
}

Thanks, I think that is the best way too now you mention it! Thanks a bunch! :)/>