Request: Critical Anti-Grief Plugin Support with Future Client Mods in Mind

This may sound like a giant “duh” to anyone coming from Bukkit, but anyone who’s run a modded server with Bukkit plugins before can tell you that anti-grief is a nightmare when mods are permitted to directly impact the world and players without consulting with other (anti grief) mods/plugins first.

Tekkit was the infamous example - certain parts of Tekkit weren’t calling the provided Bukkit integration API’s for block changes and entity events, which made it impossible for Bukkit plugins to cancel those events based on anti-grief rules. For example, using the “destruction catalyst”, any griefer could walk into a land claim that he was otherwise unable to modify due to not having permissions and instantly wipe the whole thing out with a couple of right clicks. Server owners eventually got wise to this, and their only option was to disable large parts of Tekkit which were known to be problematic.

This was bad for players because server owners on the learning curve left their players open to grief which could not be prevented or rolled back, except by a whole-server rollback based on a world backup, AND some of the coolest toys made available by popular mods were not available to them, much to their disappointments. It was bad for server owners because they had no general anti grief tools to trust - they had to be absolute experts in every mod they installed, and configure them exactly right to avoid a major griefing problem.

So my suggestion is to fire a cancelable event for ALL changes to the world and entities in it, without exception for any plugins/mods (meaning there would be no Sponge API which does not fire the event and respect cancellations before allowing the changes). Otherwise, we’ll be right back in the sinking Tekkit boat again, this time on a wider scale because modding for client will be so much easier.

Some specifics:

Any event should be tied to either a block (e.g. fire spreading from a source fire block to a destination non-fire block), or an entity (tnt or creepers exploding blocks, players placing or breaking blocks). The only exception would be during chunk generation, where we know it’s not grief because no players haven’t had an opportunity to influence the event. Even natural events can be modeled this way - blocks added by tree growth can be tied to the sapling that rooted the tree, apples growing on a tree can be blamed on the leaf block above the new apple. Blame water freezing on adjacent ice blocks, or snowy air above.

By doing this, we can assess whether the event should be allowed to happen based on the source entity/block - a tree rooted outside a land claim can’t add blocks inside a nearby land claim (it might have been planted by a griefer with intent to change the claim), a creeper can’t destroy claimed blocks unless he’s chasing someone with build permission in the claim, a player can’t shoot some crazy magic ring to wipe out claimed blocks unless he has build permission in the claim, and a player can’t hurt an animal in a land claim with an arrow unless he has permission to kill animals in the land claim.

For example, consider these signatures for block and entity health changes, which include required parameters for WHO or WHAT is responsible for the change:

world.setblocktypeanddata(location, newtype, newdata, sourceBlock)
world.setblocktypeanddata(location, newtype, newdata, sourceEntity)
entity.setHealth(newHealth, sourceBlock)
entity.setHealth(newHealth, sourceEntity)

In the above, sourceBlock and sourceEntity cannot be null, and in the case of block changes, the sourceBlock can’t be the same as the block being changed.

With this somewhat generic information about the source of world changing events in place and a guarantee that they will always be cancellable, it’s possible to implement generic anti grief which will effectively prevent grief no matter which mods or plugins are installed. But it only works if all plugins/mods follow the rule about asking other plugins’ permissions first, and that will only happen if it’s made unavoidable by the API.

Thanks for reading my lengthy post. :smile:

I will be porting GriefPrevention over to Sponge, and it will offer the same amazing preventative anti-grief features it offered to CraftBukkit server owners for Vanilla grief. Whether it can offer the same level of preventative protection for heavily modded Sponge servers will depend on whether Sponge implements the API to guarantee these events are cancellable and enough metadata is available to make informed decisions about potential cancellations.

7 Likes

Feasibility

Changing the set block signatures is going to anger a lot of people. It would also mean that we would have to basically rewrite a huge portion of vanilla.

If we simply add a new method, it would not have a universal effect and existing Forge mods that aren’t using Sponge’s API would not provide this information. In addition, any Sponge plugin can just bypass the API and use the original methods.

I can’t really see being able to convince everyone to get on board.

Theoretical Implementation

The best way to handle permission is to use the concept of a “Cause.”

Both WorldGuard and Spout implement the concept of “Cause.” WorldGuard, however, has to build it on top of Bukkit’s API though, which is fairly inconsistent.

Causes in both WG and Spout:

  • Can apply to more than just players: they can be applied to entities, blocks, and other things
  • Causes can be chained. For example, when you drop a piece of sand above a protected region in WG, it builds the casual change of “block places entity -> entity places block” with the root cause being the original block.

For example, due to the unification of causes, the following code in WG protects a region from everything (sand dropping, TNT, players placing blocks, entities placing blocks, blocks placing blocks, water flow, lava flow):

@EventHandler
public void onBreakBlock(final BreakBlockEvent event) {
    final RegionQuery query = getPlugin().getRegionContainer().createQuery();
    final RegionAssociable associable = createRegionAssociable(event.getCause());

    event.filter(new Predicate<Location>() {
        @Override
        public boolean apply(Location target) {
            return query.testBuild(target, associable);
        }
    });
}

100% generic code for complete protection of everything that sends events (which is the other issue).

3 Likes

The implementation isn’t so important to me - the signatures above were just an example to illustrate my idea. What I’m asking for from the Sponge API is this:

  1. If mods/plugins make potentially griefy changes like block changes and entity damage, a cancellable event will ALWAYS be fired first.

  2. That event will include some causal information (even just one level of causality is enough in my opinion, but a chain is bonus points).

Do you think this is a reasonable expectation for the platform, or will some plugins/mods become accidental griefing tools because their authors don’t adhere to recommended guidelines?

Thanks for replying. When I saw you were on the project, I was very happy because I knew you’d advocate for good anti-grief support in the platform.

1 Like

This was a huge issue with Prism on Cauldron. Blood and I worked together to do the best we could, but there were always mods making changes that Cauldron didn’t fire events for, and Prism was oblivious to them. Users had no way to see a record of a change, let alone roll it back.

Accessing an inventory was also difficult. Users could login to an M.E. system and take items without Prism being able to track it.

I’m keeping a close eye on the dev of Sponge (even contributing a bit) so that I can tailor Prism appropriately.

1 Like

Thanks for the backup! I think this is extremely important - with the planned support for client mods in Sponge, I worry that there will be a huge swell of new ways of griefing that don’t fire cancellable events. :smile:

I would totally agree with you. However…

As a programmer I do know some of the technicalities of such a task.

  1. To add events to mods that don’t already support such things will require editing almost all of minecrafts code for anything relating to such events.

  2. For things that add custom inventories like M.E. it makes it even harder to add events to.
    This is due to the fact its not actually extending some kind of Object a chest would use. However I do not know its inner workings this is only an example.

  3. This would be harder to keep up to date on forge’s end. As most of this kind of change would be required at forge’s level I would think. #Sponge is only an abstraction layer in a sense.

@sk89q and the other dev’s should be able to figure out something. I just don’t think its gonna be easy to force a mod to cancel their actions in events. At least not in a straight forward way.

As I previously mentioned,

  1. The only way you can really guarantee that most people would provide this data is to not even let them call setBlock() without a cause.
  2. However, removal of the cause-less setBlock() method would:
  3. Not fly with a lot of existing mods and plugins.
  4. Break MC vanilla unless we rewrite pretty much all of MC.

Would be possible to add such a method, not as a replacement but as a “best practice”? I’d much rather have a consistent method like this for everyone to share than for the burden to catching everything to be on the logging or region-protection developers. If a mod isn’t using this new method, we can feel less guilty/burdened about the events not being tracked.

Not intersecting with some code thingy, but as a server owner EVERYONE using mods of some kind want to be able to prevent grief & if that can’t happen, then use mods? I am just saying doesn’t matter how just as long as plugins like GP can actually prevent grief including mods.
Just my two cents on the subject.

How about add that method but keep old one with a default value of UNKNOWN cause.

Only thing left in that problem though would be vanilla…

This would fix only the plugin/mod part.

It won’t fix fact that we have to edit vanilla further…

Aaaaand please do make UNKNOWN and the method without a cause deprecated, so everyone who makes a plugin is immediately seeing that this is not the greatest way to do it :wink:

Sounds like bad news. Plugin authors can’t be trusted to do the right thing - they’ll overlook the requirement to fire cancelable events and identify cause for changes, even if it’s just by accident. Then server owners are on the hook to become complete experts in every mod they install, and never install the mods that griefers can use as tools. And then they’ll complain to anti-grief plugin authors, not understanding it’s out of our hands because we don’t get a chance to deny the changes.

Would it be possible to keep the original method intact but change visibility to make it unavailable to plugin authors, leaving only the wrapper with cause requirement and automatic event firing visible to Sponge plugins? Sure some will complain because they have to do more updates to their Bukkit plugin code when they’re doing porting work, but if this is done early, then no Sponge plugin code will break because it hasn’t been written, yet.

2 Likes

I do agree with the problems with authors being able to make some MISTAKES but the fact is. It is really their problem. If server owners have trouble with this. They simply should not use it. It is not sponge’s responsibility to enforce this sadly. Do we really have the right to break everyone’s server with stuff like this?

I think deprecating an existing method and making it use a default Unknown cause would be best.
If mods interact with stuff directly without such methods. They should hook into the api on their own. We should not be allowed to force our stuff into people’s faces. Hints gregtech although its pretty much loved and hated depending on where you go


I am not pointing at Gregtech. I am only using it as an example of a mod that forces stuff down other mods throats. However it is possible to disable such features but they are enabled by default to be exact.

The server owners won’t know their server has a griefing opportunity until they experience a griefing problem. Then, they won’t know right away what exactly the griefer did to circumvent anti-grief in many cases, and that means they don’t know which plugin to blame. Only after much investigation can a server owner determine which plugin is to blame, and now can he uninstall it? What if it added new blocks types to the world? What if players have items added by that plugin?

And each server owner has to go through this process for each plugin. Basically, no server owner could install any mod without worrying that it will lead to him having to wipe his server, supersizing the griefer’s localized work to an entire server wipe. That used to be the joke about Tekkit - “So, I set up this cool Tekkit server. A week later, I had to wipe it.”

1 Like

Maybe the community can write some sort of validation tool that tests a security plugin for such things. Perform activity X, check that event Y fired - that type of thing.

1 Like

That might work, it sounds like it could work.

Keeping a list of mods that are approved to work with Anti-Grief plugins would be nice. Have the mod authors submit their mod to the list so that way we can keep up a list of Mods which are compatible, as well as give some visibility to the mods.

I don’t like it, too expensive. Who’s going to do all the testing? And if anything is missed, the value of the whole list will come into question. Even if it works, imagine finding the time to test every version of every mod submitted to the list.

And the testing would have to be manual - a tool would only effectively test if the mod under test fired all the right events, which is the root of the problem in the first place.

I would really like to have my server grief free. Atleast spawn area.

99.9% server owners will agree.

Community need this.

But developers don’t. The API is for devs to make things like Anti-Grief happen.