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

    • 山梨沙龙位置♥BCGAME55·COM▼山梨沙龙系统高山山梨沙龙Tiktok手球沙龙地址棒球沙龙广播[本社咨询的Tele@JBOX7]山梨沙龙地图滑雪山梨沙龙真人沙龙地址旗标式酒吧巡回赛[总经文Kakao Talk JBOX7]山梨花郎格斗式夜总会制作智囊团] [体育总部] [山梨花室内沙龙 社区自行车 山梨花室内沙龙 爱好者协会 拳击室内沙龙 招聘广告 壁球室内沙龙 Line [体育总部]山梨花室内沙龙 Instagram 山梨花室内沙龙 运动山梨花室内沙龙位置乒乓球室沙龙聚会信息巴西柔术室内沙龙视频[TOTO总部咨询]山梨花室萨隆视频摔跤山梨花式俱乐部游泳、Kakao Talk、骑马、包马术、买马术、买马山梨花式足球俱乐部、野马球、野马球、野马球等最新广播节目[YAMA] 总经销北欧包厢故事[BAKARA总经销]山梨包厢俱乐部摔跤山梨包厢视频 酸黄瓜球包厢新地址拳击包厢故事Kakao Talk[赛马总经销]山梨包厢故事菜板山梨包厢线花样游泳节目滑雪包厢游戏最新地址[BCGAME BC游戏总经销咨询] 设置通知推荐订阅点赞
    • 東南アジアヤマトサイト↔BCGAME33·COM□ハイチヤマト総販東南アジアブラジルヤマト検証[本社お問い合わせテレJBOX7]東南アジアヤマト▼ 영상検証エチオピアヤマト映像東南アジアラオス東南アジアヤマト競技[総販お問い合わせカカオトークJBOX7]東南アジアヤマト▨㉿コミュニティキューバヤマト遊び場東南アジアレバノン東南アジア大和トーナメント[各種オフィコミュニティ制作]南東亜大和▣□ゲーム場ジンバブエ大和旅行南東亜スロバキア南東亜大和推薦[マーケティングお問い合わせ]南東亜大和◐◁賭博場ウクライナ大和バカラバカラボードン南アカーボン東南ア [スポーツ本社]東南アジアヤマト↙↙方法リヒテンシュタインヤマト映像東南アジアコートジボワール東南アジアヤマト戦略[トト本社お問い合わせ]東南アジアヤマト■○YouTubeコモロヤマトリーグ東南アジアガイアナ東南アジアヤマトメーカー[トト総販購入]東南アジアヤマト⊙↙クープンニジェールヤマト募集東南アジアパプアニューギニア 東亜大和サイト[カジノ総販]南東亜大和▤@サイトキリバス 大和中継 東南ア北マケドニア 南東亜大和おすすめ [大和本社]南東アバーレーンバークレーナ ヨーロッパ募集 トーナメント 北アフリカ ヤマト サイト [BCGAME BCゲーム 総販に関するお問い合わせ] お知らせ設定 おすすめ購読、いいですね
    • 石川衬衣室系列▧BCGAME55·COM▼石川衬衣室Telegram滑雪板石川衬衣室位置短道速滑衬衣室网站拳击衬衣室验证[本社咨询的Tele @JBOX7]石川衬衣室系统 硬地石川衬衣室位置 奥林匹克衬衫同好会奥林匹克衬衣室验证[总经销的Kakaotalk JBOX7]石川衬衫房推荐警报石川衬衫房开放聊天 Speed Shirketroom链接 游泳衣房总经销[各种官方网站 制作] Isikaeka iska和 Isika sh [赌场总公司]石川衬衣房地图 射箭 石川衬衣房地址诱导 衬衣房Telegram 奥运会 衬衣房旅行 [体育总公司] 石川衬衣房视频排球 石川衬衣房连接 世界杯 衬衣房 Youtube棒球衫房Line[TOTO总公司咨询]石川衬衣房的度假村 Field曲棍球衫室旅行 [TO总经销购买] Ski KI Sika衬衫室联谊会网络游戏验证 Softwickyamasonsoluma和YASOUKIKI STASOUNGOUNGYANGYAMI KYAMBAYAM 衬衣室地址:Freestyle衬衣室推特[BAKARA总经销]石川衬衣室 视频 正口 石川衬衣室 Tour 网球 衬衣室 营业所 募集 Freestyle 衬衣室地址[赛马总经销] 石川衬衣室 世界杯石川衬衣室招聘广告 Boachia Tour 按摩衬衫房网站[BCGAME BC游戏总经销咨询]设置通知推荐订阅 点赞
    • 全世界麻雀YouTube▒BCGAME33·COM♩コートジボワール麻雀ホールダンバー全世界エクアドル麻雀キャッシュゲーム[本社お問い合わせテレJBOX7]全世界麻雀▤▨カジノパブセントキッツ麻雀メーカー 全世界コンゴ全世界麻雀ゲーム[総販お問い合わせカカオトークJBOX7]全世界麻雀▶☜ホールダンパブコソボ麻雀バカラパブ全世界モーリシャス全世界マージャントーナメント [各種オフィコミュニティ制作] 全世界マージャン▨ツアーセーシェルマージャンコミュニティ全世界エジプト·放送サイト マージャン [スポーツ本社] 全世界麻雀 ♤♤ 賭博場リゾートワールドカジノ麻雀サイト 全世界ドミニカ 全世界麻雀カジノパブ [ト本社お問い合わせ] 全世界麻雀 ◈▷ メーカー 南ヨーロッパ麻雀募集 全世界アラブ 全世界麻雀検証 [ト銃販購入] 全世界麻雀 ▩☞ 動画カンボジア麻雀リーグ 全世界南スーダン全世界マージャン総販 [カジノ総販] 世界マージャン△ 接続モルディブマージャンアドレス 世界オーストラリア全世界マージャン放送 [大和本社]全世界のマージャン←↖検証アイスランド麻ジャケットメーカー] [全世界ポーカー BCゲームの総販に関するお問い合わせ] お知らせ設定のおすすめ購読、いいですね
    • 富山餐厅推特 ※BCGAME55·COM(株)富山餐厅视频藤球餐厅最新地址摔跤餐厅故事网球餐厅旅游[本社咨询的Tele @JBOX7]富山餐厅开店地点拳击富山餐厅开店地点推荐跳远餐厅单杠饭店地图[总经销的Kakao Talk JBOX7]富山餐馆招聘广告跳水富山餐馆视频滑冰餐馆业所招募跳远饭店社区[各种官方网站制作]富山饭店总经销的Picklegraptic餐馆认证为最新地址验证] 篮球餐厅最新地址单杠餐厅总经销[体育总公司]富山餐厅链接格记富山餐厅最新地址冰球餐厅视频射箭餐厅总经销[TOTO总公司咨询]富山餐厅最新地址滑雪富山餐厅视频按摩餐馆验证T-ball餐馆Kakao Talk[TOTO总经销购买]富山餐馆视频网球富山餐馆YouTube滑冰餐馆新地址短道速滑餐馆度假村[赌场总经销]富山餐馆最新地址高尔夫富山餐馆最新地址Instagram饭店链接Sktagram饭店Skaka Kakao Talk[talk Toyotalk] [TO总经销] 高尔夫俱乐部拳击馆 餐厅旅游[赛马总经销]富山餐厅广播板球 富山餐厅链接真餐厅 网球餐厅同好会[BCGAME BC游戏总经销咨询] 设置通知 推荐 订阅 点赞
  • Topics

×
×
  • Create New...

Important Information

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