Prevent gaining advancements in specific worlds

Discussion in 'Plugin Requests' started by adamk523, Jun 26, 2019.

  1. Offline

    adamk523

    Minecraft version: 1.12.2 and above (Paper)

    Suggested name: PerWorldAdvancements

    What I want: Our server has a creative plotworld that you can teleport to, and we also have lots of custom advancements to unlock. Unfortunately players can unlock any advancement in any world, including in the creative mode world!

    At the minimum, a config file where the admin can define worlds that do not unlock any advancements even if the criteria are met would be perfect for my needs. Extra features (such as blocking certain advancements, granular permissions, blocking based on gamemode, etc) are gravy, but definitely not required. Just trying to patch a simple exploit here :)

    Ideas for commands and permissions: Other than a reload config command, I don't see any need for any additional commands or perms.

    When I'd like it by: ASAP, so the fewest number of people possible will accidentally or intentionally unlock advancements in creative.
     
  2. Offline

    adamk523

    Anyone who can help? I really need something simple to stop people from grinding every achievement in the game while in the creative mode plotworld.
     
  3. Offline

    Zombie_Striker

    @adamk523
    Its not specifically for advancements, but my plugin LobbyAPI allows for advancements to be unlocked per world. With it, you should be able to register the different worlds and allow the advancements to be locked for each world.
    https://dev.bukkit.org/projects/lobbyapi/files

    (*Note, the advancements will be locked to the last world they are in when they join. If they have joined the server in the creative world, the advancements will only be applied to the creative world and will be cleared for the survival world, and visa versa.)
     
  4. Offline

    adamk523

    @Zombie_Striker Sorry about the late reply, got hired for a new job so server admin stuff naturally had to wait!

    I appreciate the tip, but I'm not a Java developer. ._. Hence my post in the "plugin requests" forum. Ideally I just want to prevent players from gaining advancements in certain config-defined worlds, so something simple will work just as well.

    I also don't quite understand the specifics of your note either, do you mean that a player would have to relog if they joined the server in the creative world and wanted to unlock advancements in the survival world?
     
  5. Offline

    Machine Maker

    @adamk523 If you can't get his LobbyAPI doing what you want, I can throw this together real fast, just let me know.

    If you decide you need this:
    So just to confirm, you want to be able to configure a list of worlds where, even if the criteria are met, the advancement is not marked as completed.

    And furthermore, you want to be able to block certain advancements in specific worlds.
     
  6. Offline

    adamk523

    @X1machinemaker1X Thank you so much!! :) That's exactly what I'm looking for; just a simple fix to stop people from cheating 80% of the game's achievements in creative mode. A config with a list of worlds where no advancements will be gained is plenty useful for now and I'll be more than happy with only that feature, but the ability to block certain advancements would be very handy to have as well in a future version. Also it's got to be 1.12+ compatible since we're still on 1.12.2, just as a reminder.

    If it's not too much hassle throwing the source up on Github as well, I'd love to see how you did it. Just starting to get my feet wet with basic Java and plugin development after 8+ years of server administration, and studying simple plugins is how I learn best. :D Thanks again for taking this on, I think it will be of use to any server admin who wants to implement separate creative and survival worlds on the same server!
     
  7. Offline

    Machine Maker

    Cool, I'll get started on this later today.
     
  8. Offline

    Machine Maker

    @adamk523 So it was a little more complex than I originally though. Here is the first version. Now it may seem that they are actually getting the advancement because it will appear in chat, but they don't actually. And you can disable the annouceAdvancements gamerule if you are using multiverse (/mvrule annouceAdvancements false).

    I'm guessing there is a way for me to stop that packet from getting sent, but I am not sure what it is yet. I will keep digging around.
     
  9. Offline

    adamk523

    @X1machinemaker1X Thank you again for your help, unfortunately the test went just as I feared it would. When an advancement condition is fulfilled, extreme chat spam and intense server-crashing lag happens as the plugin attempts to cancel the Advancement Get every tick. You're right, this is tougher than I thought too :eek:
     
  10. Offline

    Machine Maker

    What do you mean by chat-spam? I just got the one message in chat that the advancement was completed. and I didn't see any thing in the console?
     
  11. Offline

    adamk523

    @X1machinemaker1X What happens (correct me if I'm wrong) is that the plugin listens for an "onAdvancementGet" event, checks whether the player is in a config-defined blacklisted world, and revokes the advancement instantly. The problem with that design is, Mojang's advancement system seems to want to check on every single tick that you've fulfilled an advancement's criteria, so that means the moment the advancement gets taken away from you, it's already added back on by the vanilla game. This battle of giving and taking advancements happens instantly, twenty times a second/as fast as the server can tick, resulting in massive amounts of spam and crippling server lag as long as any advancement's criteria continue to be met. For example, if I'm holding a diamond in a blacklisted world, I get the "DIAMONDS!" advancement momentarily before it's taken away from me, but I immediately earn it back and have it taken... and so on and so forth, creating an endless feedback loop of lag and spam.

    I thought of a possible (but slightly difficult) solution to the problem that would work around Mojang's usual stupidity and would only require processing on world change. You know the plugin "Per World Inventory"? On world change, it checks admin-defined groups of worlds in a config file; world, world_nether, and world_the_end might be one group, while creative_world is in a second group. If you warp to a world outside of the survival group, for example, the plugin saves your current inventory to a flat file, and then loads up a separate inventory from a flat file into the current NBT playerdata.dat file. Basically, inventories are kept separate from certain groups of worlds by using flat file storage.

    If we applied this methodology (if necessary, using some ProtocolLib witchcraft to handle the differing sets of achievements per player), couldn't we check which world a player is in, and if they're in one group of worlds, a certain set of advancements and the player's advancement save data is loaded and sent to the client? Not only would admins be able to disable advancements in certain worlds by creating blank sets of advancements (there's nothing to gain, so there's nothing to revoke anymore), but this would also open up worlds of opportunity for new custom advancements per world, such as a separate set of creative mode advancements, or even a new secret set for secret worlds!

    Hopefully this made sense, looks like the most ideal solution would be tricky since it would require some flat file magic and separate sets of advancements. I think that this could be a genuinely very useful plugin for many servers though! :) Hopefully it's not too much to ask for, but it's the most elegant solution to prevent the constant tug-of-war with giving and revoking advancements that I know of.
     
  12. Offline

    Machine Maker

    See, I think it only checks on inventory updates. (Which isn’t ideal either) I only got the chat message once when I picked up a diamond, then one more time when I picked it up again. So I don’t think it’s checking very tick. That would be wasteful on the games part.


    As for your solution, I will look into it. It’s a good idea.
     
  13. Offline

    adamk523

    @Machine Maker I have a custom achievement that triggers when you step on a certain type of block, so I don't see how it could be only for inventory updates. I don't think it's checking every tick either, but it doesn't seem to waste much time with the checks - as soon as I stepped on the block, the server began suffering crippling lag.

    Thanks!! :) Wish I could help more past the ideas stage, I'm a slow learner with Java's generally overcomplicated syntax.
     
  14. Offline

    Machine Maker

    @adamk523 So looking into advancements a bit more, each world folder has room for custom advancements. I believe you can override the advancements in the minecraft namespace.
    I think if you create a folder in your world/data/advancements named "minecraft" and then sub-folders called story, nether, adventure, husbandry and end. Then in each of those folders create a file called root.json and fill it with
    Code:json
    1.  
    2. {
    3. "parent": "totally not possible",
    4. "criteria": {
    5. "impossible": {
    6. "trigger": "minecraft:impossible"
    7. }
    8. }
    9. }
    10.  


    according to dinnerbone, that *should* remove the advancements from that world.
     

Share This Page