Jump to content

[Solved but weird] TileEntity Client and Server doing unsynchronized stuff


Xerus

Recommended Posts

Problem 1 is solved: In short, i needed to send Server information to the client while i had an Container open - A quick look into ContainerFurnace showed the solution, using detectAndSendChanges()

 

I have a tileentity that uses fuel to plant plants. how much fuel it has in it is displayed in a gui, that is obviously a client thing. update() gets called on both client and server, but since it only uses fuel and plants if there is space, sometimes the client uses fuel(I would conclude when it is called first) and the server too and sometimes only the server uses fuel. this then makes the gui display the wrong, client-side information.

 

 

After implementing this, a new problem occured. Go 2 posts down to look at it.

 

Ok I now solved the issue by simply introducing a new value for the gui and only changing it if the values from the tileentity for lastfuel and fuel are different:

    int lastfuel;
    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
    	if(te.getField(1)!=te.getField(0))
    		lastfuel=te.getField(1);
        ...
    }

still wondering how the problem occured tho

Link to comment
Share on other sites

Ok well now I implemented this into my container:

 

private int fuel;
private int lastfuelvalue;
    public void detectAndSendChanges(){
        super.detectAndSendChanges();
        for (int i = 0; i<this.listeners.size(); ++i) {
            IContainerListener listener = (IContainerListener)this.listeners.get(i);
            if (this.fuel!=this.te.getField(0)){
            	listener.sendProgressBarUpdate(this, 0, this.te.getField(0));
            }
            if (this.lastfuelvalue!=this.te.getField(1)){
            	listener.sendProgressBarUpdate(this, 1, this.te.getField(1));
            }
        }
        this.fuel=this.te.getField(0);
        this.lastfuelvalue=this.te.getField(1);
    }
    @SideOnly(Side.CLIENT)
    public void updateProgressBar(int id, int data){
        this.te.setField(id, data);
    }

 

 

the really weird thing is, when the variable in field 0(fuel) changes and the gui is open, it kinda sets lastfuelvalue to fuel(what I dont want), but when i reopen the gui the packet is send again and it gets displayed correct. maybe i didnt explain it good but I just dont understand what mc is doing here...

lemme show pictures:

2016-08-14.png

normal gui(fuel value in top left only for debug)

2016-08-141.png

after it used fuel while keeping the gui open

2016-08-142.png

after reopening the gui

 

just want to remind: this ONLY happened after i added all this listening stuff!

 

Link to comment
Share on other sites

You also need to add

public void addListener(IContainerListener listener) {
     super.addListeners(listener);
     listener.sendAllWindowProperties(this, tileEntity);
}

to your containers class.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

get/setfield:

 

	
@Override
public int getField(int id) {
	switch (id){
	case 0: return this.fuel;
	case 1: return this.lastfuel;
	}
	return 0;
}
@Override
public void setField(int id, int value) {
	switch (id){
	case 0: fuel=value;
	case 1: lastfuel=value;
	}
}

 

@Animefan I already had it but it changed nothing. Do you even know what i does?

Link to comment
Share on other sites

get/setfield:

@Animefan I already had it but it changed nothing. Do you even know what i does?

I believe it sends all of the properties aka the fields from server to client.

Did you return 2 on getFieldCount?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

it is actually this but i thought it is unnecessary:

 

@Override
public int getField(int id) {
	switch (id){
	case 0: return this.fuel;
	case 1: return this.lastfuel;
	case 2: return this.yoffset;
	case 3: return this.actualslots;
	}
	return 0;
}
@Override
public void setField(int id, int value) {
	switch (id){
	case 0: fuel=value;
	case 1: lastfuel=value;
	case 2: yoffset=value;
	}
}

@Override
public int getFieldCount() {
	return 4;
}

 

Link to comment
Share on other sites

Always post all of the code even if you think it unnecessary. Was that all of the code in your container?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

apart from the constructor, yes

if you want it:

 

private IInventory te;

    public FarmerContainer(IInventory playerInv, IInventory te) {
        this.te = te;
        //Farmer-Inventar
        this.addSlotToContainer(new CustomSlot(te, 0, 26, 45));
        int xslots=te.getField(te.getFieldCount()-1);
        for (int y = 0; y < 2; ++y) {
            for (int x = 0; x < xslots; ++x) {
                this.addSlotToContainer(new CustomSlot(te, x + y * xslots + 1, 62 + x * 18, 45 - y * 21));
            }
        }
        //Player-Inventar
        for (int y = 0; y < 3; ++y) {
            for (int x = 0; x < 9; ++x) {
                this.addSlotToContainer(new Slot(playerInv, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
            }
        }
        for (int x = 0; x < 9; ++x) {
            this.addSlotToContainer(new Slot(playerInv, x, 8 + x * 18, 142));
        }
    }

 

nothing fancy

Link to comment
Share on other sites

Well you definitely could, but using the in place system is easier. And I assume it would be more internet intensive. Give me a minute to look at the code...

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Here you go:

public class FarmerTE extends TEInventory implements ITickable,ISidedInventory {
    
int fuel;
    int lastfuel;
    int yoffset;
    private static int rowslots=5;

    public FarmerTE() {
        super("farmer",rowslots*2+1,new String[]{"fuel","lastfuel","yoffset"});
        fuel=0;
        lastfuel=1;
        yoffset=-1;
    }

private int delay=2;
@Override
    public void update(){
	if(worldObj.isRemote)
		return;
	if(delay>0){
		delay--;
		return;
	}
	delay=5;
	BlockPos position=nextpos();
	Block b=util.blockat(worldObj,position);
	if(b!=null){
		// entferne hohes Gras
		if(util.blockat(worldObj, position.up()).equals(Blocks.TALLGRASS)) worldObj.setBlockState(position.up(),Blocks.AIR.getDefaultState());
		// erde zu farmland
		if((b.equals(Blocks.DIRT)||b.equals(Blocks.GRASS))&&util.blockat(worldObj, position.up()).equals(Blocks.AIR)&&useFuel()){
			worldObj.playSound(null, position, SoundEvents.ITEM_HOE_TILL, SoundCategory.BLOCKS, 1.0F, 1.0F);
			if(!worldObj.isRemote) worldObj.setBlockState(position, Blocks.FARMLAND.getDefaultState(), 11);
		}
		// pflanzen/ernten
		Block s=util.blockat(worldObj,position.up());
		if(s.equals(Blocks.AIR)){
			plant(position);
		} else if(s instanceof BlockCrops){
			if(((BlockCrops)s).isMaxAge(worldObj.getBlockState(position.up()))&&useFuel()) harvest(position,s);
		} else if(s instanceof BlockNetherWart){
			if(worldObj.getBlockState(position.up()).getValue(BlockNetherWart.AGE).intValue()>=3&&useFuel()) harvest(position,s);
		}
	}
    }

private void plant(BlockPos position){
	for(int slot=1;slot<rowslots+1;slot++){
		ItemStack stack=this.getStackInSlot(slot);
		if(stack!=null&&isplantable(stack)){
			IPlantable item=(IPlantable)stack.getItem();		if(util.blockat(worldObj,position).canSustainPlant(worldObj.getBlockState(position),worldObj,position,EnumFacing.UP,item)&&useFuel()){
			    worldObj.setBlockState(position.up(),item.getPlant(null, null));
		    	decrStackSize(slot,1);
		    	return;
			}
		}
	}
}

private void harvest(BlockPos position,Block plant){
	java.util.List<ItemStack> items=plant.getDrops(worldObj, position.up(), worldObj.getBlockState(position.up()), 0);
        for(ItemStack stack : items){
        	int start=rowslots+1;
        	if(isplantable(stack))
        		start=1;
        	for(int slot=start;slot<getSizeInventory();slot++){
        		ItemStack content=getStackInSlot(slot);
        		if(content==null){
        			setInventorySlotContents(slot,stack);
        			break;
        		} else if(content.getItem().equals(stack.getItem())){
        			if(content.stackSize+stack.stackSize<=64){
        				content.stackSize+=stack.stackSize;
        				setInventorySlotContents(slot,content);
        				break;
        			} else {
        				stack.stackSize-=64-content.stackSize;
        				content.stackSize=64;
        				setInventorySlotContents(slot,content);
        			}
        		}
        	}
        }
    	worldObj.setBlockToAir(position.up());
    	plant(position);
}

private boolean isplantable(ItemStack stack){
	return stack.getItem() instanceof IPlantable;
}

private boolean useFuel(){
	int fuelPerOperation=50;
	if(fuel<fuelPerOperation){
		if(getStackInSlot(0)!=null&&TileEntityFurnace.isItemFuel(getStackInSlot(0))){
			lastfuel=TileEntityFurnace.getItemBurnTime(getStackInSlot(0));
			fuel+=lastfuel;
			decrStackSize(0,1);
		}
	}
	if(fuel>=fuelPerOperation){
		fuel-=fuelPerOperation;
		return true;
	}
	return false;
}

private int[][] get=new int[][]{{-1,-1,-1,0,1,1,1,0},{-1,0,1,1,1,0,-1,-1}};
private int currentblock=0;
private BlockPos nextpos(){
	if(currentblock==7) currentblock=0;
	else currentblock++;
	return pos.add(get[0][currentblock],0-yoffset,get[1][currentblock]);
}

@Override
public boolean isItemValidForSlot(int index, ItemStack stack) {
	if(index==0&&TileEntityFurnace.isItemFuel(stack))
		return true;
	if(index>0&&index<rowslots+1&&isplantable(stack))
		return true;
	return false;
}

@Override
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction) {
	return isItemValidForSlot(index, stack);
}
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) {
	if(index>rowslots)
		return true;
	return false;
}

@Override
public int[] getSlotsForFace(EnumFacing side) {
	return new int[]{0,1,2,3,4,5,6,7,8,9,10};
}

@Override
public int getField(int id) {
	switch (id){
	case 0: return this.fuel;
	case 1: return this.lastfuel;
	case 2: return this.yoffset;
	case 3: return this.rowslots;
	}
	throw new RuntimeException("field "+id+" not found");
}
@Override
public void setField(int id, int value) {
	switch (id){
	case 0: fuel=value;
	case 1: lastfuel=value;
	case 2: yoffset=value;
	}
}

@Override
public int getFieldCount() {
	return 4;
}

}

Link to comment
Share on other sites

I'm not sure if I understand the current problem, but is it that the current fuel can be greater than lastFuel? If so the problem is

 

			lastfuel=TileEntityFurnace.getItemBurnTime(getStackInSlot(0));
			fuel+=lastfuel;

 

If not please explain it to me.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

and it cant be the problem since update() only performs on server side since I check for worldObj.isRemote

Well if it only updates server side then we send the data to the client...The client has the same data.

 

Well could you explain the problem.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

yes i am

just for completeness my gui class:

public class FarmerGui extends BaseGui {

    public FarmerGui(IInventory playerInv, TEInventory te) {
    	super(new FarmerContainer(playerInv, te), playerInv, te);
    }

    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        drawBackgroundImage("farmer");
        // fuel blueprint
    if(te.getStackInSlot(0)==null)
    	this.drawRect(26, 45, 176, 0, 16, 16);
    // seeds blueprint
        for(int i=1;i-1<te.getField(te.getFieldCount()-1);i++)
        	if(te.getStackInSlot(i)==null)
        		this.drawRect(44+18*i, 45, 176, 16, 16, 16);
        // progress bar
        int progress=te.getField(0)>0?12-(te.getField(0)*12/te.getField(1)):14;
        this.drawRect(26, 28+progress, 176, 32+progress, 14, 14-progress);
    }
    
    @Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
    	super.drawGuiContainerForegroundLayer(mouseX, mouseY);
    	// temporary debug output
    	drawString("Fuel: "+te.getField(0)+"/"+te.getField(1), 2, 2);
    }
    
}

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Niigata大女儿房验证ºBCGAME55·COM℡ Niigata大女儿房开放聊天骑马 Niigata大女儿房链接软式网球大女儿房地址水球大女儿房亚东[本社咨询的Tele@JBOX7] [Niigata大女儿房视频 硬地滚球大女儿房广告 Free Style大女儿房Kakao Talk 橄榄球场开放聊天[总经销的Kakao Talk JBOX7] NiGATA 大草莓同好高点] 拳击视频 [赌场总公司] NIGAGATA 大女儿房 度假村 奥运会 NIGAGATA 大女儿房社区骑马大女儿房推荐广告 [体育总公司] NIGAGATA 大女儿房 Telegram 骑马 NIGAGATA 大女儿房的故事 功夫 大女儿房 招聘广告 Alpine 大女儿房的地图[TOTO总公司咨询] NIGAGATA 大女儿房总经销摔跤 NIGAGATA 大闺房系统跳高 视频 跳远 高尔夫 Twitter [TO总销购买] NIGAGOTA TANGETA GO TAN GO TAN GO TEA 羽毛球大女儿房LING大女儿房Instagram[BAKARA总经销] NIGATA大女儿房聚会信息 PLING NIGATA大女儿房链接滑雪大女儿房视频软网球大女儿房验证[赛马总经销] NIGATA大女儿房最新地址 Alpine NIGAGATA大女儿房链接藤球馆营业所招集 拳击 大草莓屋链接[BCGAME BC游戏总经销咨询] 设置通知 推荐订阅点赞
    • ヨーロッパカジノ遊び場↙BCGAME33·COM□ベラルーシのカジノ方法ヨーロッパ北欧カジノ中継[本社お問い合わせテレJBOX7]ヨーロッパカジノ♧▥ツアーエルサルバドルカジノ旅行ヨーロッパ西アフリカヨーロッパカジノコミュニティ[総販お問い合わせカカオトークJBOX7]ヨーロッパカジノ↕♠キャッシュゲームジブチカジノ検証ヨーロッパボリビアヨーロッパカジノ業者[各種オフィコミュニティ制作]欧州カジノ† サイトケニア カジノ接続 欧州アフリカ欧州カジノ接続[マーケティングお問い合わせ]欧州カジノ@放送 ボリビア カジノサイト 欧州 欧州 カジノサイト 欧州 カジノサイト 欧州 カジブチノサイト セルビア競技場] パラオカジノ旅行ヨーロッパカナダヨーロッパカジノツアー[トト本社お問い合わせ]ヨーロッパカジノ☎♨京畿アイランドカジノおすすめヨーロッパキプロスヨーロッパカジノおすすめ[トト総販購入]ヨーロッパカジノ☏↓接続アゼルバイジャンカジノツアーヨーロッパバルバドスヨーロッパカジノホールダンバ[カジノ総販]欧州カジノ#■賭博場ニジェールカジノゲーム場欧州アンドラ 欧州カジノゲーム[ヤマト本社]欧州カジノ↔@映像ガボン カジノホールダンバ 欧州バーデンバーデン 欧州 カジノ映像[バカラ総販] º㏘コミュニティスリナムアジア カジノポーカー大会 欧州東南アジア カジノンホールメニスタンバ おすすめ購読、いいですね
    • 横滨SPA链接♤BCGAME55·COM↙横滨SPA聚会信息地板运动横滨SPA故事按摩SPA地址快速SPA验证[本社咨询的Tele@JBOX7]横滨SPA地图跳高横滨SPA视频连接水上运动SPA社区[总经销的Kakao Talk JBOX7]横滨Spa Telegram 踢拳头横滨Youtube拳击Spa系统标枪机Instagram[各种官方网站制作]KOko Kakao Talk 机械马术spa SPA视频连接水上运动spa Spagram 诱导拳击运动视频 电子竞技横滨spa旅行冰球spa地图乒乓球spa巡回赛[体育总公司]横滨spa登录壁球横滨spa招聘广告跳马spa网站拳击spa最新地址[TOTO总公司咨询]横滨spa社区软网球横滨SPA新地址真实SPA登录[TOTO总经销购买]横滨pas验证长曲棍球横滨SPA认证跳马SPA公开聊天游泳SPA视频[赌场总经销]横滨SPA总经销网SPA网站推荐的YOSPA位置 短视频[KO] 做SPA的地方短道速滑SPA视频手球SPA同好会[赛马总经销]横滨SPA亚东滚球横滨SPA连接掷铅球SPA地址美式足球SPA Youtube[BCGAME BC游戏总经销咨询]通知设置推荐 订阅点赞
    • 私設ブラックジャック遊び場=BCGAME33·COM▦ヨルダンブラックジャック映像私設英国ブラックジャックツアー[本社お問い合わせテレJBOX7]私設ブラックジャック▒YouTubeアンティークガバーブーダブラックジャック募集私設ギニア私設ブラックジャック賭博場[総販お問い合わせカカオトークJBOX7]私設ブラックジャック▤️コミュニティアルバニアブラックジャックグループトーク私設フィジー私設ブラッグリーグ[各種オフィコミュニティ制作]社説黒ザック♪▨業者アラブ首長国連邦の黒ザックキャッシュゲーム社説チュニジア社説黒ザック映像[マーケティングお問い合わせ]社説黒ザック↘↗カジノパブ 韓国ブラックジャック動画私設マリ私設ブラックジャックホールダンパブ[ト本社お問い合わせ]私設ブラックジャック▲▨業者ルクセンブルクブラックジャックサイト私設ギリシャ私設ブラックジャック業者[ト総販購入]私設ブラックジャック↔§ホールダンバジョージアブラックジャックカジノパブ私設セネガル私設ブラックジャックコミュニティ[カジノ総販]社説ブラックジャッキ▲▼遊び場コモロ ブラックジャッキキャッシュゲーム社説北マケドニア社説ブラックジャッキグループチャット[大和本社]社説 ブラックジャッキ™¶ クープーンベラジオカジノ ブラックジャッキ [バサミコ] 総販のお問い合わせ]お知らせ設定おすすめ購読いいですね
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.