jayxo Posted September 15, 2021 Posted September 15, 2021 Hello! I have a book that writes down a players life information. I.e. how long they’ve been living, and when they die on that life, how long they lasted and what they died from. My question is, is it possible to update content in a written book when it’s opened? Becuase the way it works now, you have to get the book with a command instead of it refreshing it’s content automatically. Any help would be extremely helpful! Thank you. Here’s a pastebin of the current class that writes in the book: https://pastebin.com/s6X05Nzz Quote
Alpvax Posted September 24, 2021 Posted September 24, 2021 (edited) I'm assuming that it is just a vanilla book with custom NBT, not your own custom item? If that is the case you could listen to the use item event (sorry, I can't remember the name of it off the top of my head), check for the book being used (opened) and sync the data with the item. Edited September 24, 2021 by Alpvax Quote
Luis_ST Posted September 24, 2021 Posted September 24, 2021 28 minutes ago, Alpvax said: If that is the case you could listen to the use item event (sorry, I can't remember the name of it off the top of my head), check for the book being used (opened) and sync the data with the item. you mean LivingEntityUseItemEvent.Start? Quote
Alpvax Posted September 27, 2021 Posted September 27, 2021 On 9/24/2021 at 2:45 PM, Luis_ST said: you mean LivingEntityUseItemEvent.Start? No, I actually meant PlayerInteractEvent.RightClickItem, books don't count as being "used" I don't think Quote
jayxo Posted October 11, 2021 Author Posted October 11, 2021 (edited) On 9/27/2021 at 7:21 AM, Alpvax said: No, I actually meant PlayerInteractEvent.RightClickItem, books don't count as being "used" I don't think sorry for such a late response! i actually tried that before, but it would always show the player who opened it info. like i would open your book, and it would display my players capability information instead of yours. https://pastebin.com/3qpwP8BF Edited October 11, 2021 by jayxo Quote
jayxo Posted October 11, 2021 Author Posted October 11, 2021 this is the HealthBookUtils.class https://pastebin.com/s6X05Nzz i didn’t want to rewrite the entire vanilla written book since i could use nbt data. Quote
jayxo Posted October 11, 2021 Author Posted October 11, 2021 yeah! i was saying that in reference to this 1 hour ago, diesieben07 said: Why is this a real written book that you try to keep up to date instead of just using a custom book with a screen that just displays the correct info? Quote
Alpvax Posted October 13, 2021 Posted October 13, 2021 On 10/11/2021 at 4:21 PM, jayxo said: it would always show the player who opened it info. https://pastebin.com/3qpwP8BF I assumed that was what you wanted. Currently you get the capability of the player opening the book: @SubscribeEvent public void onUse(PlayerInteractEvent.RightClickItem event) { PlayerEntity player = event.getPlayer(); ... You need to use the player who "owns" the book instead. So store the "owner's" id in the book somehow (NBT/capablility), then when the book is opened, get the player from the id (they may not exist/be offline, in which case you can't reasonably update), then update the data. It might be a better idea to change to a level (overworld) capability / saveddata if you need to access the data for offline players, then retrieve that data for displaying in your book. As die7 says, it will probably be better to create a custom gui (based on the vanilla book screen, you can possibly subclass it, although I'm not sure), then retrieve the latest data on demand, rather than updating the item nbt each time. Quote
jayxo Posted October 13, 2021 Author Posted October 13, 2021 1 hour ago, Alpvax said: I assumed that was what you wanted. Currently you get the capability of the player opening the book this was actually what one of the issues i had was, i wanted to be able to look at any players book without it always showing my capability information. 1 hour ago, Alpvax said: You need to use the player who "owns" the book instead. So store the "owner's" id in the book somehow (NBT/capablility), then when the book is opened, get the player from the id (they may not exist/be offline, in which case you can't reasonably update), then update the data. i actually do have a bit that adds a “owner” nbt data in the book! it stores the players uuid if that would work? i just didn’t know how i would check if it’s connected to the players capability. in response to the level/world capability, how would i actually do that? im not sure if it’s useful, also eventually wanted to be able to use a command to get a players book even if they’re offline. Quote
Alpvax Posted October 13, 2021 Posted October 13, 2021 18 minutes ago, jayxo said: it stores the players uuid if that would work? Yes, I think that is linked to the player's GameProfile, so should never change. 13 minutes ago, jayxo said: in response to the level/world capability, how would i actually do that? im not sure if it’s useful, also eventually wanted to be able to use a command to get a players book even if they’re offline. The same way you attach the capability to the player, but just attach a capability with a Map<player id, your current player capability data> to the overworld Level instead of attaching the data to the player directly. Then when you want to modify the data, get the capability from the overworld (which is always loaded) and get the data for the player with the given id. Alternatively, you could use Saved Data (which used to be WorldSavedData), again using the overworld to access the player data. That way it doesn't matter if the player is offline, because the data is saved to the overworld, so you just need to look up the data for the player by player id. 1 Quote
jayxo Posted October 14, 2021 Author Posted October 14, 2021 this has actually helped out a lot! I definitely think the best option is using WorldSavedData. On 10/13/2021 at 8:45 AM, Alpvax said: Map<player id, your current player capability data> I've now gotten Map<UUID, *>, but for the players capability data, what kind of information would I put there? Quote
Alpvax Posted October 15, 2021 Posted October 15, 2021 17 hours ago, jayxo said: for the players capability data, what kind of information would I put there? Whatever you used to have attached to each player (only now it doesn't need to be a capability). All the stuff you want to display in the book Quote
jayxo Posted October 15, 2021 Author Posted October 15, 2021 Ohh alright! I've gotten a .dat file to load into a world, but I'm not sure where to go from here. public class StatsManager extends WorldSavedData implements Supplier { public Map<UUID, DefaultStatsCapability> players = new HashMap<>(); public PlayerEntity player = Minecraft.getInstance().player; public StatsManager() { super(XLife.MOD_ID); } public void load(CompoundNBT nbt) { players.put(player.getUUID(), StatsCapabilityProvider.stats); } public CompoundNBT save(CompoundNBT nbt) { ListNBT listNBT = new ListNBT(); for (DefaultStatsCapability stats : players.values()) { stats.save(nbt); listNBT.add(nbt); } nbt.put("Players", listNBT); return nbt; } public static StatsManager onWorld(ServerWorld world) { DimensionSavedDataManager storage = world.getDataStorage(); StatsManager sup = new StatsManager(); StatsManager saver = (StatsManager) storage.computeIfAbsent(sup, XLife.MOD_ID); storage.set(saver); return saver; } public static void onSaved(WorldEvent.Save event) { if (!event.getWorld().isClientSide() && event.getWorld() instanceof ServerWorld) { StatsManager saver = StatsManager.onWorld((ServerWorld) event.getWorld()); saver.setDirty(); } } @Override public Object get() { return this; } } I've used RaidManager as somewhat of a template for this, and the forge forums you linked. Quote
Alpvax Posted October 18, 2021 Posted October 18, 2021 On 10/15/2021 at 3:55 PM, jayxo said: public class StatsManager extends WorldSavedData implements Supplier Why are you implementing Supplier? (Also, you should include the generic type of Supplier). You probably want to add a getter for a specific player. something like the following: public DefaultStatsCapability getStats(UUID playerID) { // Bear in mind this can return null if the player stats have not been added yet. // You might want to use computeIfAbsent instead. return players.get(playerID); } Then wherever you need the DefaultStatsCapability (for example in your book update function), get your instance of StatsManager, then get the DSC from it using the new getter. On 10/15/2021 at 3:55 PM, jayxo said: public PlayerEntity player = Minecraft.getInstance().player; A) This will crash on servers (which is where loading and saving of data occurs) B) What is this for? All the players should be saved in the map. Quote
Recommended Posts
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.