首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的世界修改-如何在服务器端使用setBlock?

我的世界修改-如何在服务器端使用setBlock?
EN

Stack Overflow用户
提问于 2013-09-07 05:34:10
回答 1查看 2.9K关注 0票数 0

如果您在键盘图形用户界面中输入的代码是正确的,我正在尝试使用setBlock命令来放置我的键盘的活动(发出红石电源)版本。我将要向您展示的代码可以完美地在客户端(单人播放器)端运行,但不能在服务器端(多玩家端)运行。代码如下:

BlockKeypad 'onBlockActivated‘代码:

代码语言:javascript
复制
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代码:

代码语言:javascript
复制
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类:

代码语言:javascript
复制
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,即使我在打开图形用户界面之前就将其设置为服务器的World对象。

我在BlockKeypad类中创建了两个world对象,并向System.out.println()添加了一个item。

当我右键单击它时,它会在控制台(客户端)中打印以下内容:

代码语言:javascript
复制
net.minecraft.multiplayer.WorldClient()
null

在服务器控制台中:

代码语言:javascript
复制
null
net.minecraft.multiplayer.WorldServer()

有人知道哪里出问题了吗?我非常感谢任何人的帮助,因为这是唯一阻止我发布我的mod的多人兼容版本的东西。谢谢!

EN

回答 1

Stack Overflow用户

发布于 2013-09-26 00:12:30

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

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

这是一个关于在“我的世界”中处理数据包的教程的链接:http://www.minecraftforge.net/wiki/Packet_Handling

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

此外,Treecapitator包处理代码使用了我所需的依赖关系mod中的一个类来帮助构造包(我不能发布第三个bspkrsCore,因为我没有名誉点):mygithubURL/bspkrsCore/blob/master/src/bspkrs/fml/util/ForgePacketHelper.java

其他提示:

~不检查世界对象是否属于特定的对象类型,而是使用world.isRemote()。当isRemote()为true时,您应该运行特定于客户端的代码;当为false时,您应该运行特定于服务器的代码。

~不要使用单独的线程来修改世界...相反,您应该注册一个新的tick处理程序,以避免并发修改异常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18666908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档