Add hopper Logic #5869
Conversation
ShockedPlot7560
left a comment
There was a problem hiding this comment.
Logically, if we want to fully implement the hopper logic, the TODOs for the events and the remaining logics would have to be made.
| if($origin instanceof Container){ | ||
| $success = $this->pull($inventory, $origin->getInventory()) || $success; | ||
| }else{ | ||
| $success = $this->pickup($inventory) || $success; |
There was a problem hiding this comment.
To avoid retrieving entities from above when a block is obstructing, it would be interesting to check whether the block above is full, and therefore that no entity can be above it.
There was a problem hiding this comment.
You still have to check whether an item entity is inside that full block:
It is also possible for a hopper to collect items from inside a full, solid block, a situation that might come from items rising up through solid blocks or being summoned. wiki
There was a problem hiding this comment.
This very specific case may not need to be taken into account in pocketmine. It may increase the performance impact of hoppers, when in fact you should just place a full block on top to prevent entities from being checked.
And this is what some java engines use to optimize performance.
There was a problem hiding this comment.
Of course, it's an increased performance impact. Blocking this is basically just disabling a - mostly pretty useless - feature, making PM less-matching with vanilla behaviour.
In the end, it's your decision on what you want to implement into the core. But imo, before removing functionality for performance's sake, there should be taken a look at other, more important hot paths.
There was a problem hiding this comment.
I agree that pocketmine wouldn't exactly follow vanilla's behavior in this situation, but is that so important?
It's something to think about, as the feature is not very useful, but it could greatly improve performance as soon as the number of hoppers becomes too large.
There was a problem hiding this comment.
To me it doesn't seem like a situation that would come up very often anyway, so the performance gain from changing it is likely to be close to zero. I'd classify this as premature optimisation.
There was a problem hiding this comment.
I think @ShockedPlot7560's suggestion was, to skip the entire pickup logic (calling getNearbyEntities(), etc.) if there is a full block above the hopper, or even don't reschedule the hopper if he also has nowhere to push items too.
That should actually help and not just be premature optimization. But as I said, it's not really an optimization, since it removes vanilla behaviour.
| //TODO: Composter | ||
| //TODO: Brewing Stand | ||
| //TODO: Jukebox (improve) | ||
| if($destination instanceof \pocketmine\block\tile\Furnace){ |
There was a problem hiding this comment.
Each push logic should be implemented in the different tiles to allow greater flexibility / addition in the future.
There was a problem hiding this comment.
Better implement it in the block classes (maybe identifiable with an HopperInteractable interface), not just to remove the dependence on tiles, but also don't force yourself only to allow the implementation of hopper logic for tiles: There could be blocks, that hoppers can interact with, without them being a tile. (I don't know the Bedrock internals well enough, so I don't know if composters would also need a tile. But if not, they would be a counterexample.)
There was a problem hiding this comment.
That's indirectly what I was explaining, but you did it better than I did. I mentioned tile because that's what was checked, but implementing it in blocks seems much more coherent.
| //TODO: Composter | ||
| //TODO: Brewing Stand | ||
| //TODO: Jukebox | ||
| if($origin instanceof FurnaceInventory){ |
There was a problem hiding this comment.
Each pull logic should be implemented in the different tiles to allow greater flexibility / addition in the future.
There was a problem hiding this comment.
Same argument as for the push logic.
| public const DEFAULT_TRANSFER_COOLDOWN = 10; | ||
|
|
||
|
|
||
|
|
There was a problem hiding this comment.
Unnecessary extra spaces.
|
|
||
| public function onScheduledUpdate() : void{ | ||
| //TODO | ||
| $this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1); |
There was a problem hiding this comment.
If the block above is not a container, but a full block, there's no point in ticking the hopper all the time while the transfer is in cooldown for x amount of time if the block below is a container.
In addition, if the hopper has a full block above it but no container in front of it, the tick should not be activated to improve performance.
There was a problem hiding this comment.
As said above, there still could be item entities in that full block.
|
This is a copy pasta of #4416 and none of the issues in the review comments appear to have been addressed. |
I don't seem to remember any non-addressed comments. |
|
|
||
| private const TAG_TRANSFER_COOLDOWN = "TransferCooldown"; | ||
|
|
||
| public const DEFAULT_TRANSFER_COOLDOWN = 10; |
There was a problem hiding this comment.
Where did you get that number from? The original pr contained the correct value:
A hopper waits for 4 redstone ticks = 8 game ticks, according to the wiki
There were some design issues that you said you didn't know how to address, I thought that's why you closed it. Considering my past experience with copy-pasta PRs I don't usually have high hopes for them. |
Not necessarily. I already discussed it here on the pm discord, when @IcyEndymion004 told me he created the pr. |
|
I expect the performance issues had to do with constantly ticking all the hoppers to actively search for nearby items? |
Entities do, and hopper ticking also adds load when ticking to move items (even if it's tiny). |
|
Perhaps this is an area where an area API like the one described in #5799 would be useful. |
It is actually more problematic to have hundreds of hoppers scheduled every tick. Hoppers are not set on cooldown when they couldn't do anything, so even if they are connected to a container above (which means they don't pick up item entities), they will still be scheduled for the next tick, e.g. if the container is empty / the hopper full. |
|
Sounds like a lava/water type problem. |
|
If ticking is correctly implemented, not necessarily. We can use locks to avoid ticking the block unnecessarily:
In the future, if an API is implemented that allows things to be executed when an entity enters an area, hopper ticking may be reduced to nothing if no action is possible. |
|
Any kind of block ticking becomes a problem if you add enough blocks. That's why most servers ban lava, water, fire etc. |
As you can see in the I am not sure if that area system would be a good use for hoppers since you would have to register a separate area for each of them. I'm just theorizing, so it could just be premature optimization, but you could end up having multiple moving item instances checking each tick if they entered any of the 100 hopper areas. (But that depends on how that API is designed. It would probably be less dramatic if you index them a certain way so that you have a reduced loop-up cost.) |
Yeah, I'm aware of the cost. My current thought is to use an octree for this. |
Seems like a decent choice if there is a good way to implement them in php. |
|
I think #5906 is a better active alternative, could we close this one? |
|
This seems like a copy pasta of #4416 anyway, and I've rarely seen a copy pasta by anyone other than the code author be successful, as they lack sufficient understanding of the code to address reviews |
Follow up and update to #4416
(This code is all done by Colin and i dont want credit for it at all just want this added)
This is testing and working!