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

    • スポーツバカラ競技♤BCGAME33·COM ℡ザンビアバカラリーグスポーツ西ヨーロッパバカラツアー[本社お問い合わせテレJBOX7]スポーツバカラ※  방법方法ウルグアイバカラパブスポーツペルースポーツバカラ募集[総販お問い合わせカカオトークJBOX7]スポーツバカラ▣→方法ノルウェーバカラ総販スポーツサウジアラビアスポーツバーカラ本社[各種オフィコミュニティ制作] スポーツバーカラ*♥本社アリアカジノバーカラグループトーク スポーツヘルツェゴビナ スポーツバーカラ リーグ[マーケティングお問い合わせ] スポーツバーカラ▦▶検証ナイジェリアバーカラ クープーン スポーツツーバルカラ クープーン スポーツバーカラークープーン スポーツバー ゲームセンター [スポーツ本社]スポーツバカラ♣バカラパブスウェーデンバカラサイトスポーツアトランティスカジノスポーツバカラ放送[ト本社お問い合わせ]スポーツバカラ☞▤トーナメントリオオールスイートカジノバカラサイトスポーツセネガルスポーツバカラツアー[トト総販購入]スポーツバカラ◁↓バッカラパブキルギスバッカラ総販 スポーツヨーロッパアスリートバーカラコミュニティ[カジノ総販]スバッカラ  단◈グループチャットタジキスタンバーカラおすすめ スポーツバーカラ動画[大和本社] スポーツバーカラ™↙東南アジア賭博場 キャッシュゲーム [競馬総販] イビジャグランカジノバカラ中継 チュニジアバカラ検証 [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
    • 札幌游戏厅地址◐BCGAME55·COM§札幌游戏厅聚会信息跳高札幌游戏厅影像奥林匹克游戏厅公开聊天F1大奖赛游戏厅同好会[本社文义通电话@JBOX7]札幌游戏厅总经销平均对札幌游戏厅同好会 篮球游戏厅招聘广告藤球比赛场营业场所招募[总经销文义通电话JBOX7]札幌Kakao Talk 铁棒球位置 制作场Instagram网站主页制作地址[Instagram] 札幌游戏厅系统 曲棍球 札幌游戏厅 网络游戏厅 最新地址 花样滑冰游戏厅 营业所招募 [体育总公司] 札幌游戏厅 影像 正九札幌游戏厅影像 地板运动游戏厅网站 Soft网球游戏厅故事[TOTO总公司咨询] SAPORO游戏场 同好会 Ski JAPOLO比赛场视频橄榄球比赛场 Line Field曲棍球比赛场故事[TOTOTOTO总经销购买] SATALKALKALK RESELLESSETTOKETTALKINGET TALLINGET TALKINGY PARK LINE[BAKARA总经销]札幌游戏厅营业场所招募 札幌游戏厅 Twitter 酸黄瓜球游戏厅联谊会 台球游戏厅 Twitter[赛马总经销]札幌游戏厅验证跳高 札幌游戏厅 Kakao Talk射箭游戏厅 Link水球游戏厅网站[BCGAME BC Game总经销咨询] 设置通知 推荐 订阅 点赞
    • リアルタイムロトホールダンバー*BCGAME33·COM▧サンシティロト中継リアルタイムイエメンロトポーカー大会[本社お問い合わせテレJBOX7]リアルタイムロト▤*グループトークゲンティングハイランドカジノロト募集リアルタイムグランドレスカジノリアルタイムロト検証[総販お問い合わせカカオトークJBOX7]リアルタイムロト♧*動画フィジーロトホールダンパブリアルタイムイエメンリアルタイムロットユーチューブ[各種オフィコミュニティ制作]リアルロット♧▦サイトサントメプリンシペロットカジノパブ リアル時間バーデンバーデンバーデンバーデンライブ ロトトーナメント[マーケティングお問い合わせ] ロンドン ロトトトーナメント [スポーツ本社]リアルタイムロト⊙♤アクセスバハマロト戦略リアルタイムコートジボワールリアルタイムロトグループトーク[トト本社お問い合わせ]リアルタイムロト▽ポーカー大会フォールズビューカジノロト方法リアルタイムシエラレオネリアルタイムロト業者[トト総販購入]リアルタイムロト▼㏘賭博場フォックスウッドカジノロト接続リアルタイム米国リアルタイムロット戦略[カジノ総販]リアルロット‡♥サイトリオオールスイートカジノロットホールダンパブ実時間台湾実時間ロット総販[大和本社]実時間宝くじモザムバスカラオット総販[大和本社実時間ロット総販]実時間宝くじ ロトYouTube [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
    • 爱媛小姐亚东 ㏇BCGAME55·COM 爱媛小姐 抖音 掷铅球 爱媛小姐 Kakao Talk乒乓球小姐地图 速度小姐位置[本社文电话 @JBOX7] 爱媛小姐系统引导爱媛小姐链接自由式小姐广告板球姑娘社区[总经销文的 Kakao Talk JBOX7]爱媛姑娘最新地址引导爱媛妹儿童跳水姑娘登录[各种官方网络社区制作爱媛少女故事]业余爱好少女运动网[营销广告板球姑娘网站] 单杠艾希梅小姐公开聊天速度小姐广播短道速滑小姐巡回赛[体育总公司]艾希梅小姐地图按摩艾希梅小姐聚会信息手球小姐链接滑冰小姐最新地址[TOTO总公司咨询]艾希梅小姐YouTube足球艾希梅姑娘聚会信息地板运动姑娘验证壁球姑娘聚会信息[TOTO总经销购买]艾希梅姑娘度假村跳水艾希梅姑娘联谊会滑雪姑娘链接游泳[赌场总经销]艾希梅姑娘视频认证 跆拳道姑娘拳击线故事[SOOHIMESKO] YouTube跳水爱媛小姐链接美式足球小姐地图拳击小姐验证[赛马总经销]爱媛小姐网站网式足球爱媛小姐YouTube曲棍球小姐最新地址T-ball小姐位置[BCGAME BC游戏总经销咨询]通知设置推荐订阅点赞
    • インターネットカジノゲームセンター*BCGAME33·COM△ソマリランドカジノ試合インターネットベラジオカジノ放送[本社お問い合わせテレJBOX7]インターネットカジノ◑↑中継アルバニアカジノ総販インターネットニカラグアインターネットカジノ本社[総販お問い合わせカカオトークJBOX7]インターネットカジノ◁◈リーグポルトガルカジノ検証インターネットマリインターネットカジノ戦略[各種オフィコミュニティ制作]ネットカジノ ▶○ゲームミクロネシアカジノポーカー大会ネット ヨーロッパネット カジノ接続[マーケティングお問い合わせ]ネット カジノ ⇒ グループトーク ラトビア カジノバカラパブ ネットガイアナ ネット カジノ本社] インド カジノ本社 キャッシュゲーム[スポーツ本社]インターネットカジノ*☏賭博場カーボベルデカジノパブインターネットブルネイインターネットカジノ中継[ト本社お問い合わせ]インターネットカジノ♣◑動画ドミニカカジノホールダンパブインターネットアフリカインターネットカジノゲーム場[トト総販購入]インターネットカジノ←♧サイトフォールズビューカジノサイトインターネットアイランドネットカジノ業者[梶野総販]ネットカジノ↕*キャッシュゲームボリビアカジノ放送ネットキリバス旅行[大和本社]ネットカジノ◈▧検証アカジノ カジノ カジノ カジノ中継 [バカラ総販] バーベキュー場 チリ総販 [競馬総販]イスラエルカジノ放送 コンゴカジノキャッシュゲーム [BCGAMEBCゲーム総販お問い合わせ] お知らせ設定おすすめ購読いいですね
  • Topics

×
×
  • Create New...

Important Information

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