CloudNetService / CloudNet

A modern application that can dynamically and easily deliver Minecraft oriented software
https://cloudnetservice.eu
Apache License 2.0
373 stars 116 forks source link

CloudNet v4: API User-Documentation/Examples #1287

Open DasBabyPixel opened 1 year ago

DasBabyPixel commented 1 year ago

Describe the new feature

Add a dedicated examples project like there is in v3. It'd be a great help to have different examples on how to use the new dependency injection and how to find the classes you need, now that we do not have a central Driver that has all the methods.

Why do you need this feature?

It is a great help to all developers trying to migrate to v4

Alternatives

Open to other suggestions, otherwise no alternatives

Other

No response

Issue uniqueness

derklaro commented 1 year ago

It's planned when the api is considered stable. As there are still some changes planned, it doesn't make much sense to write full guides just to change them again accordingly. I will keep this open - if someone has suggestions or even code examples that we should put into the documentation feel free to post them here 😄

DasBabyPixel commented 1 year ago

Any forecast on how long it is going to take until there is a release?

PC1up commented 1 year ago

API Example of how to add and remove player groups

CloudNetDriver driver = CloudNetDriver.getInstance(); // getting cloudnet driver instance
IPermissionManagement permissionManagement = driver.getPermissionManagement(); // getting permission manager
IPermissionUser user = permissionManagement.getUser(p.getUniqueId()); // getting permission user. make sure to put the proper UUID here
String sampleGroup = "This is a sample group name. You'll probably replace this with some kind of command argument";
IPermissionGroup permissionGroup = permissionManagement.getGroup(sampleGroup); // getting permission group from group name
// if you're absolutely sure the group exists, you can skip this. Group names are case sensitive!
if(permissionGroup == null){
    // group does not exist. might wanna add some kind of error message
    return;
}
if(user.getGroupNames().contains(sampleGroup)){
    // player already has group so (for the sake of creating an example) we're removing it
    user.removeGroup(sampleGroup);
    permissionManagement.updateUser(user); // dont forget to update the user
}else{
    // player doesnt have group so we're adding it
    user.addGroup(sampleGroup);
    permissionManagement.updateUser(user); // dont forget to update the user
}

Not sure if this is 100% the correct way, but it works so feel free to use it

DasBabyPixel commented 1 year ago

This thread is about examples for CloudNet 4. Anyone looking for examples for CloudNet 3 can find them here. (There are also "official" examples for the permission system, but thanks for trying to provide examples 👍 )

As far as I know the cloud permission system is going to be removed. Anyone actively using it might want to migrate to luckperms

CN-Dragon commented 5 months ago

I have not used dependency injection before, and I hope to provide an example as soon as possible

DasBabyPixel commented 5 months ago

A quick summary for most use cases: If you want to develop a CN-Module, you can acquire object instances in the methods annotated with @ModuleTask. If you want to develop a server plugin that uses CN api, see examples later in this post This gives you access to pretty much everything that used to be in CloudNetDriver

@ModuleTask(lifecycle = ModuleLifeCycle.STARTED)
public void start(@Name("module") InjectionLayer<SpecifiedInjector> injectionLayer, ComponentInfo componentInfo, DatabaseProvider databaseProvider) {
}

You can add as many parameters as you need. The first parameter in this example is the InjectionLayer for the module. (Parameter can also be omitted if not required) This InjectionLayer is the thing behind the scenes that gets you the instances. If you want an instance and you do not have the option of getting it in a @ModuleTask method, you can use the InjectionLayer to do so:

DatabaseProvider databaseProvider = injectionLayer.instance(DatabaseProvider.class)

The InjectionLayer with @Name("module") is an InjectionLayer specifically for YOUR module. It inherits from the default CN InjectionLayers (ext). These default InjectionLayers are InjectionLayer.ext() and InjectionLayer.boot(). ext inherits from boot and is meant for extension use cases. Because ext inherits from boot, the InjectionLayer of your module implicitly inherits from boot. (module < ext < boot) All the object instances you usually need are installed in boot. If you want access from a server plugin (and not a CN-module), you can use these InjectionLayers to get instances: InjectionLayer.boot().instance(DatabaseProvider.class)

Services I have used so far

The PlayerManager is bridge specific and thus hidden behind the ServicesRegistry: Example for use inside bukkit plugin:

private final PlayerManager playerManager = InjectionLayer.boot().instance(ServiceRegistry.class).firstProvider(PlayerManager.class);

Little more advanced You can install custom Bindings (basically object instances/object instance suppliers) into any InjectionLayer. This can be done by using

injectionLayer.install(BindingBuilder.create().bind(ProviderInterface.class).toInstance(new ProviderImplementation()))

You can also inject object instances in constructors, to understand how that works I recommend taking a closer look at existing CloudNet modules like bridge, which are good examples of recommended usage. These modules take it a step further and do not constructors, they instead let the DI framework construct all the objects. They only say: "Hey, gimme an instance of XYZ".

If you need more information on DI, I can recommend the jakarta specs and the Aerogel github README JSR 330 is also an option, but IMO thats the worse documentation

This should pretty much cover all basic usage.

@derklaro correct me if I'm wrong about anything here pls

CN-Dragon commented 5 months ago

very think @

A quick summary for most use cases: If you want to develop a CN-Module, you can acquire object instances in the methods annotated with @ModuleTask. If you want to develop a server plugin that uses CN api, see examples later in this post This gives you access to pretty much everything that used to be in CloudNetDriver

@ModuleTask(lifecycle = ModuleLifeCycle.STARTED)
public void start(@Name("module") InjectionLayer<SpecifiedInjector> injectionLayer, ComponentInfo componentInfo, DatabaseProvider databaseProvider) {
}

You can add as many parameters as you need. The first parameter in this example is the InjectionLayer for the module. (Parameter can also be omitted if not required) This InjectionLayer is the thing behind the scenes that gets you the instances. If you want an instance and you do not have the option of getting it in a @ModuleTask method, you can use the InjectionLayer to do so:

DatabaseProvider databaseProvider = injectionLayer.instance(DatabaseProvider.class)

The InjectionLayer with @name("module") is an InjectionLayer specifically for YOUR module. It inherits from the default CN InjectionLayers (). These default InjectionLayers are and . inherits from and is meant for extension use cases. Because inherits from , the InjectionLayer of your module implicitly inherits from . ( < < ) All the object instances you usually need are installed in . If you want access from a server plugin (and not a CN-module), you can use these InjectionLayers to get instances:ext``InjectionLayer.ext()``InjectionLayer.boot()``ext``boot``ext``boot``boot``module``ext``boot``boot InjectionLayer.boot().instance(DatabaseProvider.class)

Services I have used so far

  • ServiceInfoHolder
  • EventManager
  • DatabaseProvider
  • ComponentInfo
  • ServiceTaskProvider
  • TemplateStorageProvider
  • GroupConfigurationProvider
  • ServiceRegistry
  • BridgeServiceHelper

The PlayerManager is specific and thus hidden behind the ServicesRegistry: Example for use inside bukkit plugin:bridge

private final PlayerManager playerManager = InjectionLayer.boot().instance(ServiceRegistry.class).firstProvider(PlayerManager.class);

Little more advanced You can install custom Bindings (basically object instances/object instance suppliers) into any InjectionLayer. This can be done by using

injectionLayer.install(BindingBuilder.create().bind(ProviderInterface.class).toInstance(new ProviderImplementation()))

You can also inject object instances in constructors, to understand how that works I recommend taking a closer look at existing CloudNet modules like , which are good examples of recommended usage. These modules take it a step further and do not constructors, they instead let the DI framework construct all the objects. They only say: "Hey, gimme an instance of XYZ".bridge

If you need more information on DI, I can recommend the jakarta specs and the Aerogel github README JSR 330 is also an option, but IMO thats the worse documentation

This should pretty much cover all basic usage.

@derklaro correct me if I'm wrong about anything here pls

very think u !!!!!!