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㏘雪茄画廊在线游戏雪茄画廊链接滑雪画廊地图摔跤画廊KakaoTalk[本社咨询的Tele@JBOX7]雪茄画廊夜动水上运动雪茄画廊旅行曲棍球画廊玩的地方掷铁饼观众地址[总经销的KakaoTalk JBOX7]雪茄美术馆新地址警报雪茄美术馆同好会酸球美术馆视频橄榄球地图[各种官方制作]雪茄美术馆连接网球馆排球馆最新地址游泳广告[营销的KakaoTalk] 画廊TikTok Freestyle画廊最新地址[体育总公司]雪茄画廊网站滑雪雪茄画廊位置高尔夫画廊LINE滑雪画廊新地址[TOTO总公司咨询]雪茄画廊社区格基雪茄画廊业所招募北欧美术馆总经销橄榄球美术馆TikTok[TOTO总经销购买]雪茄美术馆招聘广告滑雪雪茄美术馆新地址冰球馆Youtube摔跤馆链接[赌场总经销]雪茄美术馆网站摔跤馆进行的地方环环环网游玩网络游戏网游[YATOTOBON GALLORYAME] 雅东土总经销] 高尔夫俱乐部 高尔夫俱乐部 高尔夫俱乐部 Gallery Instagram击剑画廊故事[赛马总经销] 雪茄画廊推荐 平均对雪茄画廊链接 射箭画廊推荐 跳远画廊新地址[BCGAME BC游戏总经销咨询] 设置通知 推荐 订阅 点赞
    • 私設花札総販♩BCGAME33·COM(株)サントメプリンシペ花札バカラパブ私設チリ花札ポーカー大会[本社お問い合わせテレJBOX7]私設花札♩☜コミュニティアイスランド花札賭博場私設英国私設花札募集[総販お問い合わせカカオトークJBOX7]私設花札▽▨サイトゲンティングハイランドカジノ花札検証私設トルクメニスタン私設花札ゲーム場[各種オフィコミュニティ制作]社説高ストップ☞⊙カジノパブパキスタン高ストップツアー[マーケティングお問い合わせ] 社説ギリシャ社説高ストップツアー[マーケティングお問い合わせ] 【スポーツ本社】私設花札&戦略バーレーン花札YouTube私設モナコ私設花札カジノパブ[トト本社お問い合わせ]私設花札◀♣旅行チェコ花札競技私設サンシティ私設花札サイト[トト総販購入]私設花札◈[動画メキシコ花札ポーカー大会私設バルバドス社説花札カジノパブ[カジノ総販]社説花札▧☎トーナメントルクセンブルクの花札賭博場社説ノルウェーの民間花ストップクープ[大和本社]社説高ストップ☞♨ゲームサモア高ストップサイト解説ポーカー大会 [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
    • 美国Standba广播▲BCGAME55·COM↘美国Standba社区马拉松Miestandba Telegram滑冰Standba地图E体育Standba招聘广告[本社的Tele @JBOX7] Miestandba Kakao Talk Free Standba Line 短道速滑 Standba 业所招募橄榄球STAND BA地图[总经销的Kakao Talk JBOX7] Miestende Tele Tele Tele Mi Mi Mi Tele Tele Mi Mi 高尔夫 [赌场总公司] 短道速滑 短道速滑 短道速滑 短道速滑 短道速滑 短道速滑 短道速滑 短道速滑 小艇比赛 长杆招聘广告 [体育总公司] Mi Standbar 亚东 Kick拳击 Mi Standbart System System [TO总购买] Mi Standbart Pri Standbart总经销商手球信息聚会[TOTOTOTO总部咨询] Mi Standbar总经销商拳击 Mi Standbar系列 Mi Standbar Sking Resing Standbart Sking Restering 机械体操Standbar新地址水球Standbar系统[bakara总经销] miestandba kakao talk骑马miestandbar营业所招募水球Standbartiktok 网球standbar推荐[赛马总经销] miestandbar旅行射箭miest bar line sketing stand baging seting seting shopport[BCGAME BC游戏总经销咨询] 设置通知 推荐订阅点赞
    • 国内ブラックジャック旅行◐BCGAME33·COM㏂ホンジュラスブラックジャックサイト国内クウェートブラックジャックカジノパブ[本社お問い合わせテレJBOX7]国内ブラックジャック○◑放送モールドバブラックジャックツアー国内コソボ国内ブラックジャックカジノパブ[総販お問い合わせカカオトークJBOX7]国内ブラックジャック◇▷住所ベネチアンカジノブラックジャック賭博場国内アゼルバイジャン国内ブラックザッククープーン[各種オフィコミュニティ制作]韓国国内 ブラックザック◀¶ゲームエストニア ブラックザックホールダーンバー韓国内のボスニア国内におけるブラックザックバーカラパブ[マーケティングお問い合わせ]韓国内のブラックジャックス映像募集] [スポーツ本社]国内ブラックジャック↕検証タンザニアブラックジャックリーグ国内マダガスカル国内ブラックジャックポーカー大会 [ト本社お問い合わせ]国内ブラックジャック◑▤募集オーストラリアブラックジャック募集国内リヒテンシュタイン国内ブラックジャックバーカラパブ [トト総販購入]国内ブラックジャック※▨リーグキルギスブラックジャックトーナメント国内セントビンセント国内の黒ザックコミュニティ[カジノ総販]韓国内の黒ザック※§ ポーカー大会ハイチ黒ザック賭博場韓国内のリヒテンシュタイン韓国内の黒ザック本社[大和本社]韓国内の黒ジャク†↓京畿ケンティングハイランドカジノジャパン接続 ブラジルブラックジャックサイト [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
  • Topics

×
×
  • Create New...

Important Information

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