-
-
Notifications
You must be signed in to change notification settings - Fork 340
Remove the CommandSource in favour of Causes. #2004
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
Conversation
* Split out notion of a console to the Game object, which is a MessageReceiver & Subject. * Server -> Subject and MessageReceiver? * Make sure JDs are consistent with causes, remove anything to do with CommandSources * Not quite removing CSs yet, but in a position to do so.
|
I vote for the first option of selecting the first
For a while I was really adamant against replacing |
See #2004 (comment) * Remove this. qualifiers on methods.
2353db4 to
d9d9cd7
Compare
src/main/java/org/spongepowered/api/util/NamedIdentifiable.java
Outdated
Show resolved
Hide resolved
f4f9eb5 to
e50aa09
Compare
|
I might be misunderstanding how this will work, but I see a few problems with simply selecting the first Say that a player steps on a pressure plate that triggers a command block. I'm assuming the player would be earlier in the cause (because the pressure plate processing occurs before the command block processing).
On the other hand, selecting the last one would also break in some cases. Take Is there something I'm missing here? |
|
Remember causes are last in, first out.
No, the first
This is the tricky part. The original solution was to use the
In this case, there would be a specialist Now, this is why I want to use event contexts as part of our command structure! The player isn't a direct cause, and so this is part of the event context - but if we do that, plugin developers aren't going to want to check the context before the cause each time. As I write this, I wonder if we'd be better served by creating a Of worthy note, if we were to retain |
So, if I'm understanding this correctly, a I understand the challenges in that, though. It is tempting to just grab the first
One of the developers on a project I work on currently does this using delegation, and, it almost works, but, Vanilla commands deal with |
I think you're assuming that command consumers will always have a Effectively, I'm proposing that this line:
becomes CommandResult process(CommandCause cause, String arguments) throws CommandException; where As for vanilla commands, yes, I'll keep this in mind. |
|
I was just writing a reply after I remembered that |
This comment has been minimized.
This comment has been minimized.
322099d to
c720eab
Compare
This comment has been minimized.
This comment has been minimized.
|
+1 for the CommandCause idea. One of the primary failings of a map-and-key system is that what there is supposed to be is not immediately clear; which ones are optional in a particular context vs which ones are just never present in that context, for example. EventContextKeys should still be accepted in that cause, but a wrapper API guaranteeing things like location of execution, dimension of execution, alignment, rotation, executor, original executor, should have dedicated methods in some kind of wrapper class, that don't return Optional, as guarantees that these things always exist. Especially because these things are only used in commands and nowhere else, and context keys used lots of other places won't be used here. |
|
Soon:tm: sponge will be the plugin api that can detect the malicious plugin that called "player.setOp" :laughing: Note for implementation: While most parts of minecraft can be simulated by the vm stack, the command functions are stored in an external stack and their cause, etc. needs to be handled delicately. |
c09d9f8 to
1584092
Compare
|
Any more comments? I'm going to merge this soon otherwise (and fix a couple of javadocs that have TODOs on them). |
|
We have the location but not the rotation of the command. Maybe change the Location to a Transform? |
|
How does that work if a block is the focus of the command? |
|
It would face the direction the block is facing (since command blocks are directional). Or maybe it'd be a rotation of zero if it's a nondirectional block, I don't know. But commands can have relative rotations to the execution targets, so a. it's gotta be in there and b. vanilla knows what to do. |
|
Making sure that all quantities in vanilla |
And this is why it shouldn’t be a I do have to point out that this is all driven by the I am not saying I’m against adding the rotation, but do remember that the Plugins are allowed to think for themselves too! |
|
Right. The point of a CommandCause is to provide stuff that's guaranteed to be relevant. |
Where did I say that? Also what determines what is relevant? The Very much like how events don't have any particular guarantees, we've made that the case with commands too by making it use the Quite simply, the point of the The |
|
Exactly. And the event has a rotation associated with it. |
|
Okay. I don't really think you're getting this point of this entire command system here and you are fixated on one point that I've not even rejected. Commands in Sponge can be summed up like this: Commands using the Sponge system are different to those using the Vanilla system. By using the Cause system we, in effect, state that our commands have a different set of criteria upon execution - which is entirely our right to do. Originally, after much discussion with @Zidane, I was just going to provide the We make no guarantees about anything, because Sponge commands have no guarantees about how they are executed. Now, if someone uses the Should Of course, as a quasi-event, I'd be following what #1975 does. |
03b4145 to
9382db0
Compare
b63af90 to
9a87288
Compare
c8db922 to
217a5fe
Compare
* Split out notion of a console to the Game object, which is a MessageReceiver & Subject named SystemSubject * Make sure JDs are consistent with causes, remove anything to do with CommandSources * Renamed Nameable -> Nameable.Translatable. * Most objects now inherit Subject, MessageReceiver and Nameable. * Introduce the notion of the CommandCause, which is effectively a wrapper class that provides simple methods to get common entities from the cause. It is also a superinterface of CommandContext. * Add ExecuteCommandEvent. * Update for the use of factories to remove any unchecked warnings. * Update for CheckerFramework.
217a5fe to
7dd9f3f
Compare
This is marked as a Draft PR so that the extent of the changes I'm proposing can be seen. It is intended as a way to foster discussion on a specific point that previous PRs could not.
We are investigating how best to utilise the Cause system in our Command framework - the code in this PR is the purest option - but hear me out as I explain what we're really looking at. This is long, but please read all of it before passing comment because I'm more interested in reaching convergence of ideas rather than a "I don't like this, put it back how it was."
A recap of
Causes (and why we all should love them!)The SpongeAPI and its implementation is a system driven by
Causes. They have primarily been used in events, though they have crept into data registration and other uses where we determine which plugin is doing what. It is a powerful tool in the plugin developer's toolkit, enabling not only the determination of redstone being caused by redstone, but being able to track the player who spawned the sheep who aimlessly walked onto a pressure plate turning on redstone wire and causing an explosion, or opening a door, or firing a command block......except actually, we don't fully expose the cause to commands (we could get the cause from the CSM, but that's a live snapshot and not the cause at the specific time a command was sent). So, we are setting out to remedy this. If a player fires a command block because they stood on a pressure plate, we want to be able to directly tell a command consumer "hey, this player was the one who set your command off on this command block. Maybe you want to target them?"
This could be really handy for game servers who use command blocks or signs to trigger events, but want the context of who triggered it, rather than who is nearby. So, we have been talking a lot internally (and in previous command PRs), but I wanted to really get opnions on this point, rather than as part of a big API PR because this is rather important.
Causing those Commands
The basic idea is that you could check the
Causefor what's going on. The root might be a sign, but you can the scan the cause and find aPlayerwho clicked on the sign. That sign could be aSubject, so permission checks are performed on that sign - but the player is the firstMessageReceiver- so you send the messages to them! Similarly, you might have a command block executed by a sheep on a pressure plate - but you want to execute the command on a player only. So, no problem, let's just find the firstEntityon the stack and just not execute if it's a player. By opening causes to the command system, commands can take advantage of this rich, contextual system we already have and make Sponge an even better system to develop commands against.Even better, we could expose our Event filters to Commands, so we can reduce the amount of boilerplate you write - want to have a command that only executes if the root of the command is a
Player? Perhaps two different logic paths if you have a rootPlayeror a rootConsole? While this is a little later down the line -Causes will really enable all this, allowing command executors to get the same treatments as events (though specialised).Removing those Sources?
Of course, that shouldn't all be too contriversial... but you may have been alarmed by the title of this PR. Yes, we are considering the removal of
CommandSources in the API. The simple reason is, the cause already tells you the source of the command - particularly the root of the cause. TheCommandSourceis in API 7 a collection of the following:Subject- an object that permissions can be attached to;MessageReceiver- an object that can receiveTextmessages;getLocale()method (moved toMessageReceiverin API 8 as that is a more logical place for itgetName()method for identifying this source as aString- this has been moved toNamedIdentifiable(but that name sucks IMO and could do with a better one if this goes ahead)So, in most cases, these interfaces will simply replace the
CommandSourceand the various sub sources that existed prior to this. However, there are some sub sources that have already disappeared:ProxySource: this is a source that wraps around a source to intercept permission checks etc. A common use for it should be to front a player when executing a command from a different source, such as a Discord bot. In future, the Discord bot plugin should already be in the cause, but can push aPlayerto the cause prior to execution (or the player an then some other proxySubjectif they want to control permission checks, for example).RemoteSourcedidn't belong - the command system in itself shouldn't care if a command executor is remote.RconSourceis now anRconConnectionin the appropriate packageSignSourceis now just theSignthat would be pushed to theCause, and would be aSubjectonly.CommandBlockSourcesimilarly is just theCommandBlockandMinecartCommandBlockCause and Effect (on Plugin Developers)
You may see a problem here - plugin developers will still likely want to get a traditional command source out of the cause - such that they get an easy object to obtain the console or the player out of. So, we might want to consider a
CommandTargetinterface that can be used to group theConsole,RconandPlayers together - or more precisely, interfaces that indicate objects that would operate with commands more interactively and would normally be the recipient of messages. Of course, command blocks would probably have to be in that category too as the output of command are important to them.We also have to think about how Sponge managed components (parameters etc.) handle the cause for permissions and messages, but I was likely to go with first
Subjectand firstMessageReceiver(there are currently overrides in the Context, but I fear they would be ignored and we are better just focusing on the directCause).There is the potential to be more confusing - but with good documentation and established standards we can absolutely make the
Causethe newCommandSource. We just need to make sure we do this right so it works for everyone.Sourcing those Opinions!
So, the question is, do we:
CommandSources like this and document that permission checks should be performed on the firstSubject, similarly, messages should go to the firstMessageReceiver?CommandTargetmarker interface that performs a "quasi-CommandSource" like job, but this rename indicating that command sources are no longer actual sources (that's the root of theCausenow!)CommandSources the ultimate root of an object (this is closest to what Mojang does but we don't necessarily need to follow that for Sponge plugins)Open for discussion, but as always, please keep it civil and please give reasoning. Note that we will likely go somewhere between the first two points as it stands.
Just on the note of the
Consoleobject appearing, it's there simply because I'd completely forgotten that I'd started working on it until most of the way through this PR. Note that theServerandConsoleobjects are bothSubjects to account for the possibility that (as said elsewhere) one console could support multiple servers and so someone, somewhere, might have different permissions per server... but that could also be too complex for the API. That, however, will likely go into api-8 sooner, once @Zidane, @Cybermaxke and I have settled on this (though I doubt we're far off that).