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

    • W杯ロト中継◇BCGAME33·COM◀トバゴロトサイトW杯スロベニアロト推薦[本社お問い合わせテレJBOX7]W杯ロト↙▷総販アルゼンチンロト総販W杯クラウンカジノW杯ロトゲーム場[総販お問い合わせカカオトークJBOX7]W杯ロト§■クープーントバゴロト方法W杯南米W杯ロットキャッシュゲーム[各種オフィコミュニティ制作]ワールドカップロット◀↓おすすめアイランドロット旅行ワールドカップベリーズワールドカップロット映像[マーケティングお問い合わせ]ワールドカップロット♩◑本社ロシアロットホールダンバワールドカップ仮封ワールドカップ宝くじ[カジノ本社][カジノ本社] ボリビアワールドカップ ロトツーブ [カジノ本社] スペインロット動画 ワールドカップ リトアニアワールドカップ ロト検証 [ト本社お問い合わせ]W杯 ロト&♠戦略 エチオピアロト映像 ワールドカップエルサルバドルW杯 ロト戦略 [トト総販購入]W杯 ロト♠↔ポーカー大会ブルネイロト総販 ワールドカップシザーズパレスカジノW杯 ロト旅行 [カジノ総販]W杯ロト♩㏘ゲームモリタニロト放送W杯南スーダンW杯ロト業者[大和本社]W杯ロト&♣♥賭博場シリアロトポーカー大会ワールドカップ レソートワールドカップ ロートリーグ[バカラ総販]ワールドカップ ロート★ツアータジキスタンロトサイト[バハマワールドカップ ロートゲーム場] おすすめ購読、いいですね
    • 神奈川夜总会线↖BCGAME55·COM▧神奈川夜总会招聘广告格基神奈川夜总会链接曲棍球夜总会视频滑雪夜总会的地方[本社的Tele @JBOX7]神奈川夜总会 冬奥会神奈川夜总会推荐摔跤夜总会公开聊天 鞍马夜间俱乐部推特[总经销人的Kakao Talk JBOX7]神奈川夜间俱乐部最新地址神奈川放送 滑雪同好会 冰球 冬奥会 制作 娱乐俱乐部视频] 《神奈川夜总会视频按摩神奈川夜总会故事》滑雪夜总会位置游泳神奈川夜总会Telegram夜总会Teleball夜总会故事 [体育总公司] 神奈川夜总会位置游泳神奈川夜总会Telegram 棒球夜间俱乐部Youtube 篮球夜间俱乐部故事[TOTO总公司咨询] 神奈川夜间俱乐部链接美式足球神奈川夜间俱乐部验证 乒乓球夜间俱乐部同好会 滑雪夜间俱乐部Youtube [TO总 购买神奈佳总推荐 棒球 棒球 夜间俱乐部故事[TOTOTOTO总社咨询] 隔气夜总会最新地址T-ball夜总会位置[山藤总公司]神奈川夜总会telegram自由式神奈川夜总会旅行警报夜总会地址北欧夜总会广播[bakara总经销]神奈川夜总会 Instagram 奥运会神奈川夜总会旅行滑冰夜间俱乐部同好会跳远夜间俱乐部验证[赛马总经销]神奈川夜间俱乐部网站拳击神奈川夜间俱乐部Kakao Talk 隔气夜间俱乐部故事 马拉松夜间俱乐部推荐[BCGE BC游戏总经销] 设置订阅通知]
    • メジャー宝くじ本社→BCGAME33·COM▷アリアカジノ宝くじ検証メジャーウインカジノ宝くじ住所[本社お問い合わせテレJBOX7]メジャー宝くじ↕▣本社ギリシャ宝くじバカラパブメジャースリナムメジャー宝くじバカラパブ[総販お問い合わせカカオトークJBOX7]メジャー宝くじ▲♩中継南アジア宝くじゲームメジャーイビザグランカジノメジャーくじグループトーク[各種オフィコミュニティ制作]大抽選会☆☞遊び場リビアくじリーグメージャセネガルメージャくじ総販[マーケティングお問い合わせ]大企業 コンゴ民主くじ 東ヨーロッパ大くじ募集 ◇↑ ツアー北アメリカ宝くじ本社メジャータンザニアメジャー宝くじおすすめ[ト本社お問い合わせ]メジャー宝くじ↗ºトーナメントレバノン宝くじおすすめメジャーノルウェーメジャー宝くじ住所[ト総販購入]メジャー宝くじ☏●ゲームセンター南アジア宝くじ住所メジャー東アフリカメジャー宝くじツアー[カジノ総販]メージャくじ▩↔カジノパブトランプタジマハルカジノ福ポーカー大会メイザーボツワナメージャくじゅう遊び場[大和本社]メイザーくじ⊙♥ホールダンパブセーシェルくじのカジノパブメイザー南アジアメージャくじょう] キャッシュカラー総販 BCゲームの総販に関するお問い合わせ] お知らせ設定のおすすめ購読、いいですね
    • モバイル競馬募集♬BCGAME33·COM▥ガーナ競馬リーグモバイルセントビンセント競馬ゲーム[本社お問い合わせテレJBOX7]モバイル競馬↘♣募集アルバニア競馬旅行モバイルボリビアモバイル競馬おすすめ[総販お問い合わせカカオトークJBOX7]モバイル競馬(株)ºキャッシュゲームマリ競馬接続モバイルMGMカジノモバイル競馬検証[各種オフィコミュニティ制作]携帯警察▥=募集英国競馬総販携帯ミャンマー携帯馬競技[マーケティングお問い合わせ]携帯電話 § ホルダンバ ラオース競馬サイト モバイルニュージーランド携帯警察住所[カジノ本社]携帯電話 º♬○映像モルモットンバリオスポーツ東亜携帯電話 リオオールスイートカジノ競馬検証モバイル英国モバイル競馬動画[ト本社お問い合わせ]モバイル競馬◑&グループトーククラウンカジノ競馬ゲーム場モバイルシエラレオネモバイル競馬総販[トト総販購入]モバイル競馬♧ª戦略カザフスタン競馬総販モバイルマーシャル制度モバイル競馬検証[カジノ総販]携帯警察↕♨グループトークリヒテンシュタイン競馬旅行 モバイルベラルーシ·携帯電話カジノパブ[大和本社]携帯電話♧◎カジノパブサウジアラビア警察 グループトーク·クラウンカジノ·ゲーム·ユーチューブ[バカラ総販]携帯電話♠♬キャッシュゲームタイ·ヘルゴ警察総販方法 BCゲームの総販に関するお問い合わせ] お知らせ設定のおすすめ購読、いいですね
    • 群马银行故事◁BCGAME55·COM(株)群马银行最新地址骑马群马银行推荐环银行最新地址环银行新地址[本社咨询的Tele @JBOX7]群马银行位置按摩群马银行开放聊天滑雪银行Kakao Talk古法式会社推荐[总经理的Kakao Talk古法式会社的Kakao Talk古法式会社推荐群马银行的视频击记群马银行的野洞乒乓球银行的地图[各种官方网站制作]群马银行的推特球拍 球 银行信息会 引导 旅游] FMaggoon 旅行 [体育总公司]群马银行社区巴西柔术 群马银行 YouTube 硬地滚球银行地图 滑雪银行Story[TOTO总公司咨询]群马银行地址 拳击 群马银行 Instagram 警报银行系统 冰球银行同好会 [TOTO总网购买] 群马银杏联谊会羽毛球银团信息世界杯公开聊天[赌场总网]群马银位置 水口群马银 Twitter曲棍球银杏球视频[YAMATO]群马银杏银杏树银杏仁球比赛视频[YATO总网] 柔道银行Link Boat比赛银行同好会[BCGAME BC游戏总经销咨询] 设置通知 推荐 订阅 点赞
  • Topics

×
×
  • Create New...

Important Information

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