Minecraft modding-如何在服务器端使用setBlock?

时间:2013-09-06 21:34:10

标签: java minecraft

如果您在键盘GUI中键入的代码正确,我尝试使用setBlock命令放置键盘的活动(发出红石电源)版本。代码即将展示给你在客户端(单人游戏)方面完美无瑕地工作,但不在服务器(多人游戏)方面。下面是代码:

BlockKeypad'onBlockActivated'代码:

public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9){
this.playerObj = par5EntityPlayer;
this.lastKeypadX = par2;
this.lastKeypadY = par3;
this.lastKeypadZ = par4;

if(par1World instanceof WorldServer){
    this.worldServerObj = par1World;
    TileEntityKeypad TEK = (TileEntityKeypad) par1World.getBlockTileEntity(par2, par3, par4);
    System.out.println(TEK.getKeypadCode() + " | Code from TileEntity");

    this.openCode = TEK.getKeypadCode();
    if(TEK.getKeypadCode() == 0){
        par5EntityPlayer.openGui(mod_SecurityCraft.instance, 1, par1World, par2, par3, par4);
    }else{
        par5EntityPlayer.openGui(mod_SecurityCraft.instance, 0, par1World, par2, par3, par4);
    }

    return true;
}else{
    this.worldObj = par1World;
       //Rest of client code here


    return true;
}           

}

GuiKeypad代码:

private void checkCode(String par1String) {
int code = 0;
try{
    code = Integer.parseInt(par1String);
}catch(Exception e){
    e.printStackTrace();
}

System.out.println(BlockKeypad.openCode + " | GUI");
if(code == BlockKeypad.openCode){           
new ScheduleUpdate(3, BlockKeypad.worldServerObj, BlockKeypad.lastKeypadX,BlockKeypad.lastKeypadY, BlockKeypad.lastKeypadZ, BlockKeypad.openCode, this.keypadInventory);
    BlockKeypad.playerObj.closeScreen();
            }

}

ScheduleUpdate类:

public class ScheduleUpdate{
Timer timer;
private int xCoord;
private int yCoord;
private int zCoord;
private int metadata;
private int passcode;
private TileEntityKeypad TEK;
public ScheduleUpdate(int seconds, World par2World, int par3, int par4, int par5, int par6, TileEntityKeypad keypadInventory){
    timer = new Timer();
    timer.schedule(new RemindTask(), seconds*1000); //TODO 60
    xCoord = par3;
    yCoord = par4;
    zCoord = par5;
    passcode = par6;
    TEK = keypadInventory;
    //BlockKeypad.shouldCheckMeta = false;

    metadata = par2World.getBlockMetadata(par3, par4 , par5);
    System.out.println(metadata + " | metadata");
    par2World.setBlock(par3, par4, par5, mod_SecurityCraft.KeypadActive.blockID, metadata, 3);
    par2World.notifyBlocksOfNeighborChange(par3, par4 , par5, mod_SecurityCraft.KeypadActive.blockID);

}
class RemindTask extends TimerTask{

    public void run(){
        BlockKeypad.worldObj.setBlock(xCoord, yCoord, zCoord, mod_SecurityCraft.Keypad.blockID, metadata, 3);
        BlockKeypad.worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, mod_SecurityCraft.Keypad.blockID);

        ((TileEntityKeypad) BlockKeypad.worldObj.getBlockTileEntity(xCoord, yCoord, zCoord)).setKeypadCode(passcode);


        timer.cancel();
    }
}

}

如果我现在使用此代码,由于某种原因,当我创建一个新的ScheduleUpdate对象(在GuiKeypad代码中)时,它会在BlockKeypad.worldServerObj上给出一个NullPointerException。如果我用BlockKeypad.worldObj(我的客户端World对象)切换它,看起来它放置了块,但是如果我更新新块(右键单击它,在它旁边放置一个块等),它就会消失。所以我猜我必须使用worldServerObj,但是,每当我尝试使用它时,它会抛出一个NullPointerException,即使我在GUI打开之前设置为服务器的World对象。

我向System.out.println()创建了一个项目,这是我在BlockKeypad类中创建的两个世界对象。

当我右键单击它时,它会在控制台(客户端)中打印出来:

net.minecraft.multiplayer.WorldClient()
null

在服务器控制台中:

null
net.minecraft.multiplayer.WorldServer()

任何人都知道什么是错的?我非常感谢任何帮助,因为这是阻止我发布我的mod的多人兼容版本的唯一因素。谢谢!

1 个答案:

答案 0 :(得分:1)

简短的回答是,您已将mod编码为仅限单人游戏,这意味着只有当客户端代码和服务器代码从同一运行时环境执行并且可以轻松传递对象引用时,它才能正常运行价值来回。您的客户端报告WorldServer对象为空的原因是,当连接到专用服务器时,它实际上无法访问任何WorldServer对象(在SSP中,客户端正在运行集成服务器,因此它可以访问它) 。服务器无法访问WorldClient对象的原因也是如此。

基本上,您需要为客户端实现客户端/服务器数据包处理程序,以发送服务器所需的自定义数据,以确定播放器是否输入了正确的键盘输入并采取相应的操作。这是通过在玩家完成输入密钥代码并提交密码后从客户端调度Packet250CustomPayload的实例来完成的。 Packet250CustomPayload由一个Object []组成,它可以包含处理请求所需的任何对象类型。为了您的利益,我希望您使用Minecraft Forge作为mod加载机制,因为这是使您的mod适用于SSP和SMP的最简单方法。

以下是Minecraft中有关数据包处理的教程的链接:http://www.minecraftforge.net/wiki/Packet_Handling

这是Treecapitator源代码的另一个链接(这是我的代码,所以可以随意使用它来学习如何应用数据包处理概念):https://github.com/bspkrs/Treecapitator

此外,Treecapitator数据包处理代码使用我所需的依赖mod bspkrsCore中的一个类,它有助于构造数据包(我无法发布第三个URL,因为我没有信誉点):[mygithubURL] / bspkrsCore / blob / master / SRC / bspkrs / FML / util的/ ForgePacketHelper.java

其他提示:
〜而不是检查World对象是否属于特定对象类型,请使用world.isRemote()。当isRemote()为true时,您应该运行特定于客户端的代码,当它为false时,您应该运行特定于服务器的代码。
〜不要使用单独的线程来修改世界......你应该注册一个新的tick处理程序以避免并发修改异常。