[Solved] How to save the player's inventory at death in HashMap and load it at respawn?

No, you can’t. Minecraft server code runs on one thread, and will either throw an exception, or worse, break silently, when you try to call most API methods from another thread. Never, never, never, never, never call any thread management code on the main server thread or run API methods that are not explicitly designated thread safe on a side thread. If you wish to wait some period of time before continuing execution of your code, use a Task.

Meanwhile, the gamerule just invokes processing that you can do yourself. Save the items when they die, and restore them when they respawn. Some people have been saying that it works even if you give them the items immediately, before they respawn - have you tried that yet?

1 Like

Really? I disagree because this code works and the suspension occurs in the child process with one single task, the work of which can be performed asynchronously.

new Thread(() -> {
try {
Thread.sleep(10L);
} catch(InterruptedException ie) {
}
world.getProperties().setGameRule(“keepInventory”, “false”);
}).start();

I tried to use the Sponge task manager, but nothing happened.
It is not enough to cancel the loss of things from the inventory at the player’s death, during the activation of the event the player is respawn, his inventory is cleaned by default.
I agree that this method is not ideal and it has drawbacks, but at the moment it is the only thing that has worked for me since I need it.

Please post code. The task manager should always work, so you must be using it incorrectly.

Then save the inventory and give it back to them after respawning.

It is broken and hacky, and is not in any way guaranteed to work. WorldProperties may work from a separate thread in a controlled test environment, but like I said, it can easily break internal expectations and mangle things silently - it working once and it being safe are not the same thing. In this case, it could very well corrupt level.dat if it’s being written to, for example. There are only a couple of APIs that are usable from multiple threads, and they are clearly marked as such.

This not work. Other methods to run this task also do not work.

	Scheduler scheduler = Sponge.getScheduler();
	Task.Builder taskBuilder = scheduler.createTaskBuilder();
       /* Other Code */
            taskBuilder.delay(10, TimeUnit.MILLISECONDS).execute(new Runnable() {
	    	    public void run() {
	    	    	world.getProperties().setGameRule("keepInventory", "false");
	    	    }
	    	});

Look at the beginning of the topic, where I asked how to save the inventory in HashMap. This option would have been much better, but no matter how I tried to implement it did not work out.

I create in the main thread a new child thread, of which one operation is performed, then the child thread terminates. Similar ways of working with the world I met in plug-ins on Bukkit.

Strange, I already tried this method and it did not work, and now it works. In this case, I can also run it from a separate thread, so as not to create unnecessary tasks on the main thread.

Sponge.getServer().equals(Task.builder().execute(() -> world.getProperties().setGameRule(“keepInventory”, “false”))
.delay(100, TimeUnit.MILLISECONDS)
.submit(this));

You didn’t have the thread context earlier in the discussion topic! How were we to know you were spawning a new thread. on top of that, you can’t call API methods that arn’t explicitly designated as threadsafe or without doing research.

Creating tasks on the main thread is the only way to ensure that you are calling the methods from the right thread context. Also, the code you have here is good (at least as far as Sponge cares about threading)

But earlier you never seemed to be actually submitting the Task you made.

Also : Планировщик — Документация Sponge 4.1.0 Is from API 4.1.0 Which is a really old API version, the docs could be a little better, but you should probably be using a newer version.

Документация Sponge — документация Sponge 7.2.0 is the latest, otherwise @Minecrell has just added the 7.0 WIP docs, so versions 5.1 and 6 should appear if you need those.

I blanked and missed an obvious error. you don’t need the .equals

Sponge.getScheduler()
                .createTaskBuilder()
                .execute(
                        () -> world.getProperties().setGameRule("keepInventory", "false")
                ).delay(100, TimeUnit.MILLISECONDS)
                .submit(this);

I use API 7 on my server and I’m writing a plugin for it. I do not have the task of combining the plugin with the old API.
Personally, my opinion on this method of saving the inventory. This is not the best solution, because with it the switching of rules can occur untimely. In this case, either the player with the privilege will lose his items, or the items will be kept by the regular player.
A much better solution would be to use HashMap or something similar.

Then use one. You say it “doesn’t work”. How are we supposed to know what you mean by that? You put the items in a map, you take them out later.
Honestly, if you are trying to use .equals() as an assignment operator, then I would recommend you go over the Oracle Java Tutorials. Using complex stuff like threading or Sponge before understanding the very basics is quite dangerous.
Lastly, what I am trying to get across here is that if WorldProperties is written to from multiple threads, level.dat could get corrupted. Use Task, and this time add a submit() call to the end of the builder.

I agree that I have little experience in writing code. Today another person with a higher level of knowledge took up writing this function, but he also does not manage to write the necessary code.

At the moment, you can save items only by changing the game rule. The code that I used is working fine, but with high online can give bugs.

No. Do not use any part of the API that is not explicitly marked thread safe on any thread other than the main one. I am trying, and apparently failing, to inform you that you could very easily corrupt one of your world files.
Run the builder code on the main thread, and submit it on the main thread, and do not add an async() call to it. You are not creating an ‘unnecessary’ task if it contains a single method call; background threads should only be used for heavy and complex processing (and should resynchronize when it needs to call into Sponge).

Heck, you barely even need that for what I’m talking about - simply read the documentation. In Eclipse, hover over a method to read its documentation; in IntelliJ, click it and push Ctrl Q.

.equals(): Indicates whether some other object is “equal to” this one.

The equals() method does not change anything, or cause anything to happen, or do anything at all. What it does is test if the object you are calling equals() on is equal to the object you are passing as an argument, and return true or false respectively. This is possibly the most basic part of the object system and one of the first things you learn.

That’s exactly what I did. From the background thread, I direct the operation to the main thread, while the execution delay works as I need.

Now this is understandable to me.