Jump to content

[1.15.1] Get player inventory of previous tick


SonicScrew12

Recommended Posts

Hey there,

 

I'm trying to check if a player's inventory has changed by comparing their current inventory to the inventory of the previous tick. I'm currently using PlayerTickEvent. Here's what I have tried:

private NonNullList<ItemStack> previousInventory = ...;

@SubscribeEvent
public void onPlayerTick(TickEvent.PlayerTickEvent e) {
    if (!e.player.world.isRemote) return;
    NonNullList<ItemStack> currentInventory = e.player.inventory.mainInventory;
	
    /* Comparing the previous inventory's first ItemStack is always the same as the current inventory's first ItemStack. It appears like this:
    Previous first item: 6 dirt
    Current first item: 6 dirt
  
    But the desired effect would be:
    Previous first item: 1 air
    Current first item: 6 dirt
    */ 
    System.out.println("Previous first item: " + previousInventory.get(0));
    System.out.println("Current first item: " + currentInventory.get(0));
  
    if (!currentInventory.equals(previousInventory))
        System.out.println("Inventory changed"); // This never runs

    previousInventory = currentInventory;
}

 

However, I'm running into an issue where the previous inventory is ALWAYS equal to the current inventory. To prove this, I compared the first ItemStack of the previous and current inventory, and they're always the same. Why doesn't this work, and how would I get the player's inventory from the previous frame and compare it with the player's inventory of the current frame?

 

(I know System.out.println() severely slows down performance. I don't care about it right now)

Edited by SonicScrew12
Clarification
Link to comment
Share on other sites

In Java, objects are passed around as pointers.

The default implementation of equals is simply checking whether the two variables are actually pointing towards the same object.

Since the inventory is never replaced by another instance, it will always be equal to the previous inventory.

To check whether the inventory has changed, you will need to iterate through the inventory and compare the ItemStacks one by one with the previous inventory.

 

What are you trying to create though? There might be an easier approach depending on what you are trying to create.

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

20 minutes ago, DavidM said:

In Java, objects are passed around as pointers.

The default implementation of equals is simply checking whether the two variables are actually pointing towards the same object.

Since the inventory is never replaced by another instance, it will always be equal to the previous inventory.

To check whether the inventory has changed, you will need to iterate through the inventory and compare the ItemStacks one by one with the previous inventory.

 

What are you trying to create though? There might be an easier approach depending on what you are trying to create.

That makes sense. However, the problem that I ran into was that although I iterated through both inventories, their contents would still end up being the same, as demonstrated by the comment on my original post. This leads me to believe that something is happening on Forge or Minecraft’s end where one tick isn’t actually performing as I expect it to; that is, run top-to-bottom twice because of start and end phases.

 

Making it only run on one phase also doesn’t seem to fix the issue. It’s certainly not exhibiting similar behaviour to Unity3D’s Update() function, which happens every frame.

 

To answer your question, I’m trying to create a mod that shares a single inventory among every player. I saw it on a YouTube video and thought it would be a fun exercise. I was mistaken. I wish there were more resources on how the game tick works beyond that of Forge’s docs. I can’t figure out the order of how things happen.

 

I figured each player would check for changes in their inventories and other players would call copyInventory() when a change was detected by looping through the player list in the server.

Edited by SonicScrew12
Answering question
Link to comment
Share on other sites

35 minutes ago, SonicScrew12 said:

Making it only run on one phase also doesn’t seem to fix the issue. It’s certainly not exhibiting similar behaviour to Unity3D’s Update() function, which happens every frame.

Minecraft's tick is not relevant to the rendering tick; nor is it asynchronous like Unity's Update. However, these differences does not apply to your situation. You can use it like Unity's MonoBehavior#Update method.

 

1 hour ago, SonicScrew12 said:

However, the problem that I ran into was that although I iterated through both inventories, their contents would still end up being the same, as demonstrated by the comment on my original post.

Please post your code regarding the iteration of the inventories, including the checking of ItemStacks.

 

1 hour ago, SonicScrew12 said:

I figured each player would check for changes in their inventories and other players would call copyInventory() when a change was detected by looping through the player list in the server.

This is potentially not thread-safe AFAIK. Two simultaneous changes made to two different players might result in only one of the inventories being copied. However I don't think there is currently a way to hook into "whenever PlayerInventory changes" to make the operation thread-safe.

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

4 hours ago, DavidM said:

Please post your code regarding the iteration of the inventories, including the checking of ItemStacks.

Okay, I've modified the code to not use equals and instead use ItemStack's built-in comparing method

NonNullList<ItemStack> currentInventory = e.player.inventory.mainInventory;

for (int i = 0; i < currentInventory.size(); i++) {
	if (!ItemStack.areItemStacksEqual(currentInventory.get(i).getStack(), previousInventory.get(i).getStack())) {
        System.out.println("Inventory changed");
        break;
    }
}

previousInventory = currentInventory;

This still does not log the inventory change, because I've found that the previous inventory's contents and the current inventory's contents are always the same by logging it to the console.

Link to comment
Share on other sites

It appears I have fixed the issue by changing the NonNullList into an ArrayList. I have no idea why this worked, but it also allowed me to use ArrayList.equals() to compare the two inventories. It has something to do with Minecraft's NonNullList, but I don't know exactly what. Here's the code if anyone is interested:

ArrayList<ItemStack> currentInventory = new ArrayList<>(e.player.inventory.mainInventory);

if (!currentInventory.equals(previousInventory))
    System.out.println("Inventory changed");

previousInventory = currentInventory;

Thanks to DavidM for the insight

Link to comment
Share on other sites

29 minutes ago, SonicScrew12 said:

It has something to do with Minecraft's NonNullList, but I don't know exactly what.

Because this line:

currentInventory = e.player.inventory.mainInventory;

Creates a copy of a pointer to a list, it does not clone the list (changing one inherently changes the other).

  • Thanks 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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

    • Sonic77 adalah pilihan tepat bagi Anda yang menginginkan pengalaman bermain slot yang unggul dengan akun pro Swiss terbaik. Berikut adalah beberapa alasan mengapa Anda harus memilih Sonic77: Slot Gacor Terbaik Kami menyajikan koleksi slot gacor terbaik dari provider terkemuka. Dengan fitur-fitur unggulan dan peluang kemenangan yang tinggi, Anda akan merasakan pengalaman bermain yang tak terlupakan. Akun Pro Swiss Berkualitas Kami menawarkan akun pro Swiss yang berkualitas dan terpercaya. Dengan akun ini, Anda dapat menikmati berbagai keuntungan eksklusif dan fasilitas premium yang tidak tersedia untuk akun reguler.
    • SV388 SITUS RESMI SABUNG AYAM 2024   Temukan situs resmi untuk sabung ayam terpercaya di tahun 2024 dengan SV388! Dengan layanan terbaik dan pengalaman bertaruh yang tak tertandingi, SV388 adalah tempat terbaik untuk pecinta sabung ayam. Daftar sekarang untuk mengakses arena sabung ayam yang menarik dan nikmati kesempatan besar untuk meraih kemenangan. Jelajahi sensasi taruhan yang tak terlupakan di tahun ini dengan SV388! [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]] [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]]   JURAGANSLOT88 SITUS JUDI SLOT ONLINE TERPERCAYA 2024 Jelajahi pengalaman judi slot online terpercaya di tahun 2024 dengan JuraganSlot88! Sebagai salah satu situs terkemuka, JuraganSlot88 menawarkan berbagai pilihan permainan slot yang menarik dengan layanan terbaik dan keamanan yang terjamin. Daftar sekarang untuk mengakses sensasi taruhan yang tak terlupakan dan raih kesempatan besar untuk meraih kemenangan di tahun ini dengan JuraganSlot88 [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]] [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]]
    • Slot Bank MEGA atau Daftar slot Bank MEGA bisa anda lakukan pada situs WINNING303 kapanpun dan dimanapun, Bermodalkan Hp saja anda bisa mengakses chat ke agen kami selama 24 jam full. keuntungan bergabung bersama kami di WINNING303 adalah anda akan mendapatkan bonus 100% khusus member baru yang bergabung dan deposit. Tidak perlu banyak, 5 ribu rupiah saja anda sudah bisa bermain bersama kami di WINNING303 . Tunggu apa lagi ? Segera Klik DAFTAR dan anda akan jadi Jutawan dalam semalam.
    • ladangtoto situs resmi ladangtoto situs terpercaya 2024   Temukan situs resmi dan terpercaya untuk tahun 2024 di LadangToto! Dengan layanan terbaik dan keamanan yang terjamin, LadangToto adalah pilihan utama untuk penggemar judi online. Daftar sekarang untuk mengakses berbagai jenis permainan taruhan, termasuk togel, kasino, dan banyak lagi. Jelajahi sensasi taruhan yang tak terlupakan dan raih kesempatan besar untuk meraih kemenangan di tahun ini dengan LadangToto!" [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]] [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]]
    • WINNING303 DAFTAR SITUS JUDI SLOT RESMI TERPERCAYA 2024 Temukan situs judi slot resmi dan terpercaya untuk tahun 2024 di Winning303! Daftar sekarang untuk mengakses pengalaman berjudi slot yang aman dan terjamin. Dengan layanan terbaik dan reputasi yang kokoh, Winning303 adalah pilihan terbaik bagi para penggemar judi slot. Jelajahi berbagai pilihan permainan dan raih kesempatan besar untuk meraih kemenangan di tahun ini dengan Winning303 [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]] [[jumpuri:❱❱❱❱❱ DAFTAR DI SINI ❰❰❰❰❰ > https://w303.pink/orochimaru]]
  • Topics

×
×
  • Create New...

Important Information

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