setBlock() блоки исчезают после релогона.

Блоки поставленные программно исчезают после релогона, причём если ставить на такие добавленные блоки свой блок, он опускается ниже и ставится на место того блока, на который я пытался поставить. После релога те блоки, которые я поставил вручную - остаются, а те, которые ставил программно - исчезают. 

Код:
Block tbl=getBlockById(fsr.getMCId(xi-this.X, yi-this.Y, zi-this.Z));
                    
    if(tbl!=null){
        this.lWorld.setBlock(xi, zi, yi,tbl);
    }

Я так понимаю, надо сообщить серверу, что я блоки поставил, но не понимаю как это сделать. Тем более что по setBlock гуглится команда консоли с туториалами, а это, очевидно, не то.
 
2,955
12
Что это вообще за кусок кода с ужасными названиями переменных?
 
Это пример кода, который ставит блоки. 
Изначально с помощью 
Код:
Block tbl=getBlockById(

я получаю блок, потом с помощью

Код:
this.lWorld.setBlock(xi, zi, yi,tbl);

я ставлю блок в мир.

Думаю, название переменных на работоспособность кода не повлияет. 
После такой установки блоки и появляются, но до перелогина.
 
2,955
12
Только не понятно, что это за переменные и вообще откуда ты их взял. Где ты это делаешь?
 
Хм... Не пойму при чём тут переменные. По факту:
Код:
xi, zi, yi - это координаты, аналогичны xi=1, zi=1, yi=64


i -в названии для того чтобы понять, что это переменная цикла. 

Код:
Block tbl=getBlockById() - штатная функция, в которой получается блок по айдишнику. например 
Block tbl=getBlockById(1);



В общем и целом, для одноразового выполнения этот код можно представить как:

Код:
Block myBlock=getBlockById(1);

this.lWorld.setBlock(1, 1, 64,myBlock);


Я думаю так названия переменных не будут смущать.
И всё-таки, есть мысли по тому, в чём проблема или это праздное любопытство?

Я в билдкрафте нашёл такое использование этой процедуры:

Код:
context.world().setBlock(x, y, z, block, meta, 3);

И это 3 меня смущает. А meta я пока не использую.

И да, делаю я это в эклипсе. Или ты другое имел ввиду?
 
Установку блока прописал в блоке мода. Вызываю процедуру содержащую установку блока из класса GUI.

То есть: У меня блок. Из него гуй. В гуе кнопка. По нажатию кнопки вызываю свою процедуру внутри блока и в ней устанавливаю новый блок по координатам.
В блоке же сохраняю в локальную переменную 


Код:
private World lWorld;


и запоминаю для дальнейшего использования координаты текущего блока и локальную переменную мира
Код:
    @Override
    public boolean onBlockActivated(World par1World, int x, int z, int y, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    {
        
        if (!par1World.isRemote)
        {
            return true;
        }
        else
        {
        
            this.lWorld=par1World;
            this.X=x;
            this.Y=y;
            this.Z=z;
            
            par5EntityPlayer.openGui(ExampleMod.instance, 0, par1World, x, y, z);
            
        }
        
        super.onBlockActivated( par1World,  x,  z,  y,  par5EntityPlayer,  par6,  par7,  par8,  par9);
        return true;
    }


Ну и в гуе всё тривиально:
Код:
package com.example.examplemod.block;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;

import cpw.mods.fml.common.Mod;
import buildcraft.BuildCraftBuilders;
import buildcraft.core.network.RPCHandler;
import buildcraft.core.utils.StringUtils;


public class GUIOrangeBlock extends GuiScreen{

    

    private GuiTextField tFX;
    private GuiTextField tFY;
    private GuiTextField tFZ;
    
    private GuiTextField tFName;
    
    private int MAX_NAME_SIZE=120;
    private int MAX_COORD_SIZE=3;
    
    private static final int TEXT_X = 130;
    private static final int TEXT_Y = 62;
    private static final int TEXT_WIDTH = 156;
    private static final int NUM_WIDTH = 30;
    private static final int NUM_X = TEXT_X+TEXT_WIDTH-NUM_WIDTH;
    
    private static final int TEXT_HEIGHT = 12;
    
    private static final int guiLeft=85;
    private static final int guiTop=37;
    
    
    private EntityPlayer lplayer; 
    private OrangeBlock lblock;
    
    private int X,Y,Z,MRub;
    private String zoneName;
    
    public  GUIOrangeBlock(EntityPlayer player, Block block)
    {
        super();

        this.lplayer=player;
        this.lblock=(OrangeBlock)block;
    }
    
    @Override
    public void initGui() {
        super.initGui();

        Keyboard.enableRepeatEvents(true);
    
//        int posX = (this.width - 120) / 2;
//        int posY = (this.height - 80) / 2;
        int btwn =TEXT_HEIGHT+3;
        
        buttonList.add(new GuiButton(0, TEXT_X, TEXT_Y+btwn * 5, TEXT_WIDTH/2-3, 20, "Sale Castle"));
        buttonList.add(new GuiButton(1, TEXT_X + TEXT_WIDTH/2+3, TEXT_Y+btwn * 5, TEXT_WIDTH/2-3, 20, "Pay Castle"));
        
        tFX = new GuiTextField(this.fontRendererObj, NUM_X, TEXT_Y, NUM_WIDTH, TEXT_HEIGHT);

        tFY = new GuiTextField(this.fontRendererObj, NUM_X, TEXT_Y+btwn, NUM_WIDTH, TEXT_HEIGHT);
        tFZ = new GuiTextField(this.fontRendererObj, NUM_X, TEXT_Y+btwn*2, NUM_WIDTH, TEXT_HEIGHT);
        tFName = new GuiTextField(this.fontRendererObj, TEXT_X, TEXT_Y+btwn*4, TEXT_WIDTH, TEXT_HEIGHT);
        
        
        
        tFX.setMaxStringLength(MAX_COORD_SIZE);
        tFY.setMaxStringLength(MAX_COORD_SIZE);
        tFZ.setMaxStringLength(MAX_COORD_SIZE);
        tFName.setMaxStringLength(MAX_NAME_SIZE);
        
        tFName.setText("MySuperCastle");
        tFX.setText("16");
        tFY.setText("16");
        tFZ.setText("16");
        
        
        
        tFX.setFocused(true);
        
    }
    
    
    @Override
    public void drawScreen(int x, int y, float f)
    {
        this.drawDefaultBackground();
    
        

        
        String title = StringUtils.localize("tile.architectBlock.name");
        fontRendererObj.drawString(title, 50, 6, 0x404040);


        tFX.drawTextBox();
        tFY.drawTextBox();
        tFZ.drawTextBox();
        tFName.drawTextBox();
        
        
        super.drawScreen(x, y, f);
    }    
    
    @Override
    protected void mouseClicked(int x, int y, int btn) {
        

        tFX.mouseClicked(x , y , btn);
        tFY.mouseClicked(x , y , btn);
        tFZ.mouseClicked(x , y , btn);
        tFName.mouseClicked(x , y , btn);

        
        
        
        super.mouseClicked(x, y, btn);
    }
    
    @Override
    public void actionPerformed(GuiButton button)
    {
        switch(button.id)
        {
        case 0: 
            lblock.dump(tFX.getText(),
                        tFY.getText(),
                        tFZ.getText(),
                        tFName.getText());
            
            
        break;
        case 1: 
            try{
            lblock.reupdump(tFName.getText());            
            }catch (Exception e) {
                // TODO: handle exception
                
            }
            
        break;
        default:
            
            
        }
    }
    

    @Override
    protected void keyTyped(char c, int i) {
         if(i==1){
                Minecraft.getMinecraft().displayGuiScreen(null);
                return;
            }
        
        if (tFX.isFocused()) {
            if (c == 13 || c == 27) {
                tFX.setFocused(false);
            } else{
                super.keyTyped(c, i);
                tFX.textboxKeyTyped(c, i);
                //RPCHandler.rpcServer(architect, "handleClientSetName", tF.getText());
            }
        } else         if (tFY.isFocused()) {
            if (c == 13 || c == 27) {
                tFY.setFocused(false);
            } else{
                super.keyTyped(c, i);
                tFY.textboxKeyTyped(c, i);
                //RPCHandler.rpcServer(architect, "handleClientSetName", tF.getText());
            }
        } else         if (tFZ.isFocused()) {
            if (c == 13 || c == 27) {
                tFZ.setFocused(false);
            } else{
                super.keyTyped(c, i);
                tFZ.textboxKeyTyped(c, i);
                //RPCHandler.rpcServer(architect, "handleClientSetName", tF.getText());
            }
        } else         if (tFName.isFocused()) {
            if (c == 13 || c == 27) {
                tFName.setFocused(false);
            } else{
                super.keyTyped(c, i);
                tFName.textboxKeyTyped(c, i);
                //RPCHandler.rpcServer(architect, "handleClientSetName", tF.getText());
            }
        } 
//        else {
//            if (i == 1 || i == this.mc.gameSettings.keyBindInventory.getKeyCode())
//            {
//                //this.mc.thePlayer.closeScreen();
//                Minecraft.getMinecraft().displayGuiScreen(null);
//            }
//        }
        
        super.keyTyped(c, i);
        
    }
    @Override
    public void updateScreen()
    {
        super.updateScreen();
        tFX.updateCursorCounter();
        tFY.updateCursorCounter();
        tFZ.updateCursorCounter();
        tFName.updateCursorCounter();
    }
    
    @Override
    public void onGuiClosed() {
        Keyboard.enableRepeatEvents(false);
    }
}


и тут lblock.dump и lblock.reupdump(
вызывают тот самый код установки блока.


Часть кода слямзил с билдкрафта. Но, надеюсь, они не обидятся.
 
1,990
18
105
Яснопонятно.
Гуи на клиенте, соответственно ты и мир клиентский берешь. Сервер о твоих действиях нифига не знает.
Шли пакет, либо эмулируй постановку блока игроком, чтобы сработало обычное onBlockPlacedBy и ванилька всё отправила сама.
 
Oldestkon написал(а):
...
Шли пакет, либо эмулируй постановку блока игроком...

Во! Я чувствовал, что где-то тут не то. 
Можно чуть подробнее? Пакет если слать, я же его и на сервере должен обработать? В билдкрафте я недогнал зачем они пакеты слали. 
Или как эмулировать постановку блока игроком? Кстати, это мне, наверное, больше подошло бы. Но про установку блока только сетблок нашёл или сетблоксметадатой.
 
1,990
18
105
Лучше слать пакет. Эмулировать постановку блока игроком можно только в маленьком радиусе вокруг игрока. Тут я немного промазал.
Ничего сложного нет. В главный класс Добавляешь статический экземпляр SimpleNetworkWrapper.
Вообще вот: http://www.minecraftforge.net/forum/index.php?topic=20135.0

Запомни одну истину: клиенту верить нельзя. Всегда проверяй данные, сверяй клиентские данные с серверными и отменяй операцию чуть что не так. Игрок хочет поставить блок? Ну, пусть сервер проверит, есть ли у игрока этот блок.
Либо если есть тайл с инвентарем, и, логично, контейнером - на сервере в обработчике пакета достаешь через второй аргумент (context) игрока (методы смотри там), и проверяешь у него содержимое openContainer на наличие нужного предмета.
Все изменения инвентаря тоже на сервере делай.
Слоты синхронизируются сами, пакеты в основном IDшниками слотов обмениваются, в те дебри лезть совсем не обязательно.
 
У меня мод пока, практически креативный, так что пока я полностью доверяю клиенту. 

Спасибо большое за ответ, но непонятно, что всё-таки делать с этим пакетом на сервере. Вообще, есть какая-то ссылка на описание клиент-серверного деления? Что и как запускается на сервере, и что и как на клиенте. Я заметил, пока проектировал ГУЙ что есть серверный ГУЙ - который представляет из себя GuiInventory  и клиентский  GuiScreen  
В моём случае, как я понимаю, надо поставить блок как сейчас, потом отправить сообщение на сервер с координатами и данными блока, включая, возможно большой кусок метадаты и на сервере это сообщение парсить, и вызывать тот же код но для серверной переменной мира?

Серверную переменную мира, получается, надо сохранять при клике на блок, но в классе мода и потом там же ставить блок(сообщение в класс мода приходят, я так понял)? Пока не трогаю проверки клиента на наличие блока и права установки его туда.

В общем, прошу, господа, подскажите подробнее принцип клиент-серверного разделения логики работы в Майнкрафте... Все ссылки приветствуются!
 
1,990
18
105
На сервере ГУИ нет в помине. Следовательно, GuiInventory, тоже.
На сервере нет вообще ничего, что может давать визуальное восприятие.
Попозже отвечу развернуто.
 
Agravaine написал(а):

Спасибо, полезная информация! Очень пригодится!

Oldestkon написал(а):
На сервере ГУИ нет в помине. Следовательно, GuiInventory, тоже.
На сервере нет вообще ничего, что может давать визуальное восприятие.
Попозже отвечу развернуто.

Тем не менее в классе CommonProxy.java есть
Код:
    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player, World world,
            int x, int y, int z) {
        return null;
    }

    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player, World world,
            int x, int y, int z) {
        return null;
    }

Вот эти серверные гуи элементы, которые, видимо как раз копия всех инвентарей, я и имел ввиду под серверным гуи.

Жду обещанного развёрнутого описания, потому как просветления ещё, к сожалению, не достиг...
 
Понимаю что прошло пять лет,но все же,ты исправил проблему? И как? Просто то же самое не могу решить
 
Это всем уже давно известно что на сервере надо,но конкретно как никто не показывает
 
Сверху