Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "The Crafting Mechanic" example on "Recipes" #155

Merged
merged 2 commits into from
Aug 26, 2024

Conversation

HenryLoenwind
Copy link
Contributor

@HenryLoenwind HenryLoenwind commented Aug 19, 2024

Fixes #154

  • added missing creation of the "recipes" variable
  • fixes logic potentially causing client-server desync by only skipping server-only tasks instead of everything on the client

Preview URL: https://pr-155.neoforged-docs-previews.pages.dev

@sciwhiz12 sciwhiz12 added the incorrect Incorrect information. label Aug 19, 2024
@ChampionAsh5357
Copy link
Contributor

fixes logic potentially causing client-server desync by only skipping server-only tasks instead of everything on the client

Would you mind explaining how the change fixes a client/server desync? You should generally be checking recipes on the server only, along with removing the block and adding the item entity. It would be different if the recipe was being populated to some sort of client menu, but that is not relevant in this case.

@HenryLoenwind
Copy link
Contributor Author

Would you mind explaining how the change fixes a client/server desync?

Sure. Imageine there is a listener from another mod that also listens to UseItemOnBlockEvent and plants a flower. On the server the event gets cancelled, so the flower never is planted. But on the client, the event is delivered to the other handler that put the flower there. Now we have a desync that persists, as the server never cancels the placed flower.

Block changes run on both server and client to reduce lag. Cancelling any code path that may place/change/remove a block on one side only is bad. At most you can cancel it on the client and wait for the server to sync the block action (then it will only feel laggy to the player), or cancel it on the server and send a block update back to the original state. But cancelling something server-side only when you have no way of sending a packet that cancels the action (because you have no idea what may have happened) is not good at all.

Also, cancelling this event cancels the vanilla logic for the right click. What would that have done? And what would the right-click handling for the offhand have done? The player could have a torch in their offhand, on the server nothing would have happened, but on the client that torch would have been placed. Again, without the server having any idea about it or being able to send an update to undo it.

We're very used to code only running on client OR server, but there's plenty of stuff that runs on the client predicting what the server will do. Block updates, entity movement, even day time advancing. Those all are cases where interfering on only one side will either produce desyncs, lag, rubberbanding, or stutter.

@ChampionAsh5357
Copy link
Contributor

Sure. Imageine there is a listener from another mod that also listens to UseItemOnBlockEvent and plants a flower. On the server the event gets cancelled, so the flower never is planted. But on the client, the event is delivered to the other handler that put the flower there. Now we have a desync that persists, as the server never cancels the placed flower.

Ah, I missed that this was called in an event. Thank you for the detailed explanation regardless. Though, if we want to make it better, I suggest to replace the setCanceled with the cancelWithResult and supply the correct interaction result, as if the recipe succeeds, it should probably do a sided success return.

@neoforged-pages-deployments neoforged-pages-deployments bot deployed to neoforged-docs-previews (Preview) August 20, 2024 13:19 Active
@neoforged-pages-deployments
Copy link

neoforged-pages-deployments bot commented Aug 20, 2024

Deploying with Cloudflare Pages

Name Result
Last commit: 8f9462e49019be3ff829d7c4eeb11dffd1d5f408
Status: ✅ Deploy successful!
Preview URL: https://3d4f3795.neoforged-docs-previews.pages.dev
PR Preview URL: https://pr-155.neoforged-docs-previews.pages.dev

@HenryLoenwind
Copy link
Contributor Author

supply the correct interaction result

Sure. Could you take that part? I don't feel secure enough in that part yet...

@ChampionAsh5357
Copy link
Contributor

supply the correct interaction result

Sure. Could you take that part? I don't feel secure enough in that part yet...

It should just be event.cancelWithResult(ItemInteractionResult.sidedSuccess(level.isClientSide)); since the recipe produced a valid output and stops any further interaction from happening. We use the sided success as the action causes a swing on the client and consumes any further steps on the server.

@IchHabeHunger54
Copy link
Member

For context, I would like to mention that I eventually want to make an article all about how the hierarchy surrounding the Level class works - with all the ServerLevel, ClientLevel, LevelAccessor, etc., as well as explaining the relations between levels, worlds, dimensions etc. However, that will have to wait a bit, and this is definitely a good addition regardless of that.

Copy link
Contributor

@ChampionAsh5357 ChampionAsh5357 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Sorry for being late on this.

@neoforged-pages-deployments neoforged-pages-deployments bot deployed to neoforged-docs-previews (Preview) August 26, 2024 01:30 Active
@ChampionAsh5357 ChampionAsh5357 merged commit 1f8e3b3 into neoforged:main Aug 26, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
incorrect Incorrect information.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Recipe use example missing how to get the RecipeManager
4 participants