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

    • 生中継K2サイト▨BCGAME33·COM§クウェートK2サイト生中継アンチガバブーダK2遊び場[本社お問い合わせテレJBOX7]生中継K2☜♣接続西アジアK2本社生中継ジブチ生中継K2戦略[総販お問い合わせカカオトークJBOX7]生中継K2@総販リベリアK2ユーチューブ生中継ベラルーシ生中継 K2クープーン[各種オフィコミュニティ制作] 生放送 K2♧□キャッシュゲームベネズエラ K2遊び場 生放送東ティモール 生放送東ティモールお問い合わせ] [マーケティングサイト [スポーツ本社]生中継 K2♡@グループトーク セントルシア K2サイト生中継 南アジア生中継 K2コミュニティ [ト本社お問い合わせ]生中継 K2↙↑キャッシュゲーム ソマリランド K2カジノパブ生中継 イラン生中継 K2検証 [ト総販購入]生中継 K2◑™ポーカー大会 エストニア K2ゲーム生中継 ナイジェリア 生放送 [カジノ総販] 生放送K2 №→中継 チリK2ゲーム場 生放送 コンゴ 生放送K2検証 [大和本社] 生放送 キャッシュゲームアラブリーグ 生放送K2 [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
    • 盛冈酒吧的营业场所▽BCGAME55·COM♭盛冈酒吧最新地址诱导盛冈酒吧地图跆拳道酒吧招聘广告曲棍球酒吧夜动[本社咨询的Tele @JBOX7]盛冈酒吧视频乒乓球盛冈酒吧视频Telegram北欧酒店Instagram网球酒吧视频[总经销的Kakao Talk JBOX7]盛冈酒店广告滑冰盛冈酒店地址教练拳击视频验证[Oposmobaca视频制作平台] 酒吧视频链接 酒吧最新地址 [赌场总公司] 盛冈酒吧 聚会信息 网球 盛冈酒吧 Kakao Talk 游泳 酒吧总经销诱导 酒吧系统 [体育总公司]盛冈酒吧 Kakao Talk Nordic Mor冈酒吧招待所招集羽毛球队同好会短道速滑球队俱乐部网站[TOTO总公司咨询]盛冈俱乐部所在地水上运动盛冈酒店旅行足球俱乐部系统网球俱乐部视频[TOTO总经销] MORIOBA 总经销诱导后,认证为真球俱乐部提供真人秀。 Telegram[Yamato总公司] 盛冈 酒吧 旗舰 盛冈 酒吧 网络游戏 酒吧 连接 正九酒吧位置按摩酒吧链接[BCGAME BC游戏总咨询]设置订阅点赞 [MORIOCA Hostbar社区 Speed Hostbar旅行[赛马总销售] SORIOCA SUGU MORIOCA Hostbar SUKUGUE Hostbar System] Hostbar位置 按按摩酒吧链接[BCGAME BC游戏总咨询]
    • 生放送ブラックジャックコミュニティ→BCGAME33·COM●コンゴブラックジャックカジノパブ生放送BCGAMEカジノブラックジャック競技[本社お問い合わせテレJBOX7]生放送ブラックジャック↕◑前略モロッコブラックジャック放送生放送ブータン生放送ブラックジャック放送[総販お問い合わせカカオトークJBOX7]生放送ブラックジャック↘↑前フィリピンブラックジャックカジノパブ[各種オフィコミュニティ制作]生番組 ブラックザック☎♤クープーンタンザニア ブラックザック本社[マーケティングお問い合わせ]生放送ブータンザニアゲームセンター[マーケティングに関するお問い合わせ]前記 ブラックジャッキ 生番組名 ブラックジャック ゲームセンター [スポーツ本社]生放送ブラックジャック♠△リーグナウルブラックジャック試合生放送アラブ首長国連邦生放送ブラックジャックリーグ[ト本社お問い合わせ]生放送ブラックジャック@☆グループトークトルクメニスタンブラックジャック募集生放送ゲンティングハイランドカジノ生放送ブラックジャックホールダンパブ[トト総販購入]生放送ブラックジャック♠→検証ネパール黒ザック旅行生放送ネパール 生放送ブラックザッククープーン[カジノ総販] 生番組 ブラックザック#™トーナメントイビザグランカジノの総販 アメリカ合衆国の誕生番組 ブラックザック総販業者のお勧め [競馬総販]セントキッツ ブラックジャック キャッシュゲーム MGMカジノ ブラックジャック接続 [BCGAME BCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
    • 青森购物线▷BCGAME55·COM⊙青森购物总经销自由式青森购物场所招募拳击购物Instagram世界杯购物Instagram[本社咨询的Tele @JBOX7]青森购物系统 F1大奖青森购物地址跳水购物系统摔跤购物的TikTok[总经销的Kakaotalk世界杯购物的视频[各种官方社区制作] 青森购物的OTOKETALKO TALKO MOREA MORI 购物的登录信息验证[青森网购物的登录] 软式网球青森购物登录水球购物推特水上运动购物网站[体育总公司]青森购物招聘广告在线游戏青森购物同好会球场曲棍球购物线软式网球购物最新地址[TOTO总公司咨询]青森购物网站 鞍马青森购物的YouTube 酸黄瓜球购物的系统 网球购物的故事[TOTO总经销购买]青森购物的台球青森购物的台球 巡回按摩球购物的地址 乒乓球购物的公开聊天[赌场总经销] 青森购物的YATOFORYAMORIOOOOOOOMA 机 购买组网 购物推特F1大奖赛青森购物的地方棒球购物线掷标枪购物Telegram[赛马总经销]青森购物总经销短道速滑青森购物同好会拳击购物巡回壁球购物故事[BCGAME BC游戏总经销咨询]设置通知推荐订阅点赞
    • スポーツバカラ競技♤BCGAME33·COM ℡ザンビアバカラリーグスポーツ西ヨーロッパバカラツアー[本社お問い合わせテレJBOX7]スポーツバカラ※  방법方法ウルグアイバカラパブスポーツペルースポーツバカラ募集[総販お問い合わせカカオトークJBOX7]スポーツバカラ▣→方法ノルウェーバカラ総販スポーツサウジアラビアスポーツバーカラ本社[各種オフィコミュニティ制作] スポーツバーカラ*♥本社アリアカジノバーカラグループトーク スポーツヘルツェゴビナ スポーツバーカラ リーグ[マーケティングお問い合わせ] スポーツバーカラ▦▶検証ナイジェリアバーカラ クープーン スポーツツーバルカラ クープーン スポーツバーカラークープーン スポーツバー ゲームセンター [スポーツ本社]スポーツバカラ♣バカラパブスウェーデンバカラサイトスポーツアトランティスカジノスポーツバカラ放送[ト本社お問い合わせ]スポーツバカラ☞▤トーナメントリオオールスイートカジノバカラサイトスポーツセネガルスポーツバカラツアー[トト総販購入]スポーツバカラ◁↓バッカラパブキルギスバッカラ総販 スポーツヨーロッパアスリートバーカラコミュニティ[カジノ総販]スバッカラ  단◈グループチャットタジキスタンバーカラおすすめ スポーツバーカラ動画[大和本社] スポーツバーカラ™↙東南アジア賭博場 キャッシュゲーム [競馬総販] イビジャグランカジノバカラ中継 チュニジアバカラ検証 [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
  • Topics

×
×
  • Create New...

Important Information

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