From 428eea508f549eb360f0b266c43db66e3d135152 Mon Sep 17 00:00:00 2001 From: "niklas.nieberler" Date: Sun, 20 Aug 2023 14:08:58 +0200 Subject: [PATCH] Component support in sendActionBar --- .github/workflows/gradle-build.yml | 73 +++ .gitignore | 79 +++ Jenkinsfile | 58 +++ LICENSE | 21 + README.md | 243 +++++++++ build.gradle | 168 +++++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 26 + gradlew | 191 +++++++ gradlew.bat | 89 ++++ settings.gradle | 63 +++ simplecloud-api/build.gradle | 39 ++ .../kotlin/eu/thesimplecloud/api/CloudAPI.kt | 68 +++ .../kotlin/eu/thesimplecloud/api/ICloudAPI.kt | 144 ++++++ .../api/cachelist/AbstractCacheList.kt | 54 ++ .../api/cachelist/ICacheList.kt | 136 +++++ .../cachelist/ICacheObjectUpdateExecutor.kt | 77 +++ .../api/cachelist/manager/CacheListManager.kt | 41 ++ .../cachelist/manager/ICacheListManager.kt | 41 ++ .../value/AbstractCacheValueUpdater.kt | 42 ++ .../api/cachelist/value/ICacheValue.kt | 43 ++ .../api/cachelist/value/ICacheValueUpdater.kt | 40 ++ .../api/client/NetworkComponentReference.kt | 51 ++ .../api/client/NetworkComponentType.kt | 35 ++ .../api/command/ICommandSender.kt | 64 +++ .../api/config/AbstractJsonLibConfigLoader.kt | 55 +++ .../config/AbstractMultipleConfigLoader.kt | 65 +++ .../api/config/IConfigLoader.kt | 43 ++ .../thesimplecloud/api/config/IFileHandler.kt | 42 ++ .../api/depedency/DependenciesInformation.kt | 28 ++ .../api/directorypaths/DirectoryPaths.kt | 43 ++ .../api/dto/PlayerLoginRequestResult.kt | 34 ++ .../group/CloudServiceGroupCreatedEvent.kt | 35 ++ .../api/event/group/CloudServiceGroupEvent.kt | 34 ++ .../group/CloudServiceGroupUpdatedEvent.kt | 35 ++ .../player/CloudPlayerCommandExecuteEvent.kt | 53 ++ .../player/CloudPlayerDisconnectEvent.kt | 49 ++ .../api/event/player/CloudPlayerEvent.kt | 28 ++ .../api/event/player/CloudPlayerLoginEvent.kt | 49 ++ .../event/player/CloudPlayerMessageEvent.kt | 26 + .../player/CloudPlayerRegisteredEvent.kt | 31 ++ .../player/CloudPlayerServerConnectEvent.kt | 46 ++ .../player/CloudPlayerServerConnectedEvent.kt | 32 ++ .../player/CloudPlayerUnregisteredEvent.kt | 33 ++ .../event/player/CloudPlayerUpdatedEvent.kt | 33 ++ .../CloudPlayerPermissionCheckEvent.kt | 45 ++ .../player/permission/PermissionState.kt | 33 ++ .../service/CloudServiceConnectedEvent.kt | 30 ++ .../api/event/service/CloudServiceEvent.kt | 28 ++ .../service/CloudServiceInvisibleEvent.kt | 30 ++ .../service/CloudServiceRegisteredEvent.kt | 30 ++ .../event/service/CloudServiceStartedEvent.kt | 31 ++ .../service/CloudServiceStartingEvent.kt | 31 ++ .../service/CloudServiceUnregisteredEvent.kt | 30 ++ .../event/service/CloudServiceUpdatedEvent.kt | 30 ++ .../SynchronizedListObjectRemovedEvent.kt | 28 ++ .../SynchronizedListObjectUpdatedEvent.kt | 28 ++ .../sync/object/GlobalPropertyUpdatedEvent.kt | 28 ++ .../api/event/wrapper/WrapperEvent.kt | 28 ++ .../api/event/wrapper/WrapperUpdatedEvent.kt | 28 ++ .../api/eventapi/BasicEventManager.kt | 139 ++++++ .../api/eventapi/CloudEventHandler.kt | 28 ++ .../api/eventapi/ICancellable.kt | 40 ++ .../eu/thesimplecloud/api/eventapi/IEvent.kt | 28 ++ .../api/eventapi/IEventExecutor.kt | 36 ++ .../api/eventapi/IEventManager.kt | 73 +++ .../thesimplecloud/api/eventapi/IListener.kt | 29 ++ .../api/eventapi/ISynchronizedEvent.kt | 29 ++ .../api/eventapi/exception/EventException.kt | 29 ++ .../api/exception/NoSuchPlayerException.kt | 26 + .../api/exception/NoSuchServiceException.kt | 25 + .../api/exception/NoSuchWorldException.kt | 26 + .../api/exception/PlayerConnectException.kt | 29 ++ .../api/exception/SerializationException.kt | 26 + .../UnreachableComponentException.kt | 29 ++ .../api/extension/ClientManagerExtension.kt | 53 ++ .../api/external/ICloudModule.kt | 42 ++ .../api/language/ILanguageManager.kt | 61 +++ .../api/language/LanguageManager.kt | 55 +++ .../api/language/LanguagePlaceholder.kt | 37 ++ .../api/language/LanguageProperty.kt | 59 +++ .../api/language/LoadedLanguageFile.kt | 39 ++ .../api/listenerextension/AdvancedListener.kt | 103 ++++ .../AdvancedListenerExtension.kt | 32 ++ .../listenerextension/IAdvancedListener.kt | 68 +++ .../api/location/GroupLocation.kt | 84 ++++ .../api/location/ServiceLocation.kt | 128 +++++ .../api/location/SimpleLocation.kt | 80 +++ .../api/location/TemplateLocation.kt | 75 +++ .../api/message/IMessageChannel.kt | 65 +++ .../api/message/IMessageChannelManager.kt | 50 ++ .../api/message/IMessageListener.kt | 34 ++ .../eu/thesimplecloud/api/message/Message.kt | 33 ++ .../api/message/MessageChannel.kt | 84 ++++ .../api/message/MessageChannelManager.kt | 91 ++++ .../api/network/component/IAuthenticatable.kt | 39 ++ .../network/component/INetworkComponent.kt | 49 ++ .../api/network/component/ManagerComponent.kt | 50 ++ .../packets/PacketIOExecuteFunction.kt | 51 ++ .../api/network/packets/PacketIOPing.kt | 40 ++ .../packets/event/PacketIOCallEvent.kt | 42 ++ .../packets/language/PacketIOLanguage.kt | 56 +++ .../packets/message/PacketIOChannelMessage.kt | 45 ++ ...acketIOCloudPlayerForceCommandExecution.kt | 47 ++ .../player/PacketIOConnectCloudPlayer.kt | 52 ++ .../player/PacketIOGetAllOnlinePlayers.kt | 36 ++ .../packets/player/PacketIOGetCloudPlayer.kt | 56 +++ .../player/PacketIOGetNetworkOnlineCount.kt | 40 ++ .../player/PacketIOGetOfflinePlayer.kt | 48 ++ .../player/PacketIOGetPlayerLocation.kt | 45 ++ .../packets/player/PacketIOGetPlayerPing.kt | 28 ++ .../PacketIOGetPlayersConnectedToService.kt | 50 ++ .../PacketIOGetRegisteredPlayerCount.kt | 40 ++ .../packets/player/PacketIOKickCloudPlayer.kt | 45 ++ .../player/PacketIOPlayerHasPermission.kt | 45 ++ .../player/PacketIOSaveOfflinePlayer.kt | 46 ++ .../PacketIOSendMessageToCloudPlayer.kt | 54 ++ .../player/PacketIOSendPlayerToLobby.kt | 44 ++ .../player/PacketIOSendTablistToPlayer.kt | 57 +++ .../player/PacketIOSendTitleToCloudPlayer.kt | 62 +++ .../player/PacketIOSetCloudPlayerUpdates.kt | 51 ++ .../packets/player/PacketIOTeleportPlayer.kt | 50 ++ .../packets/screen/PacketIOExecuteCommand.kt | 59 +++ .../packets/service/PacketIOCopyService.kt | 51 ++ .../service/PacketIOStartCloudService.kt | 42 ++ .../service/PacketIOStopCloudService.kt | 44 ++ .../service/PacketIOWrapperStartService.kt | 43 ++ .../PacketIOCloudServiceGroupData.kt | 54 ++ .../PacketIOCreateServiceGroup.kt | 37 ++ .../serviceversion/PacketIOServiceVersions.kt | 50 ++ .../cachelist/PacketIOUpdateCacheObject.kt | 72 +++ .../PacketIOGetAllCachedListProperties.kt | 47 ++ .../sync/list/PacketIORemoveListProperty.kt | 54 ++ .../sync/list/PacketIOUpdateListProperty.kt | 54 ++ .../sync/object/PacketIOGetGlobalProperty.kt | 54 ++ .../object/PacketIORemoveGlobalProperty.kt | 43 ++ .../object/PacketIOUpdateGlobalProperty.kt | 48 ++ .../api/parser/ITypeFromClassParser.kt | 38 ++ .../thesimplecloud/api/parser/ITypeParser.kt | 41 ++ .../parser/jsondata/IJsonDataTypeParser.kt | 29 ++ .../api/parser/jsondata/JsonDataParser.kt | 33 ++ .../api/parser/string/IStringTypeParser.kt | 28 ++ .../api/parser/string/StringParser.kt | 71 +++ .../parser/string/typeparser/BooleanParser.kt | 40 ++ .../typeparser/CloudLobbyGroupParser.kt | 35 ++ .../typeparser/CloudProxyGroupParser.kt | 35 ++ .../typeparser/CloudServerGroupParser.kt | 35 ++ .../typeparser/CloudServiceGroupParser.kt | 35 ++ .../string/typeparser/CloudServiceParser.kt | 35 ++ .../parser/string/typeparser/DoubleParser.kt | 41 ++ .../parser/string/typeparser/FloatParser.kt | 41 ++ .../api/parser/string/typeparser/IntParser.kt | 41 ++ .../string/typeparser/TemplateParser.kt | 34 ++ .../string/typeparser/WrapperInfoParser.kt | 34 ++ .../api/player/AbstractCloudPlayerManager.kt | 94 ++++ .../api/player/ICloudPlayerUpdater.kt | 51 ++ .../api/player/IOfflineCloudPlayer.kt | 86 ++++ .../api/player/OfflineCloudPlayer.kt | 94 ++++ .../api/player/PlayerMessageQueue.kt | 61 +++ .../api/player/PlayerServerConnectState.kt | 37 ++ .../api/player/SimpleCloudPlayer.kt | 53 ++ .../player/connection/ConnectionResponse.kt | 55 +++ .../player/connection/DefaultPlayerAddress.kt | 33 ++ .../connection/DefaultPlayerConnection.kt | 44 ++ .../api/player/connection/IPlayerAddress.kt | 37 ++ .../player/connection/IPlayerConnection.kt | 62 +++ .../api/player/impl/CloudPlayer.kt | 146 ++++++ .../api/player/impl/CloudPlayerUpdater.kt | 75 +++ .../api/player/text/CloudText.kt | 77 +++ .../api/player/text/CloudTextBuilder.kt | 97 ++++ .../thesimplecloud/api/property/IProperty.kt | 38 ++ .../api/property/IPropertyMap.kt | 88 ++++ .../thesimplecloud/api/property/Property.kt | 88 ++++ .../api/screen/ICommandExecutable.kt | 36 ++ .../api/screen/ICommandExecuteManager.kt | 32 ++ .../api/service/ICloudService.kt | 261 ++++++++++ .../api/service/ICloudServiceManager.kt | 83 ++++ .../api/service/ICloudServiceUpdater.kt | 37 ++ .../api/service/ICloudServiceVariables.kt | 101 ++++ .../api/service/ServiceState.kt | 52 ++ .../thesimplecloud/api/service/ServiceType.kt | 63 +++ .../impl/AbstractCloudServiceManager.kt | 101 ++++ .../api/service/impl/DefaultCloudService.kt | 203 ++++++++ .../impl/DefaultCloudServiceUpdater.kt | 112 +++++ .../IServiceStartConfiguration.kt | 79 +++ .../ServiceStartConfiguration.kt | 95 ++++ .../start/future/IServiceStartPromise.kt | 87 ++++ .../start/future/ServiceStartPromise.kt | 234 +++++++++ .../service/version/IServiceVersionHandler.kt | 81 +++ .../api/service/version/ServiceVersion.kt | 38 ++ .../service/version/ServiceVersionHandler.kt | 92 ++++ .../loader/CombinedServiceVersionLoader.kt | 41 ++ .../version/loader/IServiceVersionLoader.kt | 40 ++ .../loader/LocalServiceVersionHandler.kt | 58 +++ .../version/loader/ServiceVersionWebLoader.kt | 63 +++ .../service/version/type/MinecraftEdition.kt | 35 ++ .../service/version/type/ServiceAPIType.kt | 51 ++ .../version/type/ServiceVersionType.kt | 43 ++ .../api/servicegroup/ICloudServiceGroup.kt | 124 +++++ .../servicegroup/ICloudServiceGroupManager.kt | 248 ++++++++++ .../servicegroup/ICloudServiceGroupUpdater.kt | 32 ++ .../ICloudServiceGroupVariables.kt | 141 ++++++ .../grouptype/ICloudLobbyGroup.kt | 45 ++ .../grouptype/ICloudProxyGroup.kt | 45 ++ .../grouptype/ICloudServerGroup.kt | 37 ++ .../updater/ICloudLobbyGroupUpdater.kt | 40 ++ .../updater/ICloudProxyGroupUpdater.kt | 40 ++ .../impl/AbstractCloudServiceGroupManager.kt | 72 +++ .../servicegroup/impl/AbstractServiceGroup.kt | 145 ++++++ .../servicegroup/impl/DefaultLobbyGroup.kt | 96 ++++ .../servicegroup/impl/DefaultProxyGroup.kt | 95 ++++ .../servicegroup/impl/DefaultServerGroup.kt | 83 ++++ .../impl/updater/DefaultLobbyGroupUpdater.kt | 42 ++ .../impl/updater/DefaultProxyGroupUpdater.kt | 43 ++ .../updater/DefaultServiceGroupUpdater.kt | 132 +++++ .../list/AbstractSynchronizedObjectList.kt | 89 ++++ .../api/sync/list/ISynchronizedObjectList.kt | 65 +++ .../manager/ISynchronizedObjectListManager.kt | 71 +++ .../manager/SynchronizedObjectListManager.kt | 74 +++ .../api/sync/object/GlobalPropertyHolder.kt | 129 +++++ .../api/sync/object/IGlobalPropertyHolder.kt | 35 ++ .../thesimplecloud/api/template/ITemplate.kt | 45 ++ .../api/template/ITemplateManager.kt | 41 ++ .../api/template/ITemplateUpdater.kt | 37 ++ .../api/template/ITemplateVariables.kt | 71 +++ .../api/template/impl/DefaultTemplate.kt | 78 +++ .../template/impl/DefaultTemplateManager.kt | 61 +++ .../template/impl/DefaultTemplateUpdater.kt | 80 +++ .../api/utils/ClassExtension.kt | 32 ++ .../api/utils/ConfigurationFileEditor.kt | 118 +++++ .../api/utils/DatabaseExclude.kt | 36 ++ .../thesimplecloud/api/utils/EnumExtension.kt | 34 ++ .../eu/thesimplecloud/api/utils/FileFinder.kt | 52 ++ .../api/utils/ManifestLoader.kt | 41 ++ .../eu/thesimplecloud/api/utils/Nameable.kt | 32 ++ .../api/utils/NoArgsFunction.kt | 35 ++ .../api/utils/ObjectSerializer.kt | 69 +++ .../api/utils/StringIterableExtension.kt | 34 ++ .../eu/thesimplecloud/api/utils/ZipUtils.kt | 79 +++ .../api/utils/time/TimeAmountMeasurer.kt | 48 ++ .../api/utils/time/Timestamp.kt | 61 +++ .../api/wrapper/IWrapperInfo.kt | 94 ++++ .../api/wrapper/IWrapperInfoUpdater.kt | 92 ++++ .../api/wrapper/IWrapperManager.kt | 53 ++ .../api/wrapper/impl/DefaultWrapperInfo.kt | 112 +++++ .../wrapper/impl/DefaultWrapperInfoUpdater.kt | 99 ++++ .../api/wrapper/impl/DefaultWrapperManager.kt | 71 +++ .../api/eventapi/AdvancedListenerTest.kt | 96 ++++ .../api/eventapi/EmptyMockCloudAPIImpl.kt | 96 ++++ .../api/eventapi/EventApiTest.kt | 105 ++++ .../ServiceVersionHandlerTest.kt | 189 +++++++ simplecloud-base/build.gradle | 67 +++ .../base/core/jvm/JvmArgument.kt | 34 ++ .../base/core/jvm/JvmArgumentsConfig.kt | 33 ++ .../base/manager/commands/ClearCommand.kt | 39 ++ .../base/manager/commands/CopyCommand.kt | 63 +++ .../base/manager/commands/CreateCommand.kt | 91 ++++ .../base/manager/commands/DeleteCommand.kt | 115 +++++ .../base/manager/commands/EditCommand.kt | 316 ++++++++++++ .../base/manager/commands/ExecuteCommand.kt | 51 ++ .../base/manager/commands/InfoCommand.kt | 96 ++++ .../base/manager/commands/ListCommand.kt | 100 ++++ .../base/manager/commands/ReloadCommand.kt | 152 ++++++ .../base/manager/commands/ScreenCommand.kt | 82 +++ .../base/manager/commands/ShutdownCommand.kt | 46 ++ .../manager/commands/ShutdownGroupCommand.kt | 53 ++ .../base/manager/commands/StartCommand.kt | 60 +++ .../manager/commands/StartStaticCommand.kt | 68 +++ ...GroupParameterCommandSuggestionProvider.kt | 52 ++ ...apperParameterCommandSuggestionProvider.kt | 53 ++ .../config/JvmArgumentsConfigLoader.kt | 42 ++ .../config/encryption/KeyConfigLoader.kt | 41 ++ .../config/mongo/DatabaseConfigLoader.kt | 47 ++ .../config/template/TemplatesConfig.kt | 29 ++ .../config/template/TemplatesConfigLoader.kt | 34 ++ .../config/updater/ModuleUpdaterConfig.kt | 33 ++ .../updater/ModuleUpdaterConfigLoader.kt | 56 +++ .../AbstractOfflineCloudPlayerHandler.kt | 43 ++ .../database/DatabaseConnectionInformation.kt | 34 ++ .../base/manager/database/DatabaseType.kt | 38 ++ .../database/IOfflineCloudPlayerHandler.kt | 56 +++ .../MongoOfflineCloudPlayerHandler.kt | 133 +++++ .../database/SQLOfflineCloudPlayerHandler.kt | 166 +++++++ .../database/aes/AdvancedEncryption.kt | 64 +++ .../events/CloudPlayerLoginRequestEvent.kt | 43 ++ .../CloudServiceGroupFileHandler.kt | 69 +++ .../manager/filehandler/WrapperFileHandler.kt | 59 +++ .../base/manager/impl/CloudAPIImpl.kt | 97 ++++ .../impl/CloudServiceGroupManagerImpl.kt | 72 +++ .../manager/impl/CloudServiceManagerImpl.kt | 104 ++++ .../manager/impl/CommandExecuteManagerImpl.kt | 56 +++ .../base/manager/impl/EventManagerImpl.kt | 41 ++ .../base/manager/impl/TemplateManagerImpl.kt | 61 +++ .../base/manager/impl/WrapperManagerImpl.kt | 41 ++ .../ingamecommands/IngameCommandUpdater.kt | 51 ++ .../manager/language/LanguageManagerImpl.kt | 52 ++ .../base/manager/listener/CloudListener.kt | 83 ++++ .../manager/listener/ModuleEventListener.kt | 54 ++ .../packets/PacketInCloudClientLogin.kt | 81 +++ .../packets/PacketInGetTabSuggestions.kt | 56 +++ .../network/packets/PacketInScreenMessage.kt | 52 ++ .../network/packets/PacketOutJvmArguments.kt | 45 ++ .../packets/PacketOutReloadExistingModules.kt | 33 ++ .../packets/PacketOutSetWrapperName.kt | 35 ++ .../player/PacketInCreateCloudPlayer.kt | 73 +++ .../player/PacketInPlayerConnectToServer.kt | 61 +++ .../player/PacketInPlayerExecuteCommand.kt | 51 ++ .../player/PacketInPlayerLoginRequest.kt | 45 ++ .../player/PacketInTeleportOtherService.kt | 53 ++ .../player/PacketOutGetPlayerOnlineStatus.kt | 46 ++ .../packets/template/PacketInGetTemplates.kt | 58 +++ .../base/manager/packet/IPacketRegistry.kt | 60 +++ .../base/manager/packet/PacketRegistry.kt | 46 ++ .../manager/player/LoadOfflineCloudPlayer.kt | 37 ++ .../player/PlayerUnregisterScheduler.kt | 66 +++ .../exception/OfflinePlayerLoadException.kt | 26 + .../base/manager/service/IServiceHandler.kt | 49 ++ .../base/manager/service/ServiceHandler.kt | 219 ++++++++ .../ManagerServiceVersionHandler.kt | 70 +++ .../manager/setup/CreateDefaultLobbyGroup.kt | 41 ++ .../manager/setup/CreateDefaultProxyGroup.kt | 41 ++ .../base/manager/setup/ServiceVersionSetup.kt | 95 ++++ .../base/manager/setup/WrapperSetup.kt | 97 ++++ .../setup/database/DatabaseConnectionSetup.kt | 107 ++++ .../DatabaseTypeSetupAnswerProvider.kt | 40 ++ .../manager/setup/groups/DefaultGroupSetup.kt | 63 +++ .../manager/setup/groups/LobbyGroupSetup.kt | 192 +++++++ .../setup/groups/LobbyGroupSetupWithJava.kt | 42 ++ .../manager/setup/groups/ProxyGroupSetup.kt | 195 ++++++++ .../manager/setup/groups/ServerGroupSetup.kt | 181 +++++++ .../setup/groups/ServerGroupSetupWithJava.kt | 37 ++ .../GroupTemplateSetupAnswerProvider.kt | 42 ++ .../GroupWrapperSetupAnswerProvider.kt | 43 ++ .../ProxyVersionTypeSetupAnswerProvider.kt | 43 ++ .../ServerVersionTypeSetupAnswerProvider.kt | 43 ++ .../provider/ServiceAPITypeAnswerProvider.kt | 40 ++ .../ServiceJavaCommandAnswerProvider.kt | 34 ++ .../base/manager/startup/Manager.kt | 263 ++++++++++ .../base/manager/startup/ProfileFile.kt | 58 +++ .../server/AbstractCloudConnectionHandler.kt | 55 +++ .../CommunicationConnectionHandlerImpl.kt | 81 +++ .../startup/server/ManagerAccessHandler.kt | 44 ++ .../startup/server/ServerHandlerImpl.kt | 43 ++ .../server/TemplateConnectionHandlerImpl.kt | 33 ++ .../update/converter/ConversionException.kt | 27 + .../update/converter/Converter_2_0_To_2_1.kt | 43 ++ .../update/converter/Converter_2_2_To_2_3.kt | 69 +++ .../update/converter/Converter_2_3_To_2_4.kt | 83 ++++ .../update/converter/Converter_2_4_To_2_5.kt | 44 ++ .../update/converter/IVersionConverter.kt | 38 ++ .../converter/VersionConversionManager.kt | 101 ++++ .../base/wrapper/impl/CloudAPIImpl.kt | 86 ++++ .../impl/CloudServiceGroupManagerImpl.kt | 51 ++ .../wrapper/impl/CloudServiceManagerImpl.kt | 80 +++ .../wrapper/impl/CommandExecuteManagerImpl.kt | 57 +++ .../base/wrapper/impl/EventManagerImpl.kt | 42 ++ .../logger/LoggerMessageListenerImpl.kt | 44 ++ .../network/packets/PacketInJvmArguments.kt | 46 ++ .../packets/PacketInReloadExistingModules.kt | 35 ++ .../network/packets/PacketInSetWrapperName.kt | 45 ++ .../packets/template/PacketOutGetTemplates.kt | 30 ++ .../wrapper/process/CloudServiceProcess.kt | 238 +++++++++ .../process/CloudServiceProcessManager.kt | 42 ++ .../wrapper/process/ICloudServiceProcess.kt | 52 ++ .../process/ICloudServiceProcessManager.kt | 61 +++ .../base/wrapper/process/ProcessCopier.kt | 109 ++++ .../filehandler/LoadedServiceVersion.kt | 51 ++ .../process/filehandler/ServiceDirectory.kt | 171 +++++++ .../filehandler/ServiceVersionJarLoader.kt | 44 ++ .../filehandler/SingleServiceVersionLoader.kt | 97 ++++ .../process/queue/CloudServiceProcessQueue.kt | 91 ++++ .../IServiceConfigurator.kt | 36 ++ .../ServiceConfiguratorManager.kt | 44 ++ .../DefaultBungeeConfigurator.kt | 45 ++ .../DefaultServerConfigurator.kt | 49 ++ .../DefaultVelocityConfigurator.kt | 45 ++ .../wrapper/startup/ConnectionHandlerImpl.kt | 45 ++ .../base/wrapper/startup/CpuUsageUpdater.kt | 63 +++ .../base/wrapper/startup/PortManager.kt | 82 +++ .../base/wrapper/startup/Wrapper.kt | 234 +++++++++ .../src/main/resources/files/bukkit.yml | 43 ++ .../src/main/resources/files/config.yml | 50 ++ .../src/main/resources/files/server-icon.png | Bin 0 -> 2073 bytes .../main/resources/files/server.properties | 58 +++ .../src/main/resources/files/spigot.yml | 133 +++++ .../src/main/resources/files/velocity.toml | 95 ++++ .../src/main/resources/manager.json | 19 + .../src/main/resources/wrapper.json | 19 + simplecloud-client/build.gradle | 29 ++ .../packets/PacketOutCloudClientLogin.kt | 42 ++ .../client/packets/PacketOutScreenMessage.kt | 43 ++ simplecloud-dependency-loader/build.gradle | 23 + .../AdvancedDependencyDownloader.kt | 68 +++ .../loader/dependency/DependencyLoader.kt | 112 +++++ .../loader/dependency/DependencyLoaderMain.kt | 53 ++ .../loader/dependency/DependencyResolver.kt | 88 ++++ .../dependency/LauncherDependencyLoader.kt | 60 +++ simplecloud-launcher/build.gradle | 70 +++ .../startup/ClassLoaderValidatorMain.java | 47 ++ .../launcher/startup/WrapperRamWriter.kt | 34 ++ .../application/ApplicationClassLoader.kt | 62 +++ .../application/ApplicationStarter.kt | 67 +++ .../application/CloudApplicationType.kt | 32 ++ .../launcher/application/ICloudApplication.kt | 28 ++ .../launcher/commands/CreateJavaVersion.kt | 40 ++ .../launcher/commands/HelpCommand.kt | 66 +++ .../launcher/commands/StopCommand.kt | 47 ++ .../launcher/commands/VersionCommand.kt | 45 ++ .../launcher/config/java/JavaVersion.kt | 34 ++ .../config/java/JavaVersionConfigLoader.kt | 33 ++ .../config/launcher/LauncherConfig.kt | 33 ++ .../config/launcher/LauncherConfigLoader.kt | 34 ++ .../launcher/console/ConsoleCompleter.kt | 66 +++ .../launcher/console/ConsoleManager.kt | 115 +++++ .../launcher/console/ConsoleSender.kt | 78 +++ .../launcher/console/IConsoleManager.kt | 37 ++ .../launcher/console/command/CommandData.kt | 68 +++ .../console/command/CommandManager.kt | 327 ++++++++++++ .../console/command/CommandParameterData.kt | 34 ++ .../launcher/console/command/CommandType.kt | 36 ++ .../console/command/ICommandHandler.kt | 32 ++ .../console/command/annotations/Command.kt | 45 ++ .../command/annotations/CommandArgument.kt | 41 ++ .../command/annotations/CommandSubPath.kt | 35 ++ .../CloudPlayerCommandSuggestionProvider.kt | 40 ++ .../EmptyCommandSuggestionProvider.kt | 39 ++ .../provider/ICommandSuggestionProvider.kt | 44 ++ .../ServiceCommandSuggestionProvider.kt | 40 ++ .../ServiceGroupCommandSuggestionProvider.kt | 40 ++ .../ServiceStateCommandSuggestionProvider.kt | 34 ++ .../TemplateCommandSuggestionProvider.kt | 40 ++ .../WrapperCommandSuggestionProvider.kt | 40 ++ .../launcher/console/setup/ISetup.kt | 26 + .../launcher/console/setup/SetupManager.kt | 232 +++++++++ .../setup/annotations/SetupCancelled.kt | 28 ++ .../setup/annotations/SetupFinished.kt | 28 ++ .../setup/annotations/SetupQuestion.kt | 35 ++ .../provider/BooleanSetupAnswerProvider.kt | 39 ++ .../provider/EmptySetupAnswerProvider.kt | 39 ++ .../setup/provider/ISetupAnswerProvider.kt | 42 ++ .../provider/TemplateSetupAnswerProvider.kt | 40 ++ .../provider/WrapperSetupAnswerProvider.kt | 40 ++ .../launcher/event/command/CommandEvent.kt | 28 ++ .../event/command/CommandExecuteEvent.kt | 42 ++ .../event/command/CommandRegisteredEvent.kt | 27 + .../event/command/CommandUnregisteredEvent.kt | 27 + .../launcher/event/module/ModuleEvent.kt | 28 ++ .../event/module/ModuleLoadedEvent.kt | 28 ++ .../event/module/ModuleUnloadedEvent.kt | 28 ++ .../exception/CommandRegistrationException.kt | 32 ++ .../launcher/exception/DependencyException.kt | 26 + .../exception/module/ModuleLoadException.kt | 30 ++ .../launcher/extension/IterableExtension.kt | 46 ++ .../launcher/external/ExtensionLoader.kt | 46 ++ .../launcher/external/module/LoadedModule.kt | 45 ++ .../module/LoadedModuleFileContent.kt | 32 ++ .../external/module/ModuleClassLoader.kt | 77 +++ .../external/module/ModuleCopyType.kt | 56 +++ .../external/module/ModuleFileContent.kt | 50 ++ .../external/module/handler/IModuleHandler.kt | 114 +++++ .../external/module/handler/ModuleHandler.kt | 207 ++++++++ .../handler/ModuleLanguageFileLoader.kt | 85 ++++ .../module/handler/ModuleListLoader.kt | 127 +++++ .../module/handler/ModuleUpdateInstaller.kt | 58 +++ .../handler/RecursiveDependencyChecker.kt | 60 +++ .../module/handler/UnsafeModuleLoader.kt | 82 +++ .../module/handler/UnsafeModuleUnloader.kt | 68 +++ .../external/module/update/UpdateMethod.kt | 43 ++ .../module/update/UpdaterFileContent.kt | 36 ++ .../external/module/updater/ModuleUpdater.kt | 61 +++ .../launcher/language/LanguageFileLoader.kt | 115 +++++ .../launcher/logging/AnsiColorHelper.kt | 64 +++ .../logging/ILoggerMessageListener.kt | 29 ++ .../launcher/logging/LogType.kt | 35 ++ .../launcher/logging/LoggerProvider.kt | 233 +++++++++ .../launcher/screens/IScreen.kt | 47 ++ .../launcher/screens/IScreenManager.kt | 81 +++ .../launcher/screens/ScreenImpl.kt | 43 ++ .../launcher/screens/ScreenManagerImpl.kt | 89 ++++ .../launcher/screens/session/ScreenSession.kt | 60 +++ .../launcher/setups/AutoIpSetup.kt | 71 +++ .../thesimplecloud/launcher/setups/IpSetup.kt | 53 ++ .../launcher/setups/JavaSetup.kt | 64 +++ .../launcher/setups/LanguageSetup.kt | 47 ++ .../launcher/setups/StartSetup.kt | 57 +++ .../ApplicationTypeSetupAnswerProvider.kt | 39 ++ .../provider/LanguageSetupAnswerProvider.kt | 39 ++ .../launcher/startup/Launcher.kt | 246 +++++++++ .../launcher/startup/LauncherMain.kt | 34 ++ .../startup/LauncherStartArguments.kt | 43 ++ .../launcher/updater/AbstractUpdater.kt | 66 +++ .../launcher/updater/BaseUpdater.kt | 47 ++ .../launcher/updater/IUpdater.kt | 73 +++ .../launcher/updater/RunnerUpdater.kt | 105 ++++ .../launcher/updater/UpdateExecutor.kt | 32 ++ .../launcher/utils/FileCopier.kt | 68 +++ .../launcher/utils/IpValidator.kt | 41 ++ .../launcher/utils/WebsiteContentLoader.kt | 43 ++ .../src/main/resources/language/de.json | 197 ++++++++ .../src/main/resources/language/en.json | 198 ++++++++ .../thesimplecloud/EmptyMockCloudAPIImpl.kt | 98 ++++ .../launcher/external/ModuleListLoaderTest.kt | 130 +++++ .../thesimplecloud/mockmodule/ModuleMain.kt | 33 ++ simplecloud-modules/build.gradle | 22 + .../simplecloud-module-chat-tab/build.gradle | 40 ++ .../module/prefix/manager/PrefixModule.kt | 50 ++ .../prefix/manager/command/ChatTabCommand.kt | 51 ++ .../prefix/manager/config/ChatTabConfig.kt | 64 +++ .../config/ChatTabModuleConfigPersistence.kt | 51 ++ .../manager/config/TablistInformation.kt | 37 ++ .../prefix/service/bungee/BungeePluginMain.kt | 32 ++ .../prefix/service/spigot/BukkitPluginMain.kt | 61 +++ .../service/spigot/listener/ChatListener.kt | 72 +++ .../service/spigot/listener/CloudListener.kt | 53 ++ .../service/spigot/listener/JoinListener.kt | 51 ++ .../service/tablist/ProxyTablistHelper.kt | 47 ++ .../prefix/service/tablist/TablistHelper.kt | 111 +++++ .../service/velocity/VelocityPluginMain.kt | 36 ++ .../src/main/resources/bungee.yml | 6 + .../src/main/resources/languages/de.json | 6 + .../src/main/resources/languages/en.json | 6 + .../src/main/resources/module.json | 10 + .../src/main/resources/plugin.yml | 7 + .../src/main/resources/updater.json | 6 + .../src/main/resources/velocity-plugin.json | 9 + .../build.gradle | 34 ++ .../module/cloudflare/CloudFlareModule.kt | 88 ++++ .../cloudflare/config/domain/DomainConfig.kt | 42 ++ .../config/domain/DomainConfigLoader.kt | 39 ++ .../cloudflare/config/proxy/ProxyConfig.kt | 41 ++ .../config/proxy/ProxyConfigLoader.kt | 39 ++ .../domain/CloudFlareDomainHelper.kt | 168 +++++++ .../listener/CloudFlareSingleGroupListener.kt | 68 +++ .../src/main/resources/languages/de.json | 5 + .../src/main/resources/languages/en.json | 5 + .../src/main/resources/module.json | 19 + .../src/main/resources/updater.json | 6 + .../build.gradle | 32 ++ .../module/hubcommand/HubCommand.kt | 53 ++ .../module/hubcommand/HubCommandModule.kt | 38 ++ .../hubcommand/config/HubCommandConfig.kt | 34 ++ .../config/HubCommandConfigLoader.kt | 39 ++ .../src/main/resources/module.json | 10 + .../src/main/resources/updater.json | 6 + .../build.gradle | 32 ++ .../internalwrapper/InternalWrapperModule.kt | 109 ++++ .../setup/InternalWrapperMemorySetup.kt | 59 +++ .../src/main/resources/languages/de.json | 3 + .../src/main/resources/languages/en.json | 3 + .../src/main/resources/module.json | 10 + .../src/main/resources/updater.json | 6 + .../simplecloud-module-notify/build.gradle | 34 ++ .../module/notify/CloudListener.kt | 106 ++++ .../module/notify/NotifyModule.kt | 70 +++ .../module/notify/config/Config.kt | 36 ++ .../module/notify/config/DefaultConfig.kt | 42 ++ .../src/main/resources/module.json | 10 + .../src/main/resources/updater.json | 6 + .../simplecloud-module-npc/build.gradle | 38 ++ .../npc/lib/config/InventorySettingsConfig.kt | 11 + .../module/npc/lib/config/NPCModuleConfig.kt | 12 + .../npc/lib/config/NPCModuleConfigHandler.kt | 50 ++ .../module/npc/lib/config/NPCsConfig.kt | 14 + .../module/npc/lib/config/npc/CloudNPCData.kt | 17 + .../module/npc/lib/config/npc/LocationData.kt | 11 + .../module/npc/lib/config/npc/NPCItem.kt | 6 + .../module/npc/lib/config/npc/SkinData.kt | 6 + .../npc/lib/config/npc/action/Action.kt | 7 + .../npc/lib/config/npc/action/NPCAction.kt | 3 + .../lib/config/npc/settings/MobNPCSettings.kt | 6 + .../lib/config/npc/settings/NPCSettings.kt | 8 + .../config/npc/settings/PlayerNPCSettings.kt | 11 + .../module/npc/lib/extension/String.kt | 28 ++ .../module/npc/lib/type/MaterialType.kt | 5 + .../module/npc/lib/type/MobType.kt | 5 + .../module/npc/module/NPCModule.kt | 79 +++ .../npc/module/command/CloudNPCCommand.kt | 237 +++++++++ .../npc/module/command/CreateNpcCommand.kt | 134 +++++ .../module/command/EditGeneralNpcCommand.kt | 280 +++++++++++ ...CloudNPCActionCommandSuggestionProvider.kt | 11 + .../CloudNPCIDCommandSuggestionProvider.kt | 12 + .../CloudNPCIDMobCommandSuggestionProvider.kt | 12 + ...oudNPCIDPlayerCommandSuggestionProvider.kt | 12 + ...oudNPCItemListCommandSuggestionProvider.kt | 18 + ...loudNPCMobTypeCommandSuggestionProvider.kt | 21 + ...WithoutProxiesCommandSuggestionProvider.kt | 26 + .../module/npc/module/skin/SkinHandler.kt | 135 +++++ .../module/npc/plugin/NPCPlugin.kt | 64 +++ .../npc/plugin/inventory/InventoryData.kt | 10 + .../npc/plugin/inventory/InventoryHandler.kt | 111 +++++ .../npc/plugin/listener/CloudListener.kt | 33 ++ .../npc/plugin/listener/InventoryListener.kt | 49 ++ .../listener/PlayerConnectionListener.kt | 43 ++ .../module/npc/plugin/npc/ServerNPCHandler.kt | 83 ++++ .../npc/plugin/npc/type/AbstractServerNPC.kt | 147 ++++++ .../module/npc/plugin/npc/type/MobNPC.kt | 123 +++++ .../module/npc/plugin/npc/type/PlayerNPC.kt | 116 +++++ .../module/npc/plugin/npc/type/ServerNPC.kt | 10 + .../src/main/resources/languages/de.json | 35 ++ .../src/main/resources/languages/en.json | 35 ++ .../src/main/resources/module.json | 10 + .../src/main/resources/plugin.yml | 9 + .../src/main/resources/updater.json | 6 + .../build.gradle | 41 ++ .../module/permission/IPermissionPool.kt | 40 ++ .../permission/PermissionCheckListener.kt | 39 ++ .../PermissionPlayerUpdatedEventCaller.kt | 46 ++ .../module/permission/PermissionPool.kt | 66 +++ .../permission/entity/IPermissionEntity.kt | 79 +++ .../permission/entity/PermissionEntity.kt | 47 ++ .../group/PermissionGroupDeletedEvent.kt | 33 ++ .../event/group/PermissionGroupEvent.kt | 36 ++ .../group/PermissionGroupUpdatedEvent.kt | 33 ++ .../event/player/PermissionPlayerEvent.kt | 36 ++ .../player/PermissionPlayerUpdatedEvent.kt | 33 ++ .../permission/group/IPermissionGroup.kt | 70 +++ .../permission/group/PermissionGroup.kt | 59 +++ .../group/manager/IPermissionGroupManager.kt | 60 +++ .../group/manager/PermissionGroupManager.kt | 83 ++++ .../permission/manager/CloudListener.kt | 56 +++ .../manager/PermissionFilesPriorityUpdater.kt | 52 ++ .../permission/manager/PermissionModule.kt | 91 ++++ .../manager/command/PermissionCommand.kt | 467 ++++++++++++++++++ ...ermissionGroupCommandSuggestionProvider.kt | 41 ++ .../config/PermissionGroupConfigsLoader.kt | 52 ++ .../manager/config/PermissionModuleConfig.kt | 34 ++ .../config/PermissionModuleConfigLoader.kt | 40 ++ .../packet/PacketInGetDefaultGroupName.kt | 40 ++ .../packet/PacketOutGetDefaultGroupName.kt | 41 ++ .../permission/permission/Permission.kt | 73 +++ .../permission/player/IPermissionPlayer.kt | 113 +++++ .../player/OfflinePlayerExtension.kt | 34 ++ .../permission/player/PermissionPlayer.kt | 81 +++ .../player/PlayerPermissionGroupInfo.kt | 28 ++ .../manager/IPermissionPlayerManager.kt | 70 +++ .../service/bungee/BungeeListener.kt | 47 ++ .../service/bungee/BungeePluginMain.kt | 36 ++ .../spigot/BukkitCloudPermissibleBase.kt | 66 +++ .../service/spigot/SpigotListener.kt | 60 +++ .../service/spigot/SpigotPluginMain.kt | 38 ++ .../service/spigot/util/ReflectionUtils.kt | 47 ++ .../velocity/VelocityPermissionProvider.kt | 56 +++ .../service/velocity/VelocityPluginMain.kt | 50 ++ .../src/main/resources/bungee.yml | 6 + .../src/main/resources/languages/de.json | 26 + .../src/main/resources/languages/en.json | 26 + .../src/main/resources/module.json | 10 + .../src/main/resources/plugin.yml | 11 + .../src/main/resources/updater.json | 6 + .../src/main/resources/velocity-plugin.json | 9 + .../permission/PermissionTest.kt | 71 +++ .../build.gradle | 24 + .../manager/PlaceholdersModule.kt | 13 + .../placeholders/spigot/BukkitPluginMain.kt | 28 ++ .../placeholders/spigot/StringExtension.kt | 108 ++++ .../spigot/placeholderapi/PlaceholderHook.kt | 24 + .../src/main/resources/module.json | 10 + .../src/main/resources/plugin.yml | 15 + .../src/main/resources/updater.json | 6 + .../simplecloud-module-proxy/build.gradle | 38 ++ .../module/proxy/config/Config.kt | 43 ++ .../module/proxy/config/DefaultConfig.kt | 87 ++++ .../module/proxy/config/MotdConfiguration.kt | 37 ++ .../proxy/config/ProxyGroupConfiguration.kt | 37 ++ .../proxy/config/TablistConfiguration.kt | 35 ++ .../module/proxy/extensions/ListExtension.kt | 34 ++ .../proxy/manager/GroupCreateListener.kt | 60 +++ .../manager/MaintenanceToggleListener.kt | 93 ++++ .../module/proxy/manager/ProxyModule.kt | 88 ++++ .../proxy/manager/commands/ProxyCommand.kt | 102 ++++ .../manager/converter/ConfigConverter.kt | 43 ++ .../converter/MiniMessageConfigConverter.kt | 68 +++ .../converter/convert3to4/MessageConverter.kt | 75 +++ .../convert3to4/SingleColorCodeReplacer.kt | 54 ++ .../convert3to4/SpecialColorCodeReplacer.kt | 82 +++ .../module/proxy/service/ProxyHandler.kt | 153 ++++++ .../proxy/service/bungee/BungeePluginMain.kt | 96 ++++ .../service/bungee/listener/BungeeListener.kt | 153 ++++++ .../service/velocity/VelocityPluginMain.kt | 85 ++++ .../velocity/listener/VelocityListener.kt | 151 ++++++ .../src/main/resources/languages/de.json | 8 + .../src/main/resources/languages/en.json | 8 + .../src/main/resources/module.json | 10 + .../src/main/resources/plugin.yml | 8 + .../src/main/resources/updater.json | 6 + .../src/main/resources/velocity-plugin.json | 9 + .../simplecloud-module-rest/build.gradle | 46 ++ .../thesimplecloud/module/rest/RestModule.kt | 64 +++ .../module/rest/annotation/RequestBody.kt | 33 ++ .../module/rest/annotation/RequestMapping.kt | 37 ++ .../module/rest/annotation/RequestParam.kt | 36 ++ .../rest/annotation/RequestPathParam.kt | 35 ++ .../module/rest/annotation/RequestType.kt | 42 ++ .../module/rest/annotation/RequestingUser.kt | 33 ++ .../module/rest/annotation/RestController.kt | 36 ++ .../module/rest/annotation/WebExclude.kt | 33 ++ .../module/rest/auth/AuthService.kt | 120 +++++ .../module/rest/auth/JwtProvider.kt | 59 +++ .../thesimplecloud/module/rest/auth/Roles.kt | 39 ++ .../rest/auth/controller/AuthController.kt | 56 +++ .../module/rest/auth/controller/LoginDto.kt | 34 ++ .../module/rest/auth/user/User.kt | 39 ++ .../rest/auth/user/permission/Permission.kt | 66 +++ .../permission/entity/IPermissionEntity.kt | 75 +++ .../permission/entity/PermissionEntity.kt | 46 ++ .../module/rest/config/RestConfig.kt | 36 ++ .../module/rest/config/RestConfigLoader.kt | 39 ++ .../rest/controller/ControllerHandler.kt | 101 ++++ .../module/rest/controller/IController.kt | 31 ++ .../rest/controller/IExceptionHelper.kt | 39 ++ .../rest/controller/RequestMethodData.kt | 48 ++ .../rest/defaultcontroller/UserController.kt | 72 +++ .../rest/defaultcontroller/dto/CommandDto.kt | 33 ++ .../rest/defaultcontroller/dto/ErrorDto.kt | 45 ++ .../rest/defaultcontroller/dto/PathDto.kt | 33 ++ .../rest/defaultcontroller/dto/ResultDto.kt | 33 ++ .../filemanager/FileManagerController.kt | 111 +++++ .../group/ServiceGroupActionController.kt | 57 +++ .../group/ServiceGroupController.kt | 134 +++++ .../player/PlayerActionController.kt | 38 ++ .../player/PlayerController.kt | 59 +++ .../service/ServiceActionController.kt | 66 +++ .../service/ServiceController.kt | 70 +++ .../template/TemplateController.kt | 77 +++ .../uptime/UptimeController.kt | 45 ++ .../version/VersionController.kt | 45 ++ .../wrapper/WrapperController.kt | 81 +++ .../exception/ElementAlreadyExistException.kt | 31 ++ .../rest/exception/NullResultException.kt | 31 ++ .../rest/javalin/JavalinRequestHandler.kt | 85 ++++ .../module/rest/javalin/RestServer.kt | 121 +++++ .../rest/javalin/SingleRequestProcessor.kt | 141 ++++++ .../rest/util/ContextClassLoaderChanger.kt | 41 ++ .../src/main/resources/languages/de.json | 3 + .../src/main/resources/languages/en.json | 3 + .../src/main/resources/module.json | 29 ++ .../src/main/resources/updater.json | 6 + .../build.gradle | 21 + .../api/AbstractServiceViewer.kt | 46 ++ .../api/ServiceViewGroupManager.kt | 103 ++++ .../api/ServiceViewManager.kt | 69 +++ .../api/ServiceSelectionTest.kt | 46 ++ .../simplecloud-module-sign/build.gradle | 26 + .../module/sign/lib/SignModuleConfig.kt | 78 +++ .../module/sign/lib/group/GroupLayouts.kt | 46 ++ .../sign/lib/group/GroupLayoutsContainer.kt | 54 ++ .../module/sign/lib/layout/LayoutType.kt | 43 ++ .../module/sign/lib/layout/SignFrame.kt | 32 ++ .../module/sign/lib/layout/SignLayout.kt | 50 ++ .../sign/lib/layout/SignLayoutContainer.kt | 53 ++ .../settings/CloudSignSettingsContainer.kt | 10 + .../module/sign/lib/sign/CloudSign.kt | 38 ++ .../sign/lib/sign/CloudSignContainer.kt | 60 +++ .../module/sign/manager/SignModule.kt | 72 +++ .../manager/SignModuleConfigPersistence.kt | 130 +++++ .../sign/manager/command/SignCommand.kt | 83 ++++ .../module/sign/service/BukkitCloudSign.kt | 135 +++++ .../module/sign/service/BukkitPluginMain.kt | 138 ++++++ .../module/sign/service/Placeholder.kt | 34 ++ .../module/sign/service/SignAPI.kt | 65 +++ .../sign/service/SignServiceViewManager.kt | 53 ++ .../sign/service/command/CloudSignsCommand.kt | 129 +++++ .../event/BukkitCloudSignAddedEvent.kt | 33 ++ .../service/event/BukkitCloudSignEvent.kt | 36 ++ .../event/BukkitCloudSignRemovedEvent.kt | 33 ++ .../event/BukkitCloudSignUpdatedEvent.kt | 33 ++ .../sign/service/listener/InteractListener.kt | 54 ++ .../src/main/resources/languages/de.json | 6 + .../src/main/resources/languages/en.json | 6 + .../src/main/resources/module.json | 10 + .../src/main/resources/plugin.yml | 13 + .../src/main/resources/updater.json | 6 + .../build.gradle | 44 ++ .../module/statistics/StatisticsModule.kt | 98 ++++ .../rest/timed/TimedValueController.kt | 75 +++ .../module/statistics/timed/Timed.kt | 41 ++ .../module/statistics/timed/TimedValue.kt | 39 ++ .../timed/TimedValueCollectorManager.kt | 77 +++ .../timed/collector/CPUUsageTimedCollector.kt | 49 ++ .../timed/collector/ITimedValueCollector.kt | 41 ++ .../timed/collector/MemoryTimedCollector.kt | 50 ++ .../collector/PlayerCountTimedCollector.kt | 50 ++ .../listener/CloudServiceStartListener.kt | 48 ++ .../timed/listener/PlayerConnectListener.kt | 48 ++ .../timed/store/ITimedValueStore.kt | 101 ++++ .../timed/store/MongoTimedValueStore.kt | 81 +++ .../timed/store/SQLTimedValueStore.kt | 119 +++++ .../src/main/resources/module.json | 12 + .../src/main/resources/updater.json | 6 + .../simplecloud-module-support/build.gradle | 32 ++ .../module/support/lib/DumpFile.kt | 63 +++ .../module/support/lib/DumpFileCreator.kt | 20 + .../module/support/lib/config/UploadConfig.kt | 18 + .../support/lib/config/UploadConfigLoader.kt | 16 + .../support/lib/creator/GroupFileCreator.kt | 40 ++ .../support/lib/creator/ServiceFileCreator.kt | 36 ++ .../lib/creator/ServiceVersionFileCreator.kt | 30 ++ .../support/lib/creator/WrapperFileCreator.kt | 30 ++ .../module/support/manager/SupportModule.kt | 22 + .../support/manager/command/DumpCommand.kt | 32 ++ .../support/manager/handler/UploadHandler.kt | 50 ++ .../src/main/resources/module.json | 10 + .../src/main/resources/temp/dump-file.txt | 23 + .../src/main/resources/temp/group.txt | 14 + .../src/main/resources/temp/service.txt | 10 + .../src/main/resources/temp/static-jars.txt | 4 + .../src/main/resources/temp/wrapper.txt | 4 + simplecloud-plugin/build.gradle | 49 ++ .../plugin/ICloudServicePlugin.kt | 37 ++ .../plugin/extension/LocationExtension.kt | 54 ++ .../plugin/extension/PlayerExtensions.kt | 64 +++ .../plugin/extension/SyncExtension.kt | 41 ++ .../plugin/impl/CloudAPIImpl.kt | 88 ++++ .../impl/CloudServiceGroupManagerImpl.kt | 50 ++ .../plugin/impl/CloudServiceManagerImpl.kt | 50 ++ .../plugin/impl/CommandExecuteManagerImpl.kt | 43 ++ .../plugin/impl/EventManagerImpl.kt | 42 ++ .../player/AbstractCloudPlayerManagerProxy.kt | 41 ++ .../AbstractServiceCloudPlayerManager.kt | 118 +++++ .../plugin/listener/CloudListener.kt | 51 ++ .../packets/PacketInGetPlayerOnlineStatus.kt | 52 ++ .../packets/PacketOutCreateCloudPlayer.kt | 37 ++ .../packets/PacketOutGetTabSuggestions.kt | 48 ++ .../packets/PacketOutPlayerConnectToServer.kt | 37 ++ .../packets/PacketOutPlayerExecuteCommand.kt | 39 ++ .../packets/PacketOutPlayerLoginRequest.kt | 33 ++ .../packets/PacketOutTeleportOtherService.kt | 40 ++ .../thesimplecloud/plugin/proxy/CancelType.kt | 35 ++ .../plugin/proxy/ICloudProxyPlugin.kt | 34 ++ .../plugin/proxy/ProxyEventHandler.kt | 253 ++++++++++ .../proxy/bungee/BungeeComponentExtensions.kt | 38 ++ .../plugin/proxy/bungee/CloudBungeePlugin.kt | 191 +++++++ .../plugin/proxy/bungee/LobbyConnector.kt | 46 ++ .../proxy/bungee/ReconnectHandlerImpl.kt | 43 ++ .../proxy/bungee/command/BungeeCommand.kt | 61 +++ .../proxy/bungee/listener/BungeeListener.kt | 173 +++++++ .../listener/CloudPlayerDisconnectListener.kt | 42 ++ .../proxy/velocity/CloudVelocityPlugin.kt | 164 ++++++ .../plugin/proxy/velocity/LobbyConnector.kt | 50 ++ .../velocity/commands/VelocityCommand.kt | 78 +++ .../listener/CloudPlayerDisconnectListener.kt | 44 ++ .../velocity/listener/VelocityListener.kt | 182 +++++++ .../plugin/server/CloudSpigotPlugin.kt | 90 ++++ .../plugin/server/ICloudServerPlugin.kt | 28 ++ .../server/listener/ReloadCommandBlocker.kt | 65 +++ .../plugin/server/listener/SpigotListener.kt | 100 ++++ .../plugin/startup/CloudPlugin.kt | 155 ++++++ .../plugin/startup/ConnectionHandlerImpl.kt | 39 ++ .../plugin/startup/UsedMemoryUpdater.kt | 60 +++ .../src/main/resources/bungee.yml | 5 + .../src/main/resources/plugin.yml | 9 + .../src/main/resources/velocity-plugin.json | 9 + simplecloud-runner/build.gradle | 32 ++ .../runner/RunnerClassLoader.kt | 34 ++ .../runner/RunnerClassLoaderInitMain.kt | 80 +++ .../runner/RunnerFileProvider.kt | 37 ++ .../dependency/AdvancedCloudDependency.kt | 125 +++++ .../runner/dependency/CloudDependency.kt | 42 ++ .../dependency/DependencyLoaderStartup.kt | 76 +++ .../dependency/SimpleDependencyDownloader.kt | 43 ++ .../thesimplecloud/runner/utils/Downloader.kt | 46 ++ .../runner/utils/WebContentLoader.kt | 58 +++ simplecloud-updater/build.gradle | 29 ++ .../thesimplecloud/updater/UpdaterMain.java | 83 ++++ start-files/start.bat | 1 + start-files/start.sh | 23 + 866 files changed, 50214 insertions(+) create mode 100644 .github/workflows/gradle-build.yml create mode 100644 .gitignore create mode 100644 Jenkinsfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 simplecloud-api/build.gradle create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/CloudAPI.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/ICloudAPI.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/AbstractCacheList.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheList.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheObjectUpdateExecutor.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/CacheListManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/ICacheListManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/AbstractCacheValueUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValue.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValueUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentReference.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentType.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/command/ICommandSender.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractJsonLibConfigLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractMultipleConfigLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IConfigLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IFileHandler.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/depedency/DependenciesInformation.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/directorypaths/DirectoryPaths.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/dto/PlayerLoginRequestResult.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupCreatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupUpdatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerCommandExecuteEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerDisconnectEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerLoginEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerMessageEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerRegisteredEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUnregisteredEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUpdatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/CloudPlayerPermissionCheckEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/PermissionState.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceConnectedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceInvisibleEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceRegisteredEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartingEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUnregisteredEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUpdatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectRemovedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectUpdatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/object/GlobalPropertyUpdatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperUpdatedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/BasicEventManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/CloudEventHandler.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ICancellable.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventExecutor.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IListener.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ISynchronizedEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/exception/EventException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchPlayerException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchServiceException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchWorldException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/PlayerConnectException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/SerializationException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/UnreachableComponentException.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/extension/ClientManagerExtension.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/external/ICloudModule.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/ILanguageManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguagePlaceholder.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LoadedLanguageFile.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListener.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListenerExtension.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/IAdvancedListener.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/GroupLocation.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/ServiceLocation.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/SimpleLocation.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/TemplateLocation.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannel.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannelManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageListener.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/Message.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannel.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannelManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/IAuthenticatable.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/INetworkComponent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/ManagerComponent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOExecuteFunction.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOPing.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/event/PacketIOCallEvent.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/language/PacketIOLanguage.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/message/PacketIOChannelMessage.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOCloudPlayerForceCommandExecution.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOConnectCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetAllOnlinePlayers.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetNetworkOnlineCount.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetOfflinePlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerLocation.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerPing.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayersConnectedToService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetRegisteredPlayerCount.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOKickCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOPlayerHasPermission.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSaveOfflinePlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendMessageToCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendPlayerToLobby.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTablistToPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTitleToCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSetCloudPlayerUpdates.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOTeleportPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/screen/PacketIOExecuteCommand.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOCopyService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStartCloudService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStopCloudService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOWrapperStartService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCloudServiceGroupData.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCreateServiceGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/serviceversion/PacketIOServiceVersions.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/cachelist/PacketIOUpdateCacheObject.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOGetAllCachedListProperties.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIORemoveListProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOUpdateListProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOGetGlobalProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIORemoveGlobalProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOUpdateGlobalProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeFromClassParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/IJsonDataTypeParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/JsonDataParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/IStringTypeParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/StringParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/BooleanParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudLobbyGroupParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudProxyGroupParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServerGroupParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceGroupParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/DoubleParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/FloatParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/IntParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/TemplateParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/WrapperInfoParser.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/AbstractCloudPlayerManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/ICloudPlayerUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/IOfflineCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/OfflineCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerMessageQueue.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerServerConnectState.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/SimpleCloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/ConnectionResponse.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerAddress.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerConnection.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerAddress.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerConnection.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayerUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudText.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudTextBuilder.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IProperty.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IPropertyMap.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/Property.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecutable.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecuteManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceVariables.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceState.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceType.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/AbstractCloudServiceManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudService.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudServiceUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/IServiceStartConfiguration.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/ServiceStartConfiguration.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/IServiceStartPromise.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/ServiceStartPromise.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/IServiceVersionHandler.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersion.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersionHandler.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/CombinedServiceVersionLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/IServiceVersionLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/LocalServiceVersionHandler.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/ServiceVersionWebLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/MinecraftEdition.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceAPIType.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceVersionType.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupVariables.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudLobbyGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudProxyGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudServerGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudLobbyGroupUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudProxyGroupUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractCloudServiceGroupManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractServiceGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultLobbyGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultProxyGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultServerGroup.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultLobbyGroupUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultProxyGroupUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultServiceGroupUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/AbstractSynchronizedObjectList.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/ISynchronizedObjectList.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/ISynchronizedObjectListManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/SynchronizedObjectListManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/GlobalPropertyHolder.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/IGlobalPropertyHolder.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplate.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateVariables.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplate.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ClassExtension.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ConfigurationFileEditor.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/DatabaseExclude.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/EnumExtension.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/FileFinder.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ManifestLoader.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/Nameable.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/NoArgsFunction.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ObjectSerializer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/StringIterableExtension.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ZipUtils.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/TimeAmountMeasurer.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/Timestamp.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfo.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfoUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperManager.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfo.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfoUpdater.kt create mode 100644 simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperManager.kt create mode 100644 simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/AdvancedListenerTest.kt create mode 100644 simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EmptyMockCloudAPIImpl.kt create mode 100644 simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EventApiTest.kt create mode 100644 simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/serviceversion/ServiceVersionHandlerTest.kt create mode 100644 simplecloud-base/build.gradle create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgument.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgumentsConfig.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ClearCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CopyCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CreateCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/DeleteCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/EditCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ExecuteCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/InfoCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ListCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ReloadCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ScreenCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownGroupCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartStaticCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditGroupParameterCommandSuggestionProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditWrapperParameterCommandSuggestionProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/JvmArgumentsConfigLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/encryption/KeyConfigLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/mongo/DatabaseConfigLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfig.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfigLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfig.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfigLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/AbstractOfflineCloudPlayerHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseConnectionInformation.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseType.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/IOfflineCloudPlayerHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/MongoOfflineCloudPlayerHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/SQLOfflineCloudPlayerHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/aes/AdvancedEncryption.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/events/CloudPlayerLoginRequestEvent.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/CloudServiceGroupFileHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/WrapperFileHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudAPIImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceGroupManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CommandExecuteManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/EventManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/TemplateManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/WrapperManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/ingamecommands/IngameCommandUpdater.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/language/LanguageManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/CloudListener.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/ModuleEventListener.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInCloudClientLogin.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInGetTabSuggestions.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInScreenMessage.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutJvmArguments.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutReloadExistingModules.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutSetWrapperName.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInCreateCloudPlayer.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerConnectToServer.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerExecuteCommand.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerLoginRequest.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInTeleportOtherService.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketOutGetPlayerOnlineStatus.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/template/PacketInGetTemplates.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/IPacketRegistry.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/PacketRegistry.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/LoadOfflineCloudPlayer.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/PlayerUnregisterScheduler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/exception/OfflinePlayerLoadException.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/IServiceHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/ServiceHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/serviceversion/ManagerServiceVersionHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultLobbyGroup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultProxyGroup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/ServiceVersionSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/WrapperSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseConnectionSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseTypeSetupAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/DefaultGroupSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetupWithJava.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ProxyGroupSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetup.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetupWithJava.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupTemplateSetupAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupWrapperSetupAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ProxyVersionTypeSetupAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ServerVersionTypeSetupAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceAPITypeAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceJavaCommandAnswerProvider.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/Manager.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/ProfileFile.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/AbstractCloudConnectionHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/CommunicationConnectionHandlerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ManagerAccessHandler.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ServerHandlerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/TemplateConnectionHandlerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/ConversionException.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_0_To_2_1.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_2_To_2_3.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_3_To_2_4.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_4_To_2_5.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/IVersionConverter.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/VersionConversionManager.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudAPIImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceGroupManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CommandExecuteManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/EventManagerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/logger/LoggerMessageListenerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInJvmArguments.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInReloadExistingModules.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInSetWrapperName.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/template/PacketOutGetTemplates.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcess.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcessManager.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcess.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcessManager.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ProcessCopier.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/LoadedServiceVersion.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceDirectory.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceVersionJarLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/SingleServiceVersionLoader.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/queue/CloudServiceProcessQueue.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/IServiceConfigurator.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/ServiceConfiguratorManager.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultBungeeConfigurator.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultServerConfigurator.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultVelocityConfigurator.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/ConnectionHandlerImpl.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/CpuUsageUpdater.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/PortManager.kt create mode 100644 simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/Wrapper.kt create mode 100644 simplecloud-base/src/main/resources/files/bukkit.yml create mode 100644 simplecloud-base/src/main/resources/files/config.yml create mode 100644 simplecloud-base/src/main/resources/files/server-icon.png create mode 100644 simplecloud-base/src/main/resources/files/server.properties create mode 100644 simplecloud-base/src/main/resources/files/spigot.yml create mode 100644 simplecloud-base/src/main/resources/files/velocity.toml create mode 100644 simplecloud-base/src/main/resources/manager.json create mode 100644 simplecloud-base/src/main/resources/wrapper.json create mode 100644 simplecloud-client/build.gradle create mode 100644 simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutCloudClientLogin.kt create mode 100644 simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutScreenMessage.kt create mode 100644 simplecloud-dependency-loader/build.gradle create mode 100644 simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/AdvancedDependencyDownloader.kt create mode 100644 simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoader.kt create mode 100644 simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoaderMain.kt create mode 100644 simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyResolver.kt create mode 100644 simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/LauncherDependencyLoader.kt create mode 100644 simplecloud-launcher/build.gradle create mode 100644 simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/ClassLoaderValidatorMain.java create mode 100644 simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/WrapperRamWriter.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationClassLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationStarter.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/CloudApplicationType.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ICloudApplication.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/CreateJavaVersion.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/HelpCommand.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/StopCommand.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/VersionCommand.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersion.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersionConfigLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfig.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfigLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleCompleter.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleManager.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleSender.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/IConsoleManager.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandData.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandManager.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandParameterData.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandType.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/ICommandHandler.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/Command.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandArgument.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandSubPath.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/CloudPlayerCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/EmptyCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ICommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceGroupCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceStateCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/TemplateCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/WrapperCommandSuggestionProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/ISetup.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/SetupManager.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupCancelled.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupFinished.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupQuestion.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/BooleanSetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/EmptySetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/ISetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/TemplateSetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/WrapperSetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandExecuteEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandRegisteredEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandUnregisteredEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleLoadedEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleUnloadedEvent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/CommandRegistrationException.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/DependencyException.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/module/ModuleLoadException.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/extension/IterableExtension.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/ExtensionLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModule.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModuleFileContent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleClassLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleCopyType.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleFileContent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/IModuleHandler.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleHandler.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleLanguageFileLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleListLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleUpdateInstaller.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/RecursiveDependencyChecker.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleUnloader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdateMethod.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdaterFileContent.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/updater/ModuleUpdater.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/language/LanguageFileLoader.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/AnsiColorHelper.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/ILoggerMessageListener.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LogType.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LoggerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreen.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreenManager.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenImpl.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenManagerImpl.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/session/ScreenSession.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/AutoIpSetup.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/IpSetup.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/JavaSetup.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/LanguageSetup.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/StartSetup.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/ApplicationTypeSetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/LanguageSetupAnswerProvider.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/Launcher.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherMain.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherStartArguments.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/AbstractUpdater.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/BaseUpdater.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/IUpdater.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/RunnerUpdater.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/UpdateExecutor.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/FileCopier.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/IpValidator.kt create mode 100644 simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/WebsiteContentLoader.kt create mode 100644 simplecloud-launcher/src/main/resources/language/de.json create mode 100644 simplecloud-launcher/src/main/resources/language/en.json create mode 100644 simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/EmptyMockCloudAPIImpl.kt create mode 100644 simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/launcher/external/ModuleListLoaderTest.kt create mode 100644 simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/mockmodule/ModuleMain.kt create mode 100644 simplecloud-modules/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/PrefixModule.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/command/ChatTabCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabModuleConfigPersistence.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/TablistInformation.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/bungee/BungeePluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/BukkitPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/ChatListener.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/CloudListener.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/JoinListener.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/ProxyTablistHelper.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/TablistHelper.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/velocity/VelocityPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/bungee.yml create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/plugin.yml create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/velocity-plugin.json create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/CloudFlareModule.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfigLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfigLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/domain/CloudFlareDomainHelper.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/listener/CloudFlareSingleGroupListener.kt create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommandModule.kt create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfigLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/InternalWrapperModule.kt create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/setup/InternalWrapperMemorySetup.kt create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-notify/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/CloudListener.kt create mode 100644 simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/NotifyModule.kt create mode 100644 simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/Config.kt create mode 100644 simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/DefaultConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-notify/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-notify/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-npc/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/InventorySettingsConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfigHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCsConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/CloudNPCData.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/LocationData.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/NPCItem.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/SkinData.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/Action.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/NPCAction.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/MobNPCSettings.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/NPCSettings.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/PlayerNPCSettings.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/extension/String.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MaterialType.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MobType.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/NPCModule.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CloudNPCCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CreateNpcCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/EditGeneralNpcCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCActionCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDMobCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDPlayerCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCItemListCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCMobTypeCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/ServicesWithoutProxiesCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/skin/SkinHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/NPCPlugin.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryData.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/CloudListener.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/InventoryListener.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/PlayerConnectionListener.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/ServerNPCHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/AbstractServerNPC.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/MobNPC.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/PlayerNPC.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/ServerNPC.kt create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/resources/plugin.yml create mode 100644 simplecloud-modules/simplecloud-module-npc/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-permission/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/IPermissionPool.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionCheckListener.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPlayerUpdatedEventCaller.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPool.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/IPermissionEntity.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/PermissionEntity.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupDeletedEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupUpdatedEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerUpdatedEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/IPermissionGroup.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/PermissionGroup.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/IPermissionGroupManager.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/PermissionGroupManager.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/CloudListener.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionFilesPriorityUpdater.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionModule.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionGroupCommandSuggestionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionGroupConfigsLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfigLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketInGetDefaultGroupName.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketOutGetDefaultGroupName.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/permission/Permission.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/IPermissionPlayer.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/OfflinePlayerExtension.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PermissionPlayer.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PlayerPermissionGroupInfo.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/manager/IPermissionPlayerManager.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeeListener.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeePluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/BukkitCloudPermissibleBase.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotListener.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/util/ReflectionUtils.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPermissionProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/bungee.yml create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/plugin.yml create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-permission/src/main/resources/velocity-plugin.json create mode 100644 simplecloud-modules/simplecloud-module-permission/src/test/kotlin/eu/thesimplecloud/permission/PermissionTest.kt create mode 100644 simplecloud-modules/simplecloud-module-placeholders/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/manager/PlaceholdersModule.kt create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/BukkitPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/StringExtension.kt create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/placeholderapi/PlaceholderHook.kt create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/resources/plugin.yml create mode 100644 simplecloud-modules/simplecloud-module-placeholders/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-proxy/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/Config.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/DefaultConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/MotdConfiguration.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/ProxyGroupConfiguration.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/TablistConfiguration.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/extensions/ListExtension.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/GroupCreateListener.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/MaintenanceToggleListener.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/ProxyModule.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/commands/ProxyCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/ConfigConverter.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/MiniMessageConfigConverter.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/MessageConverter.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SingleColorCodeReplacer.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SpecialColorCodeReplacer.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/ProxyHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/BungeePluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/listener/BungeeListener.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/VelocityPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/listener/VelocityListener.kt create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/resources/plugin.yml create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-proxy/src/main/resources/velocity-plugin.json create mode 100644 simplecloud-modules/simplecloud-module-rest/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/RestModule.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestBody.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestMapping.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestParam.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestPathParam.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestType.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestingUser.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RestController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/WebExclude.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/AuthService.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/JwtProvider.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/Roles.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/AuthController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/LoginDto.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/User.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/Permission.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/IPermissionEntity.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/PermissionEntity.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfigLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/ControllerHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IExceptionHelper.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/RequestMethodData.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/UserController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/CommandDto.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ErrorDto.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/PathDto.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ResultDto.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/filemanager/FileManagerController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupActionController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerActionController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceActionController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/template/TemplateController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/uptime/UptimeController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/version/VersionController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/wrapper/WrapperController.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/ElementAlreadyExistException.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/NullResultException.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/JavalinRequestHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/RestServer.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/SingleRequestProcessor.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/util/ContextClassLoaderChanger.kt create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-rest/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-serviceselection/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/AbstractServiceViewer.kt create mode 100644 simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewGroupManager.kt create mode 100644 simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewManager.kt create mode 100644 simplecloud-modules/simplecloud-module-serviceselection/src/test/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceSelectionTest.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/SignModuleConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayouts.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayoutsContainer.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/LayoutType.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignFrame.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayout.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayoutContainer.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/settings/CloudSignSettingsContainer.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSign.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSignContainer.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModule.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModuleConfigPersistence.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/command/SignCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitCloudSign.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitPluginMain.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/Placeholder.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignAPI.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignServiceViewManager.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/command/CloudSignsCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignAddedEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignRemovedEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignUpdatedEvent.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/listener/InteractListener.kt create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/de.json create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/en.json create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/resources/plugin.yml create mode 100644 simplecloud-modules/simplecloud-module-sign/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-statistics/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/StatisticsModule.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/rest/timed/TimedValueController.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/Timed.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValue.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValueCollectorManager.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/CPUUsageTimedCollector.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/ITimedValueCollector.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/MemoryTimedCollector.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/PlayerCountTimedCollector.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/CloudServiceStartListener.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/PlayerConnectListener.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/ITimedValueStore.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/MongoTimedValueStore.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/SQLTimedValueStore.kt create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-statistics/src/main/resources/updater.json create mode 100644 simplecloud-modules/simplecloud-module-support/build.gradle create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFile.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFileCreator.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfig.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfigLoader.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/GroupFileCreator.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceFileCreator.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceVersionFileCreator.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/WrapperFileCreator.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/SupportModule.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/command/DumpCommand.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/handler/UploadHandler.kt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/resources/module.json create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/resources/temp/dump-file.txt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/resources/temp/group.txt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/resources/temp/service.txt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/resources/temp/static-jars.txt create mode 100644 simplecloud-modules/simplecloud-module-support/src/main/resources/temp/wrapper.txt create mode 100644 simplecloud-plugin/build.gradle create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/ICloudServicePlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/LocationExtension.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/PlayerExtensions.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/SyncExtension.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudAPIImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceGroupManagerImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceManagerImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CommandExecuteManagerImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/EventManagerImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractCloudPlayerManagerProxy.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractServiceCloudPlayerManager.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/listener/CloudListener.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketInGetPlayerOnlineStatus.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutCreateCloudPlayer.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutGetTabSuggestions.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerConnectToServer.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerExecuteCommand.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerLoginRequest.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutTeleportOtherService.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/CancelType.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ICloudProxyPlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ProxyEventHandler.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/BungeeComponentExtensions.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/CloudBungeePlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/LobbyConnector.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/ReconnectHandlerImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/command/BungeeCommand.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/BungeeListener.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/CloudPlayerDisconnectListener.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/CloudVelocityPlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/LobbyConnector.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/commands/VelocityCommand.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/CloudPlayerDisconnectListener.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/VelocityListener.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/CloudSpigotPlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/ICloudServerPlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/ReloadCommandBlocker.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/SpigotListener.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/CloudPlugin.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/ConnectionHandlerImpl.kt create mode 100644 simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/UsedMemoryUpdater.kt create mode 100644 simplecloud-plugin/src/main/resources/bungee.yml create mode 100644 simplecloud-plugin/src/main/resources/plugin.yml create mode 100644 simplecloud-plugin/src/main/resources/velocity-plugin.json create mode 100644 simplecloud-runner/build.gradle create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoader.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoaderInitMain.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerFileProvider.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/AdvancedCloudDependency.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/CloudDependency.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/DependencyLoaderStartup.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/SimpleDependencyDownloader.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/Downloader.kt create mode 100644 simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/WebContentLoader.kt create mode 100644 simplecloud-updater/build.gradle create mode 100644 simplecloud-updater/src/main/java/eu/thesimplecloud/updater/UpdaterMain.java create mode 100644 start-files/start.bat create mode 100644 start-files/start.sh diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml new file mode 100644 index 000000000..67133c86d --- /dev/null +++ b/.github/workflows/gradle-build.yml @@ -0,0 +1,73 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle + +name: Build and Publish + +on: + #schedule: + # - cron: '37 7 * * *' + push: + branches: [ "dev/2.0", "master" ] + # Publish semver tags as releases. + #tags: [ 'v*.*.*' ] + #pull_request: + # branches: [ "development", "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: shadowJar + + - name: Copy files + run: | + mkdir -p temp + mkdir temp/modules/ + mkdir temp/storage/ + mkdir temp/storage/pluginJars/ + cp start-files/*.* temp/ + cp simplecloud-modules/**/build/libs/SimpleCloud-*.jar temp/modules/ + cp simplecloud-runner/build/libs/runner.jar temp/runner.jar + cp simplecloud-base/build/libs/base.jar temp/storage/base.jar + cp simplecloud-plugin/build/libs/*.jar temp/storage/pluginJars/ + cp simplecloud-dependency-loader/build/libs/dependency-loader.jar temp/storage/dependency-loader.jar + cp simplecloud-launcher/build/libs/launcher.jar temp/launcher.jar + rm temp/modules/SimpleCloud-Chat+Tab.jar + rm temp/modules/SimpleCloud-ServiceSelection.jar + rm temp/modules/SimpleCloud-CloudFlare.jar + + - name: Upload zip + uses: actions/upload-artifact@v3 + with: + name: SimpleCloud-Latest + path: temp/ + + # The USERNAME and TOKEN need to correspond to the credentials environment variables used in + # the publishing section of your build.gradle + - name: Publish + uses: gradle/gradle-build-action@v2 + with: + arguments: publish + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..93526bc00 --- /dev/null +++ b/.gitignore @@ -0,0 +1,79 @@ +########################## +## Java +########################## +*.class +.mtj.tmp/ +*.jar +*.war +*.ear +hs_err_pid* + +########################## +## Maven +########################## +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties + +########################## +## Gradle +########################## +.gradle +/build/ +gradle-app.setting +!gradle-wrapper.jar +.gradletasknamecache + +########################## +## IntelliJ +########################## +*.iml +.idea/ +*.ipr +*.iws +out/ +.idea_modules/ + +########################## +## Eclipse +########################## +.metadata +.classpath +.project +.settings/ +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.loadpath + +########################## +## NetBeans +########################## +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +nb-configuration.xml + +########################## +## OS X +########################## +.DS_Store + +########################## +## SimpleCloud +########################## +logs/ +launcher.json +storage/ +local-repo/ +modules/ \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..6b1b9ffe2 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,58 @@ +pipeline { + agent any + options { + buildDiscarder logRotator(numToKeepStr: '10') + } + stages { + stage('Clean') { + steps { + sh 'chmod +x ./gradlew'; + sh './gradlew clean'; + } + } + stage('Build') { + steps { + sh './gradlew build'; + } + } + stage('Test') { + steps { + sh './gradlew test'; + junit '**/build/test-results/test/*.xml'; + } + } + stage('Create zip') { + steps { + sh 'rm -f SimpleCloud-Latest.zip'; + sh 'mkdir -p temp' + sh 'mkdir temp/modules/' + sh 'mkdir temp/storage/' + sh 'cp start-files/*.* temp/'; + sh 'cp simplecloud-modules/**/build/libs/*.jar temp/modules/'; + sh 'cp simplecloud-runner/build/libs/runner.jar temp/runner.jar'; + sh 'cp simplecloud-base/build/libs/base.jar temp/storage/base.jar'; + sh 'rm temp/modules/SimpleCloud-Chat+Tab.jar'; + sh 'rm temp/modules/SimpleCloud-ServiceSelection.jar'; + sh 'rm temp/modules/SimpleCloud-CloudFlare.jar'; + zip archive: true, dir: 'temp', glob: '', zipFile: 'SimpleCloud-Latest.zip'; + sh 'rm -r temp/'; + } + } + stage('Sources') { + steps { + sh './gradlew sourceJar'; + } + } + stage('Publish') { + when { + anyOf { + branch 'master'; + branch 'dev/2.0'; + } + } + steps { + sh './gradlew publish'; + } + } + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..466e3fc26 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2022 The SimpleCloud authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..2811f7a9a --- /dev/null +++ b/README.md @@ -0,0 +1,243 @@ +

+ Logo +

+ +

+

+ A simple alternative to other minecraft cloud systems +
+ SpigotMC + · + Repository + · + Dashboard + · + Jenkins + · + Discord + · + Teamspeak +

+ +

+ +
+
+ +
+ Overview +
    +
  1. + Getting Started + +
  2. +
  3. Features
  4. +
  5. Dashboard
  6. +
  7. + Modules + +
  8. +
+
+ +
+ +## Getting Started + +### Requirements + +* **Java 8** or higher +* **[MongoDB](https://www.mongodb.com/cloud/atlas/lp/try2-de?utm_source=google&utm_campaign=gs_emea_germany_search_core_brand_atlas_desktop&utm_term=mongodb&utm_medium=cpc_paid_search&utm_ad=e&utm_ad_campaign_id=12212624524&gclid=Cj0KCQjw5auGBhDEARIsAFyNm9EkpiB2K-5CMNxHkHcY7VbdNE_4HrbwDOSrMmjgNAve270Hnd9pjRoaAqFgEALw_wcB)** + or **[SQL](https://go.mariadb.com/download-mariadb-server-community.html?utm_source=google&utm_medium=ppc&utm_campaign=MKG-Search-Google-Branded-EMEA-bd-Server-DL&gclid=Cj0KCQjw5auGBhDEARIsAFyNm9HBSH7xv8vFObvU9Xk8-bgYskrjfU53aBSkyehaGOxQQx2veRbC6-caAtJyEALw_wcB)** + database +* min. **2GB** Memory and **2 virtual cores** + +### Installation + +
    +
  1. Download the cloud on SpigotMC
  2. +
  3. Unzip the folder and execute the start file
  4. +
  5. Follow the setup instructions
  6. +
  7. Connect a wrapper to your manager. It is recommended to use the InternalWrapperModule for this. You can find it below.
  8. +
  9. Create your first group by typing create into the console
  10. +
  11. For more information type help
  12. +
  13. Have fun :D
  14. +
+ +
+ +## Features + +* Dashboard +* Language-System +* Multi-Root +* Multi-Proxy +* Module-System +* **MongoDB** and **SQL** support +* Powerful **API** +* Powerful **REST-API** +* Support for **Spigot**, **BungeeCord** and **Velocity** +* Template-System + +
+ +## Dashboard + +SimpleCloud provides a **Dashboard accessible** for every user. +The domain for the **Dashboard** is: **http://dashboard-nossl.thesimplecloud.eu**. +Now you have to enter the **IP-Address** of your server follwed by the port of the **REST-Module.** +
+
+The default port of the **REST-Module** is **8585**. So an ip would be **55.55.55.55:8585**.
+The username and password can be found in **"modules/rest/users.json"** + +
+ +## Modules + +SimpleCloud provides some modules by default. + +### Internal-Wrapper + +The **Internal-Wrapper Module** starts a wrapper every time the manager of the cloud gets started. +This wrapper does only run when the manager is running. It connects **automatically** with no need to set it up. +The wrapper will be automatically named **"InternalWrapper"** and it will have **2GB of memory**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-internalwrapper/2.4.0/simplecloud-module-internalwrapper-2.4.0.jar) +
+ +To edit the memory of the wrapper you can use the command:
+``edit wrapper InternalWrapper maxMemory `` + +
+ +### Signs + +The **Sign Module** is used to show available services for players in the lobby via a **sign**. +The players can click on that sign and will be sent to the server. The layout of the signs is **fully customizable**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-sign/2.4.0/simplecloud-module-sign-2.4.0.jar) + +![SignModule](https://i.imgur.com/w534aZG.gif "SignModule") + +
+ +### Permissions + +With the **Permission Module**, you can easily manage your permissions. +You can define groups and add permissions to them. You can also add permissions to single users. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-permission/2.4.0/simplecloud-module-permission-2.4.0.jar) + +![PermissionModule](https://i.imgur.com/mjqCmjq.png"PermissionModule") + +
+ +### Proxy + +The **Proxy Module** is used to manage your proxies. +It controls the **MOTD**, **Tablist**, **maintenance** and the **online count**. +The online count of proxies of one group will be summed up and displayed in the player info. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-proxy/2.4.0/simplecloud-module-proxy-2.4.0.jar) + +![ProxyModuleTab](https://i.imgur.com/2djSS9l.jpg "ProxyModuleTab") + +![ProxyModuleMotd](https://i.imgur.com/dkuxYM7.png "ProxyModuleMotd") + +![ProxyModuleMotdMaintenance](https://i.imgur.com/eCSXSJo.png "ProxyModuleMotdMaintenance") + +
+ +**Permissions:** +
+ +```` +Maintenance join: cloud.maintenance.join +Full join: cloud.full.join +```` + +
+ +### Hub + +The **Hub Module** provides a hub command for players to switch to a **lobby server**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-hubcommand/2.4.0/simplecloud-module-hubcommand-2.4.0.jar) + +
+ +### Notify + +The **Notify Module** sends notifications to players that have the required permission when a server gets **started** +or **stopped**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-notify/2.4.0/simplecloud-module-notify-2.4.0.jar) + +![NotifyModule](https://i.imgur.com/7lcjXbN.jpg "NotifyModule") + +
+ +**Permissions:** +
+ +```` +cloud.module.notify.messages +```` + +
+ +### REST + +The **REST Module** provides a **restful API**. It is necessary for the **dashboard**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-rest/2.4.0/simplecloud-module-rest-2.4.0.jar) + +
+ +### Statistics + +The **Statistics Module** saves some statistics of the cloud. The data is displayed on the **dashboard**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-statistics/2.4.0/simplecloud-module-statistics-2.4.0.jar) + +
+ +### Chat + Tab + +The **Chat + Tab Module** provides **prefixes** and **suffixes** in the tablist and adds a **chat configuration**. +
+You can **download** +it [here](https://repo.thesimplecloud.eu/artifactory/gradle-release-local/eu/thesimplecloud/simplecloud/simplecloud-module-chat-tab/2.4.0/simplecloud-module-chat-tab-2.4.0.jar) + +Special Thanks To: +------------- + +[![YourKit-Logo](https://www.yourkit.com/images/yklogo.png)](https://www.yourkit.com/) + +[YourKit](https://www.yourkit.com/) supports open source projects with innovative and intelligent tools +for monitoring and profiling Java and .NET applications. +YourKit is the creator of YourKit Java Profiler, +YourKit .NET Profiler, +and YourKit YouMonitor. diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..3d9f6c3ab --- /dev/null +++ b/build.gradle @@ -0,0 +1,168 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.8.22' + id "com.github.johnrengelman.shadow" version "8.1.1" + id 'org.jetbrains.dokka' version '0.10.1' +} + +allprojects { + + group 'eu.thesimplecloud.simplecloud' + version '2.5.0-SNAPSHOT' + + repositories { + mavenCentral() + jcenter() + + maven { url 'https://repository.derklaro.dev/releases' } + maven { url 'https://jitpack.io' } + maven { + url "https://repo.thesimplecloud.eu/artifactory/gradle-release-local/" + } + + maven { + url "https://libraries.minecraft.net" + } + + maven { + name = "papermc" + url = uri("https://repo.papermc.io/repository/maven-public/") + } + + maven { + name 'spongepowered' + url 'https://repo.spongepowered.org/maven' + } + + maven { + name 'bungeecord-repo' + url 'https://oss.sonatype.org/content/repositories/snapshots' + } + + maven { + name 'spigotmc-repo' + url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + } + + } + + project.ext { + depedencyClientServerAPIVersion = '4.1.17' + dependencyCommonsIOVersion = '2.11.0' + dependencyKotlinCouroutinesVersion = '1.5.2' + dependencyNettyVersion = '4.1.71.Final' + dependencyGuavaVersion = '31.0.1-jre' + dependencyKMongoVersion = '4.4.0' + } + + buildscript { + repositories { + mavenLocal() + } + } +} + +subprojects { + + apply plugin: 'java' + apply plugin: 'java-library' + apply plugin: 'maven-publish' + apply plugin: 'org.jetbrains.kotlin.jvm' + apply plugin: 'org.jetbrains.dokka' + apply plugin: "com.github.johnrengelman.shadow" + + sourceCompatibility = 8 + targetCompatibility = 8 + + task sourcesJar(type: Jar, dependsOn: classes) { + archiveClassifier.set('sources') + from sourceSets.main.allSource + } + + dependencies { + testApi group: 'junit', name: 'junit', version: '4.13' + compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + testCompileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + compileOnly(group: 'eu.thesimplecloud.clientserverapi', name: 'clientserverapi', version: depedencyClientServerAPIVersion) { + transitive = false + } + compileOnly(group: 'eu.thesimplecloud.jsonlib', name: 'json-lib', version: "1.0.8") { + transitive = false + } + + testApi(group: 'eu.thesimplecloud.clientserverapi', name: 'clientserverapi', version: depedencyClientServerAPIVersion) + testApi(group: 'eu.thesimplecloud.jsonlib', name: 'json-lib', version: "1.0.8") + + compileOnly group: 'commons-io', name: 'commons-io', version: dependencyCommonsIOVersion + compileOnly group: 'com.google.guava', name: 'guava', version: dependencyGuavaVersion + compileOnly group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion + compileOnly group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: dependencyKotlinCouroutinesVersion + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + + } + + compileKotlin { + kotlinOptions.jvmTarget = "1.8" + } + compileTestKotlin { + kotlinOptions.jvmTarget = "1.8" + } + + jar { + manifest { + attributes( + 'Implementation-Version': project.version, + ) + } + } + + publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact sourcesJar + } + } + repositories { + maven { + if (project.version.endsWith("SNAPSHOT")) { + url 'https://repo.thesimplecloud.eu/artifactory/list/gradle-dev-local/' + } else { + url 'https://repo.thesimplecloud.eu/artifactory/list/gradle-release-local//' + } + + credentials { + username = project.hasProperty("mavenUser") ? project.property("mavenUser") : System.getenv("MAVEN_USERNAME") + password = project.hasProperty("mavenPassword") ? project.property("mavenPassword") : System.getenv("MAVEN_PASSWORD") + } + } + } + } + + dokka { + outputFormat = 'html' + outputDirectory = "$buildDir/dokka" + } + +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q
Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ zw`1S}(D?mUXu_C{wupRS-jiX~w=Uqqhf|Vb3Cm9L=T+w91Cu^ z*&Ty%sN?x*h~mJc4g~k{xD4ZmF%FXZNC;oVDwLZ_WvrnzY|{v8hc1nmx4^}Z;yriXsAf+Lp+OFLbR!&Ox?xABwl zu8w&|5pCxmu#$?Cv2_-Vghl2LZ6m7}VLEfR5o2Ou$x02uA-%QB2$c(c1rH3R9hesc zfpn#oqpbKuVsdfV#cv@5pV4^f_!WS+F>SV6N0JQ9E!T90EX((_{bSSFv9ld%I0&}9 zH&Jd4MEX1e0iqDtq~h?DBrxQX1iI0lIs<|kB$Yrh&cpeK0-^K%=FBsCBT46@h#yi!AyDq1V(#V}^;{{V*@T4WJ&U-NTq43w=|K>z8%pr_nC>%C(Wa_l78Ufib$r8Od)IIN=u>417 z`Hl{9A$mI5A(;+-Q&$F&h-@;NR>Z<2U;Y21>>Z;s@0V@SbkMQQj%_;~+qTuQ?c|AV zcWm3XZQHhP&R%QWarS%mJ!9R^&!_)*s(v+VR@I#QrAT}`17Y+l<`b-nvmDNW`De%y zrwTZ9EJrj1AFA>B`1jYDow}~*dfPs}IZMO3=a{Fy#IOILc8F0;JS4x(k-NSpbN@qM z`@aE_e}5{!$v3+qVs7u?sOV(y@1Os*Fgu`fCW9=G@F_#VQ%xf$hj0~wnnP0$hFI+@ zkQj~v#V>xn)u??YutKsX>pxKCl^p!C-o?+9;!Nug^ z{rP!|+KsP5%uF;ZCa5F;O^9TGac=M|=V z_H(PfkV1rz4jl?gJ(ArXMyWT4y(86d3`$iI4^l9`vLdZkzpznSd5Ikfrs8qcSy&>z zTIZgWZGXw0n9ibQxYWE@gI0(3#KA-dAdPcsL_|hg2@~C!VZDM}5;v_Nykfq!*@*Zf zE_wVgx82GMDryKO{U{D>vSzSc%B~|cjDQrt5BN=Ugpsf8H8f1lR4SGo#hCuXPL;QQ z#~b?C4MoepT3X`qdW2dNn& zo8)K}%Lpu>0tQei+{>*VGErz|qjbK#9 zvtd8rcHplw%YyQCKR{kyo6fgg!)6tHUYT(L>B7er5)41iG`j$qe*kSh$fY!PehLcD zWeKZHn<492B34*JUQh=CY1R~jT9Jt=k=jCU2=SL&&y5QI2uAG2?L8qd2U(^AW#{(x zThSy=C#>k+QMo^7caQcpU?Qn}j-`s?1vXuzG#j8(A+RUAY})F@=r&F(8nI&HspAy4 z4>(M>hI9c7?DCW8rw6|23?qQMSq?*Vx?v30U%luBo)B-k2mkL)Ljk5xUha3pK>EEj z@(;tH|M@xkuN?gsz;*bygizwYR!6=(Xgcg^>WlGtRYCozY<rFX2E>kaZo)O<^J7a`MX8Pf`gBd4vrtD|qKn&B)C&wp0O-x*@-|m*0egT=-t@%dD zgP2D+#WPptnc;_ugD6%zN}Z+X4=c61XNLb7L1gWd8;NHrBXwJ7s0ce#lWnnFUMTR& z1_R9Fin4!d17d4jpKcfh?MKRxxQk$@)*hradH2$3)nyXep5Z;B z?yX+-Bd=TqO2!11?MDtG0n(*T^!CIiF@ZQymqq1wPM_X$Iu9-P=^}v7npvvPBu!d$ z7K?@CsA8H38+zjA@{;{kG)#AHME>Ix<711_iQ@WWMObXyVO)a&^qE1GqpP47Q|_AG zP`(AD&r!V^MXQ^e+*n5~Lp9!B+#y3#f8J^5!iC@3Y@P`;FoUH{G*pj*q7MVV)29+j z>BC`a|1@U_v%%o9VH_HsSnM`jZ-&CDvbiqDg)tQEnV>b%Ptm)T|1?TrpIl)Y$LnG_ zzKi5j2Fx^K^PG1=*?GhK;$(UCF-tM~^=Z*+Wp{FSuy7iHt9#4n(sUuHK??@v+6*|10Csdnyg9hAsC5_OrSL;jVkLlf zHXIPukLqbhs~-*oa^gqgvtpgTk_7GypwH><53riYYL*M=Q@F-yEPLqQ&1Sc zZB%w}T~RO|#jFjMWcKMZccxm-SL)s_ig?OC?y_~gLFj{n8D$J_Kw%{r0oB8?@dWzn zB528d-wUBQzrrSSLq?fR!K%59Zv9J4yCQhhDGwhptpA5O5U?Hjqt>8nOD zi{)0CI|&Gu%zunGI*XFZh(ix)q${jT8wnnzbBMPYVJc4HX*9d^mz|21$=R$J$(y7V zo0dxdbX3N#=F$zjstTf*t8vL)2*{XH!+<2IJ1VVFa67|{?LP&P41h$2i2;?N~RA30LV`BsUcj zfO9#Pg1$t}7zpv#&)8`mis3~o+P(DxOMgz-V*(?wWaxi?R=NhtW}<#^Z?(BhSwyar zG|A#Q7wh4OfK<|DAcl9THc-W4*>J4nTevsD%dkj`U~wSUCh15?_N@uMdF^Kw+{agk zJ`im^wDqj`Ev)W3k3stasP`88-M0ZBs7;B6{-tSm3>I@_e-QfT?7|n0D~0RRqDb^G zyHb=is;IwuQ&ITzL4KsP@Z`b$d%B0Wuhioo1CWttW8yhsER1ZUZzA{F*K=wmi-sb#Ju+j z-l@In^IKnb{bQG}Ps>+Vu_W#grNKNGto+yjA)?>0?~X`4I3T@5G1)RqGUZuP^NJCq&^HykuYtMDD8qq+l8RcZNJsvN(10{ zQ1$XcGt}QH-U^WU!-wRR1d--{B$%vY{JLWIV%P4-KQuxxDeJaF#{eu&&r!3Qu{w}0f--8^H|KwE>)ORrcR+2Qf zb})DRcH>k0zWK8@{RX}NYvTF;E~phK{+F;MkIP$)T$93Ba2R2TvKc>`D??#mv9wg$ zd~|-`Qx5LwwsZ2hb*Rt4S9dsF%Cny5<1fscy~)d;0m2r$f=83<->c~!GNyb!U)PA; zq^!`@@)UaG)Ew(9V?5ZBq#c%dCWZrplmuM`o~TyHjAIMh0*#1{B>K4po-dx$Tk-Cq z=WZDkP5x2W&Os`N8KiYHRH#UY*n|nvd(U>yO=MFI-2BEp?x@=N<~CbLJBf6P)}vLS?xJXYJ2^<3KJUdrwKnJnTp{ zjIi|R=L7rn9b*D#Xxr4*R<3T5AuOS+#U8hNlfo&^9JO{VbH!v9^JbK=TCGR-5EWR@ zN8T-_I|&@A}(hKeL4_*eb!1G8p~&_Im8|wc>Cdir+gg90n1dw?QaXcx6Op_W1r=axRw>4;rM*UOpT#Eb9xU1IiWo@h?|5uP zka>-XW0Ikp@dIe;MN8B01a7+5V@h3WN{J=HJ*pe0uwQ3S&MyWFni47X32Q7SyCTNQ z+sR!_9IZa5!>f&V$`q!%H8ci!a|RMx5}5MA_kr+bhtQy{-^)(hCVa@I!^TV4RBi zAFa!Nsi3y37I5EK;0cqu|9MRj<^r&h1lF}u0KpKQD^5Y+LvFEwM zLU@@v4_Na#Axy6tn3P%sD^5P#<7F;sd$f4a7LBMk zGU^RZHBcxSA%kCx*eH&wgA?Qwazm8>9SCSz_!;MqY-QX<1@p$*T8lc?@`ikEqJ>#w zcG``^CoFMAhdEXT9qt47g0IZkaU)4R7wkGs^Ax}usqJ5HfDYAV$!=6?>J6+Ha1I<5 z|6=9soU4>E))tW$<#>F ziZ$6>KJf0bPfbx_)7-}tMINlc=}|H+$uX)mhC6-Hz+XZxsKd^b?RFB6et}O#+>Wmw9Ec9) z{q}XFWp{3@qmyK*Jvzpyqv57LIR;hPXKsrh{G?&dRjF%Zt5&m20Ll?OyfUYC3WRn{cgQ?^V~UAv+5 z&_m#&nIwffgX1*Z2#5^Kl4DbE#NrD&Hi4|7SPqZ}(>_+JMz=s|k77aEL}<=0Zfb)a z%F(*L3zCA<=xO)2U3B|pcTqDbBoFp>QyAEU(jMu8(jLA61-H!ucI804+B!$E^cQQa z)_ERrW3g!B9iLb3nn3dlkvD7KsY?sRvls3QC0qPi>o<)GHx%4Xb$5a3GBTJ(k@`e@ z$RUa^%S15^1oLEmA=sayrP5;9qtf!Z1*?e$ORVPsXpL{jL<6E)0sj&swP3}NPmR%FM?O>SQgN5XfHE< zo(4#Cv11(%Nnw_{_Ro}r6=gKd{k?NebJ~<~Kv0r(r0qe4n3LFx$5%x(BKvrz$m?LG zjLIc;hbj0FMdb9aH9Lpsof#yG$(0sG2%RL;d(n>;#jb!R_+dad+K;Ccw!|RY?uS(a zj~?=&M!4C(5LnlH6k%aYvz@7?xRa^2gml%vn&eKl$R_lJ+e|xsNfXzr#xuh(>`}9g zLHSyiFwK^-p!;p$yt7$F|3*IfO3Mlu9e>Dpx8O`37?fA`cj`C0B-m9uRhJjs^mRp# zWB;Aj6|G^1V6`jg7#7V9UFvnB4((nIwG?k%c7h`?0tS8J3Bn0t#pb#SA}N-|45$-j z$R>%7cc2ebAClXc(&0UtHX<>pd)akR3Kx_cK+n<}FhzmTx!8e9^u2e4%x{>T6pQ`6 zO182bh$-W5A3^wos0SV_TgPmF4WUP-+D25KjbC{y_6W_9I2_vNKwU(^qSdn&>^=*t z&uvp*@c8#2*paD!ZMCi3;K{Na;I4Q35zw$YrW5U@Kk~)&rw;G?d7Q&c9|x<Hg|CNMsxovmfth*|E*GHezPTWa^Hd^F4!B3sF;)? z(NaPyAhocu1jUe(!5Cy|dh|W2=!@fNmuNOzxi^tE_jAtzNJ0JR-avc_H|ve#KO}#S z#a(8secu|^Tx553d4r@3#6^MHbH)vmiBpn0X^29xEv!Vuh1n(Sr5I0V&`jA2;WS|Y zbf0e}X|)wA-Pf5gBZ>r4YX3Mav1kKY(ulAJ0Q*jB)YhviHK)w!TJsi3^dMa$L@^{` z_De`fF4;M87vM3Ph9SzCoCi$#Fsd38u!^0#*sPful^p5oI(xGU?yeYjn;Hq1!wzFk zG&2w}W3`AX4bxoVm03y>ts{KaDf!}b&7$(P4KAMP=vK5?1In^-YYNtx1f#}+2QK@h zeSeAI@E6Z8a?)>sZ`fbq9_snl6LCu6g>o)rO;ijp3|$vig+4t} zylEo7$SEW<_U+qgVcaVhk+4k+C9THI5V10qV*dOV6pPtAI$)QN{!JRBKh-D zk2^{j@bZ}yqW?<#VVuI_27*cI-V~sJiqQv&m07+10XF+#ZnIJdr8t`9s_EE;T2V;B z4UnQUH9EdX%zwh-5&wflY#ve!IWt0UE-My3?L#^Bh%kcgP1q{&26eXLn zTkjJ*w+(|_>Pq0v8{%nX$QZbf)tbJaLY$03;MO=Ic-uqYUmUCuXD>J>o6BCRF=xa% z3R4SK9#t1!K4I_d>tZgE>&+kZ?Q}1qo4&h%U$GfY058s%*=!kac{0Z+4Hwm!)pFLR zJ+5*OpgWUrm0FPI2ib4NPJ+Sk07j(`diti^i#kh&f}i>P4~|d?RFb#!JN)~D@)beox}bw?4VCf^y*`2{4`-@%SFTry2h z>9VBc9#JxEs1+0i2^LR@B1J`B9Ac=#FW=(?2;5;#U$0E0UNag_!jY$&2diQk_n)bT zl5Me_SUvqUjwCqmVcyb`igygB_4YUB*m$h5oeKv3uIF0sk}~es!{D>4r%PC*F~FN3owq5e0|YeUTSG#Vq%&Gk7uwW z0lDo#_wvflqHeRm*}l?}o;EILszBt|EW*zNPmq#?4A+&i0xx^?9obLyY4xx=Y9&^G;xYXYPxG)DOpPg!i_Ccl#3L}6xAAZzNhPK1XaC_~ z!A|mlo?Be*8Nn=a+FhgpOj@G7yYs(Qk(8&|h@_>w8Y^r&5nCqe0V60rRz?b5%J;GYeBqSAjo|K692GxD4` zRZyM2FdI+-jK2}WAZTZ()w_)V{n5tEb@>+JYluDozCb$fA4H)$bzg(Ux{*hXurjO^ zwAxc+UXu=&JV*E59}h3kzQPG4M)X8E*}#_&}w*KEgtX)cU{vm9b$atHa;s>| z+L6&cn8xUL*OSjx4YGjf6{Eq+Q3{!ZyhrL&^6Vz@jGbI%cAM9GkmFlamTbcQGvOlL zmJ?(FI)c86=JEs|*;?h~o)88>12nXlpMR4@yh%qdwFNpct;vMlc=;{FSo*apJ;p}! zAX~t;3tb~VuP|ZW;z$=IHf->F@Ml)&-&Bnb{iQyE#;GZ@C$PzEf6~q}4D>9jic@mTO5x76ulDz@+XAcm35!VSu zT*Gs>;f0b2TNpjU_BjHZ&S6Sqk6V1370+!eppV2H+FY!q*n=GHQ!9Rn6MjY!Jc77A zG7Y!lFp8?TIHN!LXO?gCnsYM-gQxsm=Ek**VmZu7vnuufD7K~GIxfxbsQ@qv2T zPa`tvHB$fFCyZl>3oYg?_wW)C>^_iDOc^B7klnTOoytQH18WkOk)L2BSD0r%xgRSW zQS9elF^?O=_@|58zKLK;(f77l-Zzu}4{fXed2saq!5k#UZAoDBqYQS{sn@j@Vtp|$ zG%gnZ$U|9@u#w1@11Sjl8ze^Co=)7yS(}=;68a3~g;NDe_X^}yJj;~s8xq9ahQ5_r zxAlTMnep*)w1e(TG%tWsjo3RR;yVGPEO4V{Zp?=a_0R#=V^ioQu4YL=BO4r0$$XTX zZfnw#_$V}sDAIDrezGQ+h?q24St0QNug_?{s-pI(^jg`#JRxM1YBV;a@@JQvH8*>> zIJvku74E0NlXkYe_624>znU0J@L<-c=G#F3k4A_)*;ky!C(^uZfj%WB3-*{*B$?9+ zDm$WFp=0(xnt6`vDQV3Jl5f&R(Mp};;q8d3I%Kn>Kx=^;uSVCw0L=gw53%Bp==8Sw zxtx=cs!^-_+i{2OK`Q;913+AXc_&Z5$@z3<)So0CU3;JAv=H?@Zpi~riQ{z-zLtVL z!oF<}@IgJp)Iyz1zVJ42!SPHSkjYNS4%ulVVIXdRuiZ@5Mx8LJS}J#qD^Zi_xQ@>DKDr-_e#>5h3dtje*NcwH_h;i{Sx7}dkdpuW z(yUCjckQsagv*QGMSi9u1`Z|V^}Wjf7B@q%j2DQXyd0nOyqg%m{CK_lAoKlJ7#8M} z%IvR?Vh$6aDWK2W!=i?*<77q&B8O&3?zP(Cs@kapc)&p7En?J;t-TX9abGT#H?TW? ztO5(lPKRuC7fs}zwcUKbRh=7E8wzTsa#Z{a`WR}?UZ%!HohN}d&xJ=JQhpO1PI#>X zHkb>pW04pU%Bj_mf~U}1F1=wxdBZu1790>3Dm44bQ#F=T4V3&HlOLsGH)+AK$cHk6 zia$=$kog?)07HCL*PI6}DRhpM^*%I*kHM<#1Se+AQ!!xyhcy6j7`iDX7Z-2i73_n# zas*?7LkxS-XSqv;YBa zW_n*32D(HTYQ0$feV_Fru1ZxW0g&iwqixPX3=9t4o)o|kOo79V$?$uh?#8Q8e>4e)V6;_(x&ViUVxma+i25qea;d-oK7ouuDsB^ab{ zu1qjQ%`n56VtxBE#0qAzb7lph`Eb-}TYpXB!H-}3Ykqyp`otprp7{VEuW*^IR2n$Fb99*nAtqT&oOFIf z@w*6>YvOGw@Ja?Pp1=whZqydzx@9X4n^2!n83C5{C?G@|E?&$?p*g68)kNvUTJ)I6 z1Q|(#UuP6pj78GUxq11m-GSszc+)X{C2eo-?8ud9sB=3(D47v?`JAa{V(IF zPZQ_0AY*9M97>Jf<o%#O_%Wq}8>YM=q0|tGY+hlXcpE=Z4Od z`NT7Hu2hnvRoqOw@g1f=bv`+nba{GwA$Ak0INlqI1k<9!x_!sL()h?hEWoWrdU3w` zZ%%)VR+Bc@_v!C#koM1p-3v_^L6)_Ktj4HE>aUh%2XZE@JFMOn)J~c`_7VWNb9c-N z2b|SZMR4Z@E7j&q&9(6H3yjEu6HV7{2!1t0lgizD;mZ9$r(r7W5G$ky@w(T_dFnOD z*p#+z$@pKE+>o@%eT(2-p_C}wbQ5s(%Sn_{$HDN@MB+Ev?t@3dPy`%TZ!z}AThZSu zN<1i$siJhXFdjV zP*y|V<`V8t=h#XTRUR~5`c`Z9^-`*BZf?WAehGdg)E2Je)hqFa!k{V(u+(hTf^Yq& zoruUh2(^3pe)2{bvt4&4Y9CY3js)PUHtd4rVG57}uFJL)D(JfSIo^{P=7liFXG zq5yqgof0V8paQcP!gy+;^pp-DA5pj=gbMN0eW=-eY+N8~y+G>t+x}oa!5r>tW$xhI zPQSv=pi;~653Gvf6~*JcQ%t1xOrH2l3Zy@8AoJ+wz@daW@m7?%LXkr!bw9GY@ns3e zSfuWF_gkWnesv?s3I`@}NgE2xwgs&rj?kH-FEy82=O8`+szN ziHch`vvS`zNfap14!&#i9H@wF7}yIPm=UB%(o(}F{wsZ(wA0nJ2aD^@B41>>o-_U6 zUqD~vdo48S8~FTb^+%#zcbQiiYoDKYcj&$#^;Smmb+Ljp(L=1Kt_J!;0s%1|JK}Wi z;={~oL!foo5n8=}rs6MmUW~R&;SIJO3TL4Ky?kh+b2rT9B1Jl4>#Uh-Bec z`Hsp<==#UEW6pGPhNk8H!!DUQR~#F9jEMI6T*OWfN^Ze&X(4nV$wa8QUJ>oTkruH# zm~O<`J7Wxseo@FqaZMl#Y(mrFW9AHM9Kb|XBMqaZ2a)DvJgYipkDD_VUF_PKd~dT7 z#02}bBfPn9a!X!O#83=lbJSK#E}K&yx-HI#T6ua)6o0{|={*HFusCkHzs|Fn&|C3H zBck1cmfcWVUN&i>X$YU^Sn6k2H;r3zuXbJFz)r5~3$d$tUj(l1?o={MM){kjgqXRO zc5R*#{;V7AQh|G|)jLM@wGAK&rm2~@{Pewv#06pHbKn#wL0P6F1!^qw9g&cW3Z=9} zj)POhOlwsh@eF=>z?#sIs*C-Nl(yU!#DaiaxhEs#iJqQ8w%(?+6lU02MYSeDkr!B- zPjMv+on6OLXgGnAtl(ao>|X2Y8*Hb}GRW5}-IzXnoo-d0!m4Vy$GS!XOLy>3_+UGs z2D|YcQx@M#M|}TDOetGi{9lGo9m-=0-^+nKE^*?$^uHkxZh}I{#UTQd;X!L+W@jm( zDg@N4+lUqI92o_rNk{3P>1gxAL=&O;x)ZT=q1mk0kLlE$WeWuY_$0`0jY-Kkt zP*|m3AF}Ubd=`<>(Xg0har*_@x2YH}bn0Wk*OZz3*e5;Zc;2uBdnl8?&XjupbkOeNZsNh6pvsq_ydmJI+*z**{I{0K)-;p1~k8cpJXL$^t!-`E}=*4G^-E8>H!LjTPxSx zcF+cS`ommfKMhNSbas^@YbTpH1*RFrBuATUR zt{oFWSk^$xU&kbFQ;MCX22RAN5F6eq9UfR$ut`Jw--p2YX)A*J69m^!oYfj2y7NYcH6&r+0~_sH^c^nzeN1AU4Ga7=FlR{S|Mm~MpzY0$Z+p2W(a={b-pR9EO1Rs zB%KY|@wLcAA@)KXi!d2_BxrkhDn`DT1=Dec}V!okd{$+wK z4E{n8R*xKyci1(CnNdhf$Dp2(Jpof0-0%-38X=Dd9PQgT+w%Lshx9+loPS~MOm%ZT zt%2B2iL_KU_ita%N>xjB!#71_3=3c}o zgeW~^U_ZTJQ2!PqXulQd=3b=XOQhwATK$y(9$#1jOQ4}4?~l#&nek)H(04f(Sr=s| zWv7Lu1=%WGk4FSw^;;!8&YPM)pQDCY9DhU`hMty1@sq1=Tj7bFsOOBZOFlpR`W>-J$-(kezWJj;`?x-v>ev{*8V z8p|KXJPV$HyQr1A(9LVrM47u-XpcrIyO`yWvx1pVYc&?154aneRpLqgx)EMvRaa#|9?Wwqs2+W8n5~79G z(}iCiLk;?enn}ew`HzhG+tu+Ru@T+K5juvZN)wY;x6HjvqD!&!)$$;1VAh~7fg0K| zEha#aN=Yv|3^~YFH}cc38ovVb%L|g@9W6fo(JtT6$fa?zf@Ct88e}m?i)b*Jgc{fl zExfdvw-BYDmH6>(4QMt#p0;FUIQqkhD}aH?a7)_%JtA~soqj{ppP_82yi9kaxuK>~ ze_)Zt>1?q=ZH*kF{1iq9sr*tVuy=u>Zev}!gEZx@O6-fjyu9X00gpIl-fS_pzjpqJ z1yqBmf9NF!jaF<+YxgH6oXBdK)sH(>VZ)1siyA$P<#KDt;8NT*l_0{xit~5j1P)FN zI8hhYKhQ)i z37^aP13B~u65?sg+_@2Kr^iWHN=U;EDSZ@2W2!5ALhGNWXnFBY%7W?1 z=HI9JzQ-pLKZDYTv<0-lt|6c-RwhxZ)mU2Os{bsX_i^@*fKUj8*aDO5pks=qn3Dv6 zwggpKLuyRCTVPwmw1r}B#AS}?X7b837UlXwp~E2|PJw2SGVueL7){Y&z!jL!XN=0i zU^Eig`S2`{+gU$68aRdWx?BZ{sU_f=8sn~>s~M?GU~`fH5kCc; z8ICp+INM3(3{#k32RZdv6b9MQYdZXNuk7ed8;G?S2nT+NZBG=Tar^KFl2SvhW$bGW#kdWL-I)s_IqVnCDDM9fm8g;P;8 z7t4yZn3^*NQfx7SwmkzP$=fwdC}bafQSEF@pd&P8@H#`swGy_rz;Z?Ty5mkS%>m#% zp_!m9e<()sfKiY(nF<1zBz&&`ZlJf6QLvLhl`_``%RW&{+O>Xhp;lwSsyRqGf=RWd zpftiR`={2(siiPAS|p}@q=NhVc0ELprt%=fMXO3B)4ryC2LT(o=sLM7hJC!}T1@)E zA3^J$3&1*M6Xq>03FX`R&w*NkrZE?FwU+Muut;>qNhj@bX17ZJxnOlPSZ=Zeiz~T_ zOu#yc3t6ONHB;?|r4w+pI)~KGN;HOGC)txxiUN8#mexj+W(cz%9a4sx|IRG=}ia zuEBuba3AHsV2feqw-3MvuL`I+2|`Ud4~7ZkN=JZ;L20|Oxna5vx1qbIh#k2O4$RQF zo`tL()zxaqibg^GbB+BS5#U{@K;WWQj~GcB1zb}zJkPwH|5hZ9iH2308!>_;%msji zJHSL~s)YHBR=Koa1mLEOHos*`gp=s8KA-C zu0aE+W!#iJ*0xqKm3A`fUGy#O+X+5W36myS>Uh2!R*s$aCU^`K&KKLCCDkejX2p=5 z%o7-fl03x`gaSNyr?3_JLv?2RLS3F*8ub>Jd@^Cc17)v8vYEK4aqo?OS@W9mt%ITJ z9=S2%R8M){CugT@k~~0x`}Vl!svYqX=E)c_oU6o}#Hb^%G1l3BudxA{F*tbjG;W_>=xV73pKY53v%>I)@D36I_@&p$h|Aw zonQS`07z_F#@T-%@-Tb|)7;;anoD_WH>9ewFy(ZcEOM$#Y)8>qi7rCnsH9GO-_7zF zu*C87{Df1P4TEOsnzZ@H%&lvV(3V@;Q!%+OYRp`g05PjY^gL$^$-t0Y>H*CDDs?FZly*oZ&dxvsxaUWF!{em4{A>n@vpXg$dwvt@_rgmHF z-MER`ABa8R-t_H*kv>}CzOpz;!>p^^9ztHMsHL|SRnS<-y5Z*r(_}c4=fXF`l^-i}>e7v!qs_jv zqvWhX^F=2sDNWA9c@P0?lUlr6ecrTKM%pNQ^?*Lq?p-0~?_j50xV%^(+H>sMul#Tw zeciF*1=?a7cI(}352%>LO96pD+?9!fNyl^9v3^v&Y4L)mNGK0FN43&Xf8jUlxW1Bw zyiu2;qW-aGNhs=zbuoxnxiwZ3{PFZM#Kw)9H@(hgX23h(`Wm~m4&TvoZoYp{plb^> z_#?vXcxd>r7K+1HKJvhed>gtK`TAbJUazUWQY6T~t2af%#<+Veyr%7-#*A#@&*;@g58{i|E%6yC_InGXCOd{L0;$)z#?n7M`re zh!kO{6=>7I?*}czyF7_frt#)s1CFJ_XE&VrDA?Dp3XbvF{qsEJgb&OLSNz_5g?HpK z9)8rsr4JN!Af3G9!#Qn(6zaUDqLN(g2g8*M)Djap?WMK9NKlkC)E2|-g|#-rp%!Gz zAHd%`iq|81efi93m3yTBw3g0j#;Yb2X{mhRAI?&KDmbGqou(2xiRNb^sV}%%Wu0?< z?($L>(#BO*)^)rSgyNRni$i`R4v;GhlCZ8$@e^ROX(p=2_v6Y!%^As zu022)fHdv_-~Yu_H6WVPLpHQx!W%^6j)cBhS`O3QBW#x(eX54d&I22op(N59b*&$v zFiSRY6rOc^(dgSV1>a7-5C;(5S5MvKcM2Jm-LD9TGqDpP097%52V+0>Xqq!! zq4e3vj53SE6i8J`XcQB|MZPP8j;PAOnpGnllH6#Ku~vS42xP*Nz@~y%db7Xi8s09P z1)e%8ys6&M8D=Dt6&t`iKG_4X=!kgRQoh%Z`dc&mlOUqXk-k`jKv9@(a^2-Upw>?< zt5*^DV~6Zedbec4NVl($2T{&b)zA@b#dUyd>`2JC0=xa_fIm8{5um zr-!ApXZhC8@=vC2WyxO|!@0Km)h8ep*`^he92$@YwP>VcdoS5OC^s38e#7RPsg4j+ zbVGG}WRSET&ZfrcR(x~k8n1rTP%CnfUNKUonD$P?FtNFF#cn!wEIab-;jU=B1dHK@ z(;(yAQJ`O$sMn>h;pf^8{JISW%d+@v6@CnXh9n5TXGC}?FI9i-D0OMaIg&mAg=0Kn zNJ7oz5*ReJukD55fUsMuaP+H4tDN&V9zfqF@ zr=#ecUk9wu{0;!+gl;3Bw=Vn^)z$ahVhhw)io!na&9}LmWurLb0zubxK=UEnU*{5P z+SP}&*(iBKSO4{alBHaY^)5Q=mZ+2OwIooJ7*Q5XJ+2|q`9#f?6myq!&oz?klihLq z4C)$XP!BNS0G_Z1&TM>?Jk{S~{F3n83ioli=IO6f%wkvCl(RFFw~j0tb{GvXTx>*sB0McY0s&SNvj4+^h`9nJ_wM>F!Uc>X}9PifQekn0sKI2SAJP!a4h z5cyGTuCj3ZBM^&{dRelIlT^9zcfaAuL5Y~bl!ppSf`wZbK$z#6U~rdclk``e+!qhe z6Qspo*%<)eu6?C;Bp<^VuW6JI|Ncvyn+LlSl;Mp22Bl7ARQ0Xc24%29(ZrdsIPw&-=yHQ7_Vle|5h>AST0 zUGX2Zk34vp?U~IHT|;$U86T+UUHl_NE4m|}>E~6q``7hccCaT^#y+?wD##Q%HwPd8 zV3x4L4|qqu`B$4(LXqDJngNy-{&@aFBvVsywt@X^}iH7P%>bR?ciC$I^U-4Foa`YKI^qDyGK7k%E%c_P=yzAi`YnxGA%DeNd++j3*h^ z=rn>oBd0|~lZ<6YvmkKY*ZJlJ;Im0tqgWu&E92eqt;+NYdxx`eS(4Hw_Jb5|yVvBg z*tbdY^!AN;luEyN4VRhS@-_DC{({ziH{&Z}iGElSV~qvT>L-8G%+yEL zX#MFOhj{InyKG=mvW-<1B@c-}x$vA(nU?>S>0*eN#!SLzQ)Ex7fvQ)S4D<8|I#N$3 zT5Ei`Z?cxBODHX8(Xp73v`IsAYC@9b;t}z0wxVuQSY1J^GRwDPN@qbM-ZF48T$GZ< z8WU+;Pqo?{ghI-KZ-i*ydXu`Ep0Xw^McH_KE9J0S7G;x8Fe`DVG?j3Pv=0YzJ}yZR z%2=oqHiUjvuk0~Ca>Kol4CFi0_xQT~;_F?=u+!kIDl-9g`#ZNZ9HCy17Ga1v^Jv9# z{T4Kb1-AzUxq*MutfOWWZgD*HnFfyYg0&e9f(5tZ>krPF6{VikNeHoc{linPPt#Si z&*g>(c54V8rT_AX!J&bNm-!umPvOR}vDai#`CX___J#=zeB*{4<&2WpaDncZsOkp* zsg<%@@rbrMkR_ux9?LsQxzoBa1s%$BBn6vk#{&&zUwcfzeCBJUwFYSF$08qDsB;gWQN*g!p8pxjofWbqNSZOEKOaTx@+* zwdt5*Q47@EOZ~EZL9s?1o?A%9TJT=Ob_13yyugvPg*e&ZU(r6^k4=2+D-@n=Hv5vu zSXG|hM(>h9^zn=eQ=$6`JO&70&2|%V5Lsx>)(%#;pcOfu>*nk_3HB_BNaH$`jM<^S zcSftDU1?nL;jy)+sfonQN}(}gUW?d_ikr*3=^{G)=tjBtEPe>TO|0ddVB zTklrSHiW+!#26frPXQQ(YN8DG$PZo?(po(QUCCf_OJC`pw*uey00%gmH!`WJkrKXj2!#6?`T25mTu9OJp2L8z3! z=arrL$ZqxuE{%yV)14Kd>k}j7pxZ6#$Dz8$@WV5p8kTqN<-7W)Q7Gt2{KoOPK_tZ| zf2WG~O5@{qPI+W<4f_;reuFVdO^5`ADC1!JQE|N`s3cq@(0WB!n0uh@*c{=LAd;~} zyGK@hbF-Oo+!nN)@i*O(`@FA#u?o=~e{`4O#5}z&=UkU*50fOrzi11D^&FOqe>wii z?*k+2|EcUs;Gx{!@KBT~>PAwLrIDT7Th=Utu?~?np@t^gFs?zgX=D${RwOY^WGh-+ z+#4$066ISh8eYW#FXWp~S`<*%O^ZuItL1Tyqt8#tZ zY120E;^VG`!lZn&3sPd$RkdHpU#|w+bYV)pJC|SH9g%|5IkxVTQcBA4CL0}$&}ef@ zW^Vtj%M;;_1xxP9x#ex17&4N*{ksO*_4O}xYu(p*JkL#yr}@7b)t5X?%CY<+s5_MJ zuiqt+N_;A(_)%lumoyRFixWa-M7qK_9s6<1X?JDa9fP!+_6u~~M$5L=ipB=7(j#f< zZ34J%=bs549%~_mA(|={uZNs_0?o7;-LBP(ZRnkd{-^|2|=4vUTmtByHL8 zEph`(LSEzQj68a+`d$V<45J7cyv^#|^|%fD#si1Nx!4NW*`l*{->HEWNh6-|g>-=r zXmQ|-i}Ku$ndUeHQ^&ieT!Lf}vf6GaqW9$DJ2NWrqwPY%%4nip$@vK$nRp*_C-v<| zuKz~ZyN&<%!NS26&x?jhy+@awJipMQ-8(X4#Ae5??U<1QMt1l9R=w9fAnEF}NYu$2 z>6}Vkc zIb*A?G*z8^IvibmBKn_u^5&T_1oey0gZS2~obf(#xk=erZGTEdQnt3DMGM+0oPwss zj5zXD;(oWhB_T@~Ig#9@v)AKtXu3>Inmgf@A|-lD-1U>cNyl3h?ADD9)GG4}zUGPk zZzaXe!~Kf?<~@$G?Uql3t8jy9{2!doq4=J}j9ktTxss{p6!9UdjyDERlA*xZ!=Q)KDs5O)phz>Vq3BNGoM(H|=1*Q4$^2fTZw z(%nq1P|5Rt81}SYJpEEzMPl5VJsV5&4e)ZWKDyoZ>1EwpkHx-AQVQc8%JMz;{H~p{=FXV>jIxvm4X*qv52e?Y-f%DJ zxEA165GikEASQ^fH6K#d!Tpu2HP{sFs%E=e$gYd$aj$+xue6N+Wc(rAz~wUsk2`(b z8Kvmyz%bKQxpP}~baG-rwYcYCvkHOi zlkR<=>ZBTU*8RF_d#Bl@zZsRIhx<%~Z@Z=ik z>adw3!DK(8R|q$vy{FTxw%#xliD~6qXmY^7_9kthVPTF~Xy1CfBqbU~?1QmxmU=+k z(ggxvEuA;0e&+ci-zQR{-f7aO{O(Pz_OsEjLh_K>MbvoZ4nxtk5u{g@nPv)cgW_R} z9}EA4K4@z0?7ue}Z(o~R(X&FjejUI2g~08PH1E4w>9o{)S(?1>Z0XMvTb|;&EuyOE zGvWNpYX)Nv<8|a^;1>bh#&znEcl-r!T#pn= z4$?Yudha6F%4b>*8@=BdtXXY4N+`U4Dmx$}>HeVJk-QdTG@t!tVT#0(LeV0gvqyyw z2sEp^9eY0N`u10Tm4n8No&A=)IeEC|gnmEXoNSzu!1<4R<%-9kY_8~5Ej?zRegMn78wuMs#;i&eUA0Zk_RXQ3b&TT} z;SCI=7-FUB@*&;8|n>(_g^HGf3@QODE3LpmX~ELnymQm{Sx9xrKS zK29p~?v@R$0=v6Dr5aW>-!{+h@?Q58|Kz8{{W`%J+lDAdb&M5VHrX_mDY;1-JLnf)ezmPau$)1;=`-FU=-r-83tX=C`S#}GZufju zQ>sXNT0Ny=k@nc%cFnvA_i4SC)?_ORXHq8B4D%el1uPX`c~uG#S1M7C+*MMqLw78E zhY2dI8@+N^qrMI1+;TUda(vGqGSRyU{Fnm`aqrr7bz42c5xsOO-~oZpkzorD1g}Y<6rk&3>PsSGy}W?MtqFky@A(X# zIuNZK0cK?^=;PUAu>j0#HtjbHCV*6?jzA&OoE$*Jlga*}LF`SF?WLhv1O|zqC<>*> zYB;#lsYKx0&kH@BFpW8n*yDcc6?;_zaJs<-jPSkCsSX-!aV=P5kUgF@Nu<{a%#K*F z134Q{9|YX7X(v$62_cY3^G%t~rD>Q0z@)1|zs)vjJ6Jq9;7#Ki`w+eS**En?7;n&7 zu==V3T&eFboN3ZiMx3D8qYc;VjFUk_H-WWCau(VFXSQf~viH0L$gwD$UfFHqNcgN`x}M+YQ6RnN<+@t>JUp#)9YOkqst-Ga?{FsDpEeX0(5v{0J~SEbWiL zXC2}M4?UH@u&|;%0y`eb33ldo4~z-x8zY!oVmV=c+f$m?RfDC35mdQ2E>Pze7KWP- z>!Bh<&57I+O_^s}9Tg^k)h7{xx@0a0IA~GAOt2yy!X%Q$1rt~LbTB6@Du!_0%HV>N zlf)QI1&gvERKwso23mJ!Ou6ZS#zCS5W`gxE5T>C#E|{i<1D35C222I33?Njaz`On7 zi<+VWFP6D{e-{yiN#M|Jgk<44u1TiMI78S5W`Sdb5f+{zu34s{CfWN7a3Cf^@L%!& zN$?|!!9j2c)j$~+R6n#891w-z8(!oBpL2K=+%a$r2|~8-(vQj5_XT`<0Ksf;oP+tz z9CObS!0m)Tgg`K#xBM8B(|Z)Wb&DYL{WTYv`;A=q6~Nnx2+!lTIXtj8J7dZE!P_{z z#f8w6F}^!?^KE#+ZDv+xd5O&3EmomZzsv?>E-~ygGum45fk!SBN&|eo1rKw^?aZJ4 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..1016baed3 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,26 @@ +# +# MIT License +# +# Copyright (C) 2020-2022 The SimpleCloud authors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +# documentation files (the "Software"), to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 000000000..22b42f2fd --- /dev/null +++ b/gradlew @@ -0,0 +1,191 @@ +#!/usr/bin/env sh + +# +# MIT License +# +# Copyright (C) 2020-2022 The SimpleCloud authors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +# documentation files (the "Software"), to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..aff53bd36 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +rootProject.name = 'simplecloud-v2' +include 'simplecloud-api' +include 'simplecloud-client' +include 'simplecloud-launcher' +include 'simplecloud-plugin' +include 'simplecloud-base' +include 'simplecloud-modules' +include 'simplecloud-modules:simplecloud-module-permission' +findProject(':simplecloud-modules:simplecloud-module-permission')?.name = 'simplecloud-module-permission' +include 'simplecloud-modules:simplecloud-module-cloudflare' +findProject(':simplecloud-modules:simplecloud-module-cloudflare')?.name = 'simplecloud-module-cloudflare' +include 'simplecloud-modules:simplecloud-module-proxy' +findProject(':simplecloud-modules:simplecloud-module-proxy')?.name = 'simplecloud-module-proxy' +include 'simplecloud-modules:simplecloud-module-sign' +findProject(':simplecloud-modules:simplecloud-module-sign')?.name = 'simplecloud-module-sign' +include 'simplecloud-modules:simplecloud-module-internalwrapper' +findProject(':simplecloud-modules:simplecloud-module-internalwrapper')?.name = 'simplecloud-module-internalwrapper' +include 'simplecloud-updater' +include 'simplecloud-modules:simplecloud-module-notify' +findProject(':simplecloud-modules:simplecloud-module-notify')?.name = 'simplecloud-module-notify' +include 'simplecloud-modules:simplecloud-module-hubcommand' +findProject(':simplecloud-modules:simplecloud-module-hubcommand')?.name = 'simplecloud-module-hubcommand' +include 'simplecloud-runner' +include 'simplecloud-modules:simplecloud-module-serviceselection' +findProject(':simplecloud-modules:simplecloud-module-serviceselection')?.name = 'simplecloud-module-serviceselection' +include 'simplecloud-modules:simplecloud-module-rest' +findProject(':simplecloud-modules:simplecloud-module-rest')?.name = 'simplecloud-module-rest' +include 'simplecloud-modules:simplecloud-module-chat-tab' +findProject(':simplecloud-modules:simplecloud-module-chat-tab')?.name = 'simplecloud-module-chat-tab' +include 'simplecloud-modules:simplecloud-module-statistics' +findProject(':simplecloud-modules:simplecloud-module-statistics')?.name = 'simplecloud-module-statistics' +include 'simplecloud-dependency-loader' +include 'simplecloud-modules:simplecloud-module-npc' +findProject(':simplecloud-modules:simplecloud-module-npc')?.name = 'simplecloud-module-npc' +include 'simplecloud-modules:simplecloud-module-support' +findProject(':simplecloud-modules:simplecloud-module-support')?.name = 'simplecloud-module-support' +include 'simplecloud-modules:simplecloud-module-placeholders' +findProject(':simplecloud-modules:simplecloud-module-placeholders')?.name = 'simplecloud-module-placeholders' +include 'simplecloud-modules:simplecloud-module-placeholders' +findProject(':simplecloud-modules:simplecloud-module-placeholders')?.name = 'simplecloud-module-placeholders' + diff --git a/simplecloud-api/build.gradle b/simplecloud-api/build.gradle new file mode 100644 index 000000000..eb34b41ef --- /dev/null +++ b/simplecloud-api/build.gradle @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +dependencies { + testApi group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion + testApi group: 'org.mockito', name: 'mockito-core', version: '2.1.0' + compileOnly group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.6.1' + compileOnly(project(":simplecloud-runner")) + + testApi group: 'commons-io', name: 'commons-io', version: dependencyCommonsIOVersion + testApi group: 'com.google.guava', name: 'guava', version: dependencyGuavaVersion + testApi group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion + testApi group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: dependencyKotlinCouroutinesVersion + api group: 'com.google.code.gson', name: 'gson', version: '2.8.9' + api(group: 'eu.thesimplecloud.clientserverapi', name: 'clientserverapi', version: depedencyClientServerAPIVersion) + api(group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion) + api("net.kyori:adventure-api:4.11.0") + api("net.kyori:adventure-text-serializer-gson:4.11.0") + +} diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/CloudAPI.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/CloudAPI.kt new file mode 100644 index 000000000..8cf1baeef --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/CloudAPI.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api + +import eu.thesimplecloud.api.cachelist.manager.CacheListManager +import eu.thesimplecloud.api.cachelist.manager.ICacheListManager +import eu.thesimplecloud.api.message.IMessageChannelManager +import eu.thesimplecloud.api.message.MessageChannelManager +import eu.thesimplecloud.api.sync.`object`.GlobalPropertyHolder +import eu.thesimplecloud.api.sync.`object`.IGlobalPropertyHolder +import eu.thesimplecloud.api.template.ITemplateManager +import eu.thesimplecloud.api.template.impl.DefaultTemplateManager +import eu.thesimplecloud.api.wrapper.IWrapperManager +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperManager + +abstract class CloudAPI : ICloudAPI { + + private val wrapperManager: IWrapperManager = DefaultWrapperManager() + private val templateManager: ITemplateManager = DefaultTemplateManager() + private val messageChannelManager: IMessageChannelManager = MessageChannelManager() + private val cacheListManager: ICacheListManager = CacheListManager() + private val globalPropertyHolder: IGlobalPropertyHolder = GlobalPropertyHolder() + + init { + instance = this + } + + + override fun getWrapperManager(): IWrapperManager = this.wrapperManager + + override fun getTemplateManager(): ITemplateManager = this.templateManager + + override fun getMessageChannelManager(): IMessageChannelManager = this.messageChannelManager + + override fun getCacheListManager(): ICacheListManager = this.cacheListManager + + override fun getGlobalPropertyHolder(): IGlobalPropertyHolder = this.globalPropertyHolder + + companion object { + @JvmStatic + lateinit var instance: ICloudAPI + private set + + fun isAvailable(): Boolean { + return runCatching { CloudAPI.instance.getEventManager() }.isSuccess + } + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/ICloudAPI.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/ICloudAPI.kt new file mode 100644 index 000000000..2097a282f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/ICloudAPI.kt @@ -0,0 +1,144 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api + +import eu.thesimplecloud.api.cachelist.manager.ICacheListManager +import eu.thesimplecloud.api.eventapi.IEventManager +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.ILanguageManager +import eu.thesimplecloud.api.message.IMessageChannelManager +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.version.IServiceVersionHandler +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.sync.list.manager.ISynchronizedObjectListManager +import eu.thesimplecloud.api.sync.`object`.IGlobalPropertyHolder +import eu.thesimplecloud.api.template.ITemplateManager +import eu.thesimplecloud.api.wrapper.IWrapperManager +import eu.thesimplecloud.clientserverapi.lib.bootstrap.ICommunicationBootstrap + +/** + * The global api for the cloud. It can be accessed from everywhere. + */ +interface ICloudAPI { + + /** + * Returns the [IWrapperManager] to manage wrapper + */ + fun getWrapperManager(): IWrapperManager + + /** + * Returns the [ICloudServiceGroupManager] to manage service groups + */ + fun getCloudServiceGroupManager(): ICloudServiceGroupManager + + /** + * Returns the [ICloudServiceManager] to manage services + */ + fun getCloudServiceManager(): ICloudServiceManager + + /** + * Returns the [ICloudPlayerManager] to manage players + */ + fun getCloudPlayerManager(): ICloudPlayerManager + + /** + * Returns the [IEventManager] to manage and call events + */ + fun getEventManager(): IEventManager + + /** + * Returns the [ICommandExecuteManager] used to execute command on [ICommandExecutable] + */ + fun getCommandExecuteManager(): ICommandExecuteManager + + /** + * Returns the [ITemplateManager] used to manage the templates + */ + fun getTemplateManager(): ITemplateManager + + /** + * Returns the [IGlobalPropertyHolder] used to manage the templates + */ + fun getGlobalPropertyHolder(): IGlobalPropertyHolder + + /** + * Returns the [ICommunicationBootstrap] of this side. + */ + fun getThisSidesCommunicationBootstrap(): ICommunicationBootstrap + + /** + * Returns the [ISynchronizedObjectListManager] + */ + fun getSynchronizedObjectListManager(): ISynchronizedObjectListManager + + /** + * Return the [IMessageChannelManager] + */ + fun getMessageChannelManager(): IMessageChannelManager + + /** + * Returns the [ICacheListManager] + */ + fun getCacheListManager(): ICacheListManager + + /** + * Returns the [IServiceVersionHandler] + */ + fun getServiceVersionHandler(): IServiceVersionHandler + + /** + * Returns the [ILanguageManager] + */ + fun getLanguageManager(): ILanguageManager + + /** + * Returns the name of this side + * e.g Manager / Wrapper-1 / Lobby-1 + */ + fun getThisSidesName(): String + + /** + * Returns the [INetworkComponent] of this side. + */ + fun getThisSidesNetworkComponent(): INetworkComponent + + /** + * Returns whether this side is a manager. + */ + fun isManager(): Boolean = getThisSidesName() == "Manager" + + /** + * Returns whether the application is executed on windows. + */ + fun isWindows(): Boolean = System.getProperty("os.name").lowercase().contains("windows") + + /** + * Returns then cloud module fot this side. + */ + fun getThisSidesCloudModule(): ICloudModule + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/AbstractCacheList.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/AbstractCacheList.kt new file mode 100644 index 000000000..b084b1b58 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/AbstractCacheList.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist + +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.flatten +import java.util.concurrent.CopyOnWriteArrayList + +abstract class AbstractCacheList>(private val spreadUpdates: Boolean = true) : + ICacheList { + + protected val values = CopyOnWriteArrayList() + + override fun shallSpreadUpdates(): Boolean { + return this.spreadUpdates + } + + override fun delete(value: T, fromPacket: Boolean): ICommunicationPromise { + return CommunicationPromise.runAsync { + super.update(value, fromPacket = true, isCalledFromDelete = true).awaitCoroutine() + val result = super.delete(value, fromPacket).awaitCoroutine() + values.remove(getUpdateExecutor().getCachedObjectByUpdateValue(value)) + return@runAsync result + }.flatten() + + } + + override fun getAllCachedObjects(): List { + return this.values + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheList.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheList.kt new file mode 100644 index 000000000..2aae9a66e --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheList.kt @@ -0,0 +1,136 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import eu.thesimplecloud.api.network.packets.sync.cachelist.PacketIOUpdateCacheObject +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.combineAllPromises + +interface ICacheList> { + + /** + * Updates the cashed value with the content of the specified one. + * @param value the value to update + * @param fromPacket whether this method was called by a packet + * @return a promise that completes when the update was sent + */ + fun update( + value: T, + fromPacket: Boolean = false, + isCalledFromDelete: Boolean = false + ): ICommunicationPromise { + val valueUpdater = value.getUpdater() + val updateExecutor = getUpdateExecutor() + val cachedValue = updateExecutor.getCachedObjectByUpdateValue(value) + val eventsToCall = updateExecutor.determineEventsToCall(valueUpdater, cachedValue) + if (cachedValue == null) { + updateExecutor.addNewValue(value) + } else { + cachedValue.applyValuesFromUpdater(valueUpdater) + } + eventsToCall.forEach { CloudAPI.instance.getEventManager().call(it) } + + if (shallSpreadUpdates()) + if (!isCalledFromDelete) + if (CloudAPI.instance.isManager() || !fromPacket) + return updateExecutor.sendUpdatesToOtherComponents(value, PacketIOUpdateCacheObject.Action.UPDATE) + + return CommunicationPromise.UNIT_PROMISE + } + + /** + * Returns whether the updates shall be spread to other network components. + */ + fun shallSpreadUpdates(): Boolean + + /** + * Returns ht update lifecycle of this object + */ + fun getUpdateExecutor(): ICacheObjectUpdateExecutor + + /** + * Deletes the specified value. + * @param value the object to delete + * @param fromPacket whether this method was called by a packet + * @return a promise that completes when the delete was sent + */ + fun delete(value: T, fromPacket: Boolean = false): ICommunicationPromise { + val updater = getUpdateExecutor() + if (shallSpreadUpdates()) + if (CloudAPI.instance.isManager() || !fromPacket) + return updater.sendUpdatesToOtherComponents(value, PacketIOUpdateCacheObject.Action.DELETE) + + return CommunicationPromise.UNIT_PROMISE + } + + /** + * Returns all objects in this cache + */ + fun getAllCachedObjects(): List + + /** + * Sends the update of the [value] to the specified [connection] + * @param value the object to send + * @param connection the connection to send the [value] to + * @return the a promise that completes when the packet was handled. + */ + fun sendUpdateToConnection(value: T, connection: IConnection): ICommunicationPromise { + return connection.sendUnitQuery( + PacketIOUpdateCacheObject( + getUpdateExecutor().getIdentificationName(), + value, + PacketIOUpdateCacheObject.Action.UPDATE + ) + ) + } + + /** + * Sends the delete request of the [value] to the specified [connection] + * @param value the object to send + * @param connection the connection to send the [value] to + * @return the a promise that completes when the packet was handled. + */ + fun sendDeleteToConnection(value: T, connection: IConnection): ICommunicationPromise { + return connection.sendUnitQuery( + PacketIOUpdateCacheObject( + getUpdateExecutor().getIdentificationName(), + value, + PacketIOUpdateCacheObject.Action.DELETE + ) + ) + } + + /** + * Sends all cached objects to the specified [connection] + * @return a promise that completes when all packet have been sent. + */ + fun sendAllCachedObjectsToConnection(connection: IConnection): ICommunicationPromise { + return getAllCachedObjects().map { this.sendUpdateToConnection(it, connection) }.combineAllPromises() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheObjectUpdateExecutor.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheObjectUpdateExecutor.kt new file mode 100644 index 000000000..9f6630b87 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/ICacheObjectUpdateExecutor.kt @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.extension.sendPacketToAllAuthenticatedClients +import eu.thesimplecloud.api.network.packets.sync.cachelist.PacketIOUpdateCacheObject +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.server.INettyServer + +interface ICacheObjectUpdateExecutor> { + + /** + * Returns the identification name + */ + fun getIdentificationName(): String + + /** + * Returns the cached object by the update value + * @param value the update value + * @return the value currently cached + */ + fun getCachedObjectByUpdateValue(value: T): T? + + /** + * This method will be invoked + * the events will be called after the update value was updated to the cache + * All events should be called with the [cachedValue] if it is not null + */ + fun determineEventsToCall(updater: U, cachedValue: T?): List + + /** + * Sends the [value] to every network component that shall receive the update. + * This method is only called if [ICacheList.update] was invoked with fromPacket = false or + * this side is the Manager + */ + fun sendUpdatesToOtherComponents(value: T, action: PacketIOUpdateCacheObject.Action): ICommunicationPromise { + val packet = PacketIOUpdateCacheObject(getIdentificationName(), value, action) + return if (CloudAPI.instance.isManager()) { + val server = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyServer<*> + server.getClientManager().sendPacketToAllAuthenticatedClients(packet) + } else { + val client = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyClient + client.getConnection().sendUnitQuery(packet) + } + } + + /** + * Adds the specified [value] to the cache + */ + fun addNewValue(value: T) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/CacheListManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/CacheListManager.kt new file mode 100644 index 000000000..35602f54e --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/CacheListManager.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist.manager + +import eu.thesimplecloud.api.cachelist.ICacheList +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import java.util.concurrent.CopyOnWriteArrayList + +class CacheListManager : ICacheListManager { + + private val cacheListList = CopyOnWriteArrayList>>() + + override fun registerCacheList(cacheList: ICacheList>) { + this.cacheListList.add(cacheList as ICacheList>) + } + + override fun getCacheListenerByName(name: String): ICacheList>? { + return this.cacheListList.firstOrNull { it.getUpdateExecutor().getIdentificationName() == name } + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/ICacheListManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/ICacheListManager.kt new file mode 100644 index 000000000..dcb817a08 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/manager/ICacheListManager.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist.manager + +import eu.thesimplecloud.api.cachelist.ICacheList +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater + +interface ICacheListManager { + + /** + * Registers a cache listener. + */ + fun registerCacheList(cacheList: ICacheList>) + + /** + * Returns the [ICacheList] found by the specified [name] + */ + fun getCacheListenerByName(name: String): ICacheList>? + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/AbstractCacheValueUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/AbstractCacheValueUpdater.kt new file mode 100644 index 000000000..9867135d7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/AbstractCacheValueUpdater.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist.value + +import com.google.common.collect.Maps +import java.util.concurrent.ConcurrentMap + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 14:21 + * @author Frederick Baier + */ +abstract class AbstractCacheValueUpdater : ICacheValueUpdater { + + protected val changes: ConcurrentMap = Maps.newConcurrentMap() + + protected fun getChangedValue(key: String): T? { + return changes[key] as T? + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValue.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValue.kt new file mode 100644 index 000000000..64b690edd --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValue.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist.value + +/** + * Created by IntelliJ IDEA. + * Date: 22.01.2021 + * Time: 18:02 + * @author Frederick Baier + */ +interface ICacheValue { + + /** + * Returns the updater instance of this value + */ + fun getUpdater(): U + + /** + * Applies the values from the specified updater + */ + fun applyValuesFromUpdater(updater: U) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValueUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValueUpdater.kt new file mode 100644 index 000000000..33cb8cf83 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/cachelist/value/ICacheValueUpdater.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.cachelist.value + +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 22.01.2021 + * Time: 18:04 + * @author Frederick Baier + */ +interface ICacheValueUpdater { + + /** + * Applies the changes + */ + fun update(): ICommunicationPromise + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentReference.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentReference.kt new file mode 100644 index 000000000..5c2d45c92 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentReference.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.client + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.network.component.INetworkComponent + +data class NetworkComponentReference(val componentType: NetworkComponentType, val name: String) { + + companion object { + @JvmStatic + val MANAGER_COMPONENT_REFERENCE = NetworkComponentReference(NetworkComponentType.MANAGER, "Manager") + + + } + + fun getNetworkComponent(): INetworkComponent? { + return when (componentType) { + NetworkComponentType.WRAPPER -> { + CloudAPI.instance.getWrapperManager().getWrapperByName(name) + } + NetworkComponentType.SERVICE -> { + CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) + } + NetworkComponentType.MANAGER -> { + INetworkComponent.MANAGER_COMPONENT + } + } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentType.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentType.kt new file mode 100644 index 000000000..303bfb2b8 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/client/NetworkComponentType.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.client + +/** + * An enum to separate wrapper and service clients + */ +enum class NetworkComponentType { + + + WRAPPER, + SERVICE, + MANAGER + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/command/ICommandSender.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/command/ICommandSender.kt new file mode 100644 index 000000000..4e143a0ad --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/command/ICommandSender.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.api.exception.UnreachableComponentException +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +interface ICommandSender { + + /** + * Sends a message to this [ICommandSender] + * @return a promise that completes when the message was sent. + */ + fun sendMessage(message: String): ICommunicationPromise + + /** + * Sends message got by the [property] with the replaced values + */ + fun sendProperty(property: String, vararg placeholderValues: String): ICommunicationPromise { + val replacedMessage = CloudAPI.instance.getLanguageManager().getMessage(property, *placeholderValues) + return sendMessage(replacedMessage) + } + + /** + * Checks whether this sender has the specified [permission] + * @return a promise that is completed when the permission is checked, or + * when an exception is encountered. [ICommunicationPromise.isSuccess] indicates success + * or failure. If the sender is a ConsoleSender this method returns true. + * The promise will fail with: + * - [UnreachableComponentException] if the proxy server the sender is connected is not reachable. + * - [NoSuchPlayerException] if the sender cannot be found on the proxy. + */ + fun hasPermission(permission: String): ICommunicationPromise + + /** + * Checks if the sender has the specified [permission] + * This method blocks until the result is ready + * @return whether the player has the permission or false if there was an error + */ + fun hasPermissionSync(permission: String): Boolean = hasPermission(permission).getBlockingOrNull() ?: false + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractJsonLibConfigLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractJsonLibConfigLoader.kt new file mode 100644 index 000000000..53d036623 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractJsonLibConfigLoader.kt @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.config + +import com.google.gson.Gson +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +abstract class AbstractJsonLibConfigLoader( + private val configClass: Class, + private val configFie: File, + private val lazyDefaultObject: () -> T, + private val saveDefaultOnFistLoad: Boolean, + private val gsonToUse: Gson = JsonLib.GSON +) : IConfigLoader { + + override fun loadConfig(): T { + val objectFromFile = JsonLib.fromJsonFile(configFie, gsonToUse)?.getObjectOrNull(configClass) + if (objectFromFile == null) { + val defaultObject = lazyDefaultObject() + if (saveDefaultOnFistLoad && !doesConfigFileExist()) + saveConfig(defaultObject) + return defaultObject + } + return objectFromFile + } + + override fun saveConfig(value: T) { + JsonLib.fromObject(value, gsonToUse).saveAsFile(configFie) + } + + override fun doesConfigFileExist(): Boolean = this.configFie.exists() + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractMultipleConfigLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractMultipleConfigLoader.kt new file mode 100644 index 000000000..7dde2084b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/AbstractMultipleConfigLoader.kt @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.config + +import com.google.gson.Gson +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 12.12.2020 + * Time: 11:32 + * @author Frederick Baier + */ +abstract class AbstractMultipleConfigLoader( + private val clazz: Class, + private val directory: File, + private val defaultValues: List, + private val saveDefaultOnFirstLoad: Boolean, + private val gsonToUse: Gson = JsonLib.GSON +) : IFileHandler { + + override fun save(value: T) { + JsonLib.fromObject(value, gsonToUse).saveAsFile(getFileByObject(value)) + } + + override fun delete(value: T) { + getFileByObject(value).delete() + } + + override fun loadAll(): Set { + if (!directory.exists() && saveDefaultOnFirstLoad) saveDefaults() + return this.directory.listFiles()?.mapNotNull { JsonLib.fromJsonFile(it, gsonToUse)?.getObject(clazz) }?.toSet() + ?: emptySet() + } + + private fun saveDefaults() { + defaultValues.forEach { save(it) } + } + + private fun getFileByObject(value: T): File { + return File(this.directory, value.getName() + ".json") + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IConfigLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IConfigLoader.kt new file mode 100644 index 000000000..62868da43 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IConfigLoader.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.config + +interface IConfigLoader { + + /** + * Load the config form the file. + * If the config does not exist it returns a default value without creating the file. + */ + fun loadConfig(): T + + /** + * Saves the object to the config file + */ + fun saveConfig(value: T) + + /** + * Returns whether the config file exist + */ + fun doesConfigFileExist(): Boolean + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IFileHandler.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IFileHandler.kt new file mode 100644 index 000000000..790b61e9d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/config/IFileHandler.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.config + +interface IFileHandler { + + /** + * Saves the specified value to a file + */ + fun save(value: T) + + /** + * Deletes the file found yb the specified value + */ + fun delete(value: T) + + /** + * Loads all saved objects + */ + fun loadAll(): Set + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/depedency/DependenciesInformation.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/depedency/DependenciesInformation.kt new file mode 100644 index 000000000..7fa425d20 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/depedency/DependenciesInformation.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.depedency + +import eu.thesimplecloud.runner.dependency.CloudDependency + +class DependenciesInformation(val repositories: List, val dependencies: List) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/directorypaths/DirectoryPaths.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/directorypaths/DirectoryPaths.kt new file mode 100644 index 000000000..313d3fcb9 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/directorypaths/DirectoryPaths.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.directorypaths + +class DirectoryPaths( + val groupsPath: String = "groups/", + val proxyGroupsPath: String = groupsPath + "proxies/", + val serverGroupsPath: String = groupsPath + "servers/", + val lobbyGroupsPath: String = groupsPath + "lobbies/", + val storagePath: String = "storage/", + val templatesPath: String = "templates/", + val tempPath: String = "tmp/", + val staticPath: String = "static/", + val minecraftJarsPath: String = storagePath + "minecraftJars/", + val languagesPath: String = storagePath + "languages/", + val modulesPath: String = "modules/", + val wrappersPath: String = storagePath + "wrappers/", + val zippedTemplatesPath: String = storagePath + "zippedTemplates/", +) { + companion object { + lateinit var paths: DirectoryPaths + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/dto/PlayerLoginRequestResult.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/dto/PlayerLoginRequestResult.kt new file mode 100644 index 000000000..8cfbec6a0 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/dto/PlayerLoginRequestResult.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.dto + +/** + * Created by IntelliJ IDEA. + * Date: 17.12.2020 + * Time: 23:33 + * @author Frederick Baier + */ +data class PlayerLoginRequestResult( + val cancel: Boolean, + val kickMessage: String +) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupCreatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupCreatedEvent.kt new file mode 100644 index 000000000..b06fdf263 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupCreatedEvent.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.group + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +/** + * Created by IntelliJ IDEA. + * Date: 15.07.2020 + * Time: 23:17 + * @author Frederick Baier + * + * Called when a service was updated + */ +class CloudServiceGroupCreatedEvent(serviceGroup: ICloudServiceGroup) : CloudServiceGroupEvent(serviceGroup) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupEvent.kt new file mode 100644 index 000000000..a8a94d7c7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupEvent.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.group + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +/** + * Created by IntelliJ IDEA. + * Date: 15.07.2020 + * Time: 23:16 + * @author Frederick Baier + */ +open class CloudServiceGroupEvent(val serviceGroup: ICloudServiceGroup) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupUpdatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupUpdatedEvent.kt new file mode 100644 index 000000000..b3e382e8b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/group/CloudServiceGroupUpdatedEvent.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.group + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +/** + * Created by IntelliJ IDEA. + * Date: 15.07.2020 + * Time: 23:17 + * @author Frederick Baier + * + * Called when a service was updated + */ +class CloudServiceGroupUpdatedEvent(serviceGroup: ICloudServiceGroup) : CloudServiceGroupEvent(serviceGroup) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerCommandExecuteEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerCommandExecuteEvent.kt new file mode 100644 index 000000000..81ff559be --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerCommandExecuteEvent.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * This event will be called when a player executes any command + */ +class CloudPlayerCommandExecuteEvent( + /** + * The unique id of the player involved in this event + */ + val playerUniqueId: UUID, + + /** + * The name of the player involved in this event + */ + val playerName: String, + + /** + * The executed command + */ + val command: String +) : ISynchronizedEvent { + + fun getCloudPlayer(): ICommunicationPromise = + CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(playerUniqueId) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerDisconnectEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerDisconnectEvent.kt new file mode 100644 index 000000000..df1416ea7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerDisconnectEvent.kt @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * This event is called when a player disconnects from the network + */ +class CloudPlayerDisconnectEvent( + /** + * The unique id of the player involved in this event + */ + val playerUniqueId: UUID, + + /** + * The name of the player involved in this event + */ + val playerName: String +) : ISynchronizedEvent { + + fun getCloudPlayer(): ICommunicationPromise = + CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(playerUniqueId) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerEvent.kt new file mode 100644 index 000000000..58e07410d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.player.ICloudPlayer + +open class CloudPlayerEvent(val cloudPlayer: ICloudPlayer) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerLoginEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerLoginEvent.kt new file mode 100644 index 000000000..bf749b108 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerLoginEvent.kt @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * This event is called when a player logged in to the network + */ +class CloudPlayerLoginEvent( + /** + * The unique id of the player involved in this event + */ + val playerUniqueId: UUID, + + /** + * The name of the player involved in this event + */ + val playerName: String +) : ISynchronizedEvent { + + fun getCloudPlayer(): ICommunicationPromise = + CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(playerUniqueId) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerMessageEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerMessageEvent.kt new file mode 100644 index 000000000..0ac40d155 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerMessageEvent.kt @@ -0,0 +1,26 @@ +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.service.ICloudService + +/** + * Created by MrManHD + * Class create at 23.06.2023 23:09 + */ + +/** + * This event is called when a player sends a chat message + */ +class CloudPlayerMessageEvent( + cloudPlayer: ICloudPlayer, + + /** + * The chat message from this player + */ + val message: String, + + /** + * The cloud service where the player sent the chat message + */ + val cloudService: ICloudService +) : CloudPlayerEvent(cloudPlayer) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerRegisteredEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerRegisteredEvent.kt new file mode 100644 index 000000000..4edd75ffd --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerRegisteredEvent.kt @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.player.ICloudPlayer + +/** + * This event is called when a player is updated the first time on a service. This event means not that the player is now logged in to the network. + * @see CloudPlayerLoginEvent + */ +class CloudPlayerRegisteredEvent(cloudPlayer: ICloudPlayer) : CloudPlayerEvent(cloudPlayer) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectEvent.kt new file mode 100644 index 000000000..667b22c8a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectEvent.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.service.ICloudService + +/** + * This event is called when a player changed his server. The event will only be called on services that receive updates of the player. + * @see [ICloudPlayer.enableUpdates] + */ +class CloudPlayerServerConnectEvent( + /** + * The player involved in this event. + */ + val cloudPlayer: ICloudPlayer, + /** + * The server the player switched from. The server can be null if the player was on no server before. + */ + val from: ICloudService?, + /** + * The server the player switched to. + */ + val to: ICloudService +) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectedEvent.kt new file mode 100644 index 000000000..f5d968f05 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerServerConnectedEvent.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.service.ICloudService + +/** + * This event is called when a player is connected to a server + */ +class CloudPlayerServerConnectedEvent(cloudPlayer: ICloudPlayer, val server: ICloudService) : + CloudPlayerEvent(cloudPlayer) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUnregisteredEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUnregisteredEvent.kt new file mode 100644 index 000000000..db06efdbc --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUnregisteredEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.player.ICloudPlayer + +/** + * This event is called when a player was removed from this network component. This event is not called when a player + * leaves the network. + * + * @see CloudPlayerDisconnectEvent + */ +class CloudPlayerUnregisteredEvent(cloudPlayer: ICloudPlayer) : CloudPlayerEvent(cloudPlayer) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUpdatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUpdatedEvent.kt new file mode 100644 index 000000000..57908f89c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/CloudPlayerUpdatedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player + +import eu.thesimplecloud.api.player.ICloudPlayer + +/** + * This event is called when a network component receives an update of a player. Note, that not every component will + * receive updates. + * To read more about updates + * @see ICloudPlayer.enableUpdates + */ +class CloudPlayerUpdatedEvent(cloudPlayer: ICloudPlayer) : CloudPlayerEvent(cloudPlayer) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/CloudPlayerPermissionCheckEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/CloudPlayerPermissionCheckEvent.kt new file mode 100644 index 000000000..0d8caaef7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/CloudPlayerPermissionCheckEvent.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player.permission + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.player.ICloudPlayer + +/** + * This event is called when [ICloudPlayer.hasPermission] is called. If the result of this event is [PermissionState.UNKNOWN] + * a packet to check the permission will be sent to the player's proxy. + * Note, that the permission module of SimpleCloud uses this event and sets the [PermissionState] on every component + * in the network. + */ +class CloudPlayerPermissionCheckEvent( + val cloudPlayer: ICloudPlayer, + val permission: String, + var state: PermissionState = PermissionState.UNKNOWN +) : IEvent { + + + fun setHasPermission(boolean: Boolean) { + this.state = PermissionState.valueOf(boolean.toString().toUpperCase()) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/PermissionState.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/PermissionState.kt new file mode 100644 index 000000000..74fbb238b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/player/permission/PermissionState.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.player.permission + +/** + * Represents the result of the [CloudPlayerPermissionCheckEvent] + */ +enum class PermissionState { + + TRUE, FALSE, UNKNOWN + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceConnectedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceConnectedEvent.kt new file mode 100644 index 000000000..7dd3b5afe --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceConnectedEvent.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService + +/** + * Called when the [cloudService] connects to the manager + */ +class CloudServiceConnectedEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceEvent.kt new file mode 100644 index 000000000..7247bf779 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.service.ICloudService + +open class CloudServiceEvent(val cloudService: ICloudService) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceInvisibleEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceInvisibleEvent.kt new file mode 100644 index 000000000..f9ba1143b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceInvisibleEvent.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService + +/** + * Called when the [cloudService] connects to the manager + */ +class CloudServiceInvisibleEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceRegisteredEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceRegisteredEvent.kt new file mode 100644 index 000000000..49ea589d0 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceRegisteredEvent.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService + +/** + * Called when a service updates the first time on a network component. + */ +class CloudServiceRegisteredEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartedEvent.kt new file mode 100644 index 000000000..e47f65a8e --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartedEvent.kt @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState + +/** + * Called when the state of a [cloudService] changed to [ServiceState.VISIBLE] or [ServiceState.INVISIBLE] and was not [ServiceState.VISIBLE] or [ServiceState.INVISIBLE] before. + */ +class CloudServiceStartedEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartingEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartingEvent.kt new file mode 100644 index 000000000..75fc35c1d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceStartingEvent.kt @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState + +/** + * Called when a service changes its state from [ServiceState.PREPARED] to [ServiceState.STARTING] + */ +class CloudServiceStartingEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUnregisteredEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUnregisteredEvent.kt new file mode 100644 index 000000000..e8b432adc --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUnregisteredEvent.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService + +/** + * Called when a service was unregistered (stopped) + */ +class CloudServiceUnregisteredEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUpdatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUpdatedEvent.kt new file mode 100644 index 000000000..b69e3e435 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/service/CloudServiceUpdatedEvent.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.service + +import eu.thesimplecloud.api.service.ICloudService + +/** + * Called when a service was updated. + */ +class CloudServiceUpdatedEvent(cloudService: ICloudService) : CloudServiceEvent(cloudService) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectRemovedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectRemovedEvent.kt new file mode 100644 index 000000000..5ac926499 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectRemovedEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.sync.list + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.property.IProperty + +class SynchronizedListObjectRemovedEvent(val property: IProperty) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectUpdatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectUpdatedEvent.kt new file mode 100644 index 000000000..3d5c7c7f7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/list/SynchronizedListObjectUpdatedEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.sync.list + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.property.IProperty + +class SynchronizedListObjectUpdatedEvent(val property: IProperty) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/object/GlobalPropertyUpdatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/object/GlobalPropertyUpdatedEvent.kt new file mode 100644 index 000000000..9be9ea84b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/sync/object/GlobalPropertyUpdatedEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.sync.`object` + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.property.IProperty + +class GlobalPropertyUpdatedEvent(val propertyName: String, val property: IProperty) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperEvent.kt new file mode 100644 index 000000000..0ffcbdc6e --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.wrapper + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.wrapper.IWrapperInfo + +open class WrapperEvent(val wrapper: IWrapperInfo) : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperUpdatedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperUpdatedEvent.kt new file mode 100644 index 000000000..cd526f207 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/event/wrapper/WrapperUpdatedEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.event.wrapper + +import eu.thesimplecloud.api.wrapper.IWrapperInfo + +class WrapperUpdatedEvent(wrapper: IWrapperInfo) : WrapperEvent(wrapper) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/BasicEventManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/BasicEventManager.kt new file mode 100644 index 000000000..874703a5b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/BasicEventManager.kt @@ -0,0 +1,139 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.eventapi.exception.EventException +import eu.thesimplecloud.api.external.ICloudModule +import java.lang.reflect.Method +import java.util.concurrent.CopyOnWriteArrayList + +open class BasicEventManager : IEventManager { + + /** + * The map with all [IEvent]s and the listener methods. + */ + private val listeners = Maps.newConcurrentMap, MutableList>() + + override fun registerListener(cloudModule: ICloudModule, listener: IListener) { + for (method in getValidMethods(listener::class.java)) { + val eventClass = method.parameterTypes[0] as Class + addRegisteredEvent(RegisteredEvent.fromEventMethod(cloudModule, eventClass, listener, method)) + } + } + + override fun registerEvent( + cloudModule: ICloudModule, + eventClass: Class, + listener: IListener, + eventExecutor: IEventExecutor + ) { + addRegisteredEvent(RegisteredEvent(cloudModule, eventClass, listener, eventExecutor)) + } + + override fun unregisterListener(listener: IListener) { + val list = this.listeners.values.map { it.filter { it.listener == listener } }.flatten() + list.forEach { removeRegisteredEvent(it) } + } + + override fun call(event: IEvent, fromPacket: Boolean) { + this.listeners[event::class.java]?.forEach { registeredEvent -> + registeredEvent.eventExecutor.execute(event) + } + } + + override fun unregisterAllListenersByCloudModule(cloudModule: ICloudModule) { + listeners.values.forEach { list -> list.removeIf { it.cloudModule == cloudModule } } + } + + override fun unregisterAll() { + this.listeners.clear() + } + + /** + * Gets all methods that have the [CloudEventHandler] annotation and only one parameter + * + * @param listenerClass + * @return + */ + private fun getValidMethods(listenerClass: Class): List { + val methods = listenerClass.declaredMethods + .filter { + it.isAnnotationPresent(CloudEventHandler::class.java) && it.parameterTypes.size == 1 && IEvent::class.java.isAssignableFrom( + it.parameterTypes[0] + ) + } + methods.forEach { it.isAccessible = true } + return methods + } + + /** + * Adds the [RegisteredEvent] to the listeners map. + * + * @param registeredEvent the [RegisteredEvent] that should be registered. + */ + private fun addRegisteredEvent(registeredEvent: RegisteredEvent) { + this.listeners.getOrPut(registeredEvent.eventClass, { CopyOnWriteArrayList() }).add(registeredEvent) + } + + /** + * Removes the [RegisteredEvent] from the listeners map. + * + * @param registeredEvent the [RegisteredEvent] that should be removed. + */ + private fun removeRegisteredEvent(registeredEvent: RegisteredEvent) { + this.listeners[registeredEvent.eventClass]?.remove(registeredEvent) + } + + data class RegisteredEvent( + val cloudModule: ICloudModule, + val eventClass: Class, + val listener: IListener, + val eventExecutor: IEventExecutor + ) { + + companion object { + fun fromEventMethod( + cloudModule: ICloudModule, + eventClass: Class, + listener: IListener, + method: Method + ): RegisteredEvent { + return RegisteredEvent(cloudModule, eventClass, listener, object : IEventExecutor { + + override fun execute(event: IEvent) { + if (!eventClass.isAssignableFrom(event.javaClass)) + return + try { + method.invoke(listener, event) + } catch (ex: Exception) { + throw EventException(event, ex) + } + } + }) + } + } + + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/CloudEventHandler.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/CloudEventHandler.kt new file mode 100644 index 000000000..89f93557f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/CloudEventHandler.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class CloudEventHandler diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ICancellable.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ICancellable.kt new file mode 100644 index 000000000..014f0136d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ICancellable.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +/** + * Represents a class that can be cancelled. + */ +interface ICancellable { + + /** + * Returns whether this action was cancelled. + */ + fun isCancelled(): Boolean + + /** + * Sets the cancelled state + */ + fun setCancelled(cancel: Boolean) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEvent.kt new file mode 100644 index 000000000..b7acda4a6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +/** + * All events should implement this interface. + */ +interface IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventExecutor.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventExecutor.kt new file mode 100644 index 000000000..c5046cd6d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventExecutor.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +import eu.thesimplecloud.api.eventapi.exception.EventException + +@FunctionalInterface +interface IEventExecutor { + + /** + * Executes the specified event. + */ + @Throws(EventException::class) + fun execute(event: IEvent) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventManager.kt new file mode 100644 index 000000000..df2b92ac1 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IEventManager.kt @@ -0,0 +1,73 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +import eu.thesimplecloud.api.eventapi.exception.EventException +import eu.thesimplecloud.api.external.ICloudModule + +interface IEventManager { + + /** + * Registers all methods from the specified object that has the [CloudEventHandler] annotation. + * + * @param listener the listener object from which the methods should be registered. + */ + fun registerListener(cloudModule: ICloudModule, listener: IListener) + + /** + * Registers one event. + */ + fun registerEvent( + cloudModule: ICloudModule, + eventClass: Class, + listener: IListener, + eventExecutor: IEventExecutor + ) + + /** + * Unregisters all methods from the specified object that has the [CloudEventHandler] annotation. + * + * @param listener the listener object from which the methods should be unregistered. + */ + fun unregisterListener(listener: IListener) + + /** + * Calls all methods which were registered. + * + * @param event the event which should be called. + * @param fromPacket whether the event shall be synchronized with all components. Only used when the specified [event] is a [ISynchronizedEvent]. + */ + @Throws(EventException::class) + fun call(event: IEvent, fromPacket: Boolean = false) + + /** + * Unregisters all listeners registered with the specified [ICloudModule]. + */ + fun unregisterAllListenersByCloudModule(cloudModule: ICloudModule) + + /** + * Unregisters all listeners. + */ + fun unregisterAll() + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IListener.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IListener.kt new file mode 100644 index 000000000..aaaee9cc9 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/IListener.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +/** + * All listeners should implement this interface + */ +interface IListener { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ISynchronizedEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ISynchronizedEvent.kt new file mode 100644 index 000000000..e0cea1b5d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/ISynchronizedEvent.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +/** + * A special type of [IEvent] + * Synchronized events will be sent to all connected components(Wrappers and services). Because of this they must not contain any unserializable member variables like interfaces. + */ +interface ISynchronizedEvent : IEvent \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/exception/EventException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/exception/EventException.kt new file mode 100644 index 000000000..3f9ec7244 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/eventapi/exception/EventException.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi.exception + +import eu.thesimplecloud.api.eventapi.IEvent + +class EventException(causeEvent: IEvent, cause: Throwable) : + Exception("An error occurred while attempting to handle event ${causeEvent::class.java.name}", cause) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchPlayerException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchPlayerException.kt new file mode 100644 index 000000000..37fb5b561 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchPlayerException.kt @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.exception + +class NoSuchPlayerException(reason: String) : Exception(reason) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchServiceException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchServiceException.kt new file mode 100644 index 000000000..fe57d7d67 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchServiceException.kt @@ -0,0 +1,25 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.exception + +class NoSuchServiceException(message: String) : Exception(message) diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchWorldException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchWorldException.kt new file mode 100644 index 000000000..b12275b22 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/NoSuchWorldException.kt @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.exception + +class NoSuchWorldException(reason: String) : Exception(reason) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/PlayerConnectException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/PlayerConnectException.kt new file mode 100644 index 000000000..367f91bfb --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/PlayerConnectException.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.exception + +/** + * This exception is used to indicate that the proxy was unable to send the player to a service. + */ +class PlayerConnectException(message: String) : Exception(message) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/SerializationException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/SerializationException.kt new file mode 100644 index 000000000..e055c9a68 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/SerializationException.kt @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.exception + +class SerializationException(message: String) : Exception(message) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/UnreachableComponentException.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/UnreachableComponentException.kt new file mode 100644 index 000000000..a4d3b0ce6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/exception/UnreachableComponentException.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.exception + +/** + * This exception is thrown when a service is not available or not connected to the manager. + */ +class UnreachableComponentException(reason: String) : Exception(reason) { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/extension/ClientManagerExtension.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/extension/ClientManagerExtension.kt new file mode 100644 index 000000000..37e2aee61 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/extension/ClientManagerExtension.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.extension + +import eu.thesimplecloud.api.network.component.IAuthenticatable +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.combineAllPromises +import eu.thesimplecloud.clientserverapi.server.client.clientmanager.IClientManager +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClient +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClientValue + +fun IClientManager<*>.getAllAuthenticatedClients(): List> { + return this.getClients() + .filter { it.isOpen() } + .filter { it.getClientValue() != null && (it.getClientValue() as IAuthenticatable).isAuthenticated() } +} + +fun IClientManager<*>.sendPacketToAllAuthenticatedClients(packet: IPacket): ICommunicationPromise { + return this.getAllAuthenticatedClients().map { it.sendUnitQuery(packet) }.combineAllPromises() +} + +fun IClientManager<*>.sendPacketToAllAuthenticatedNonWrapperClients(packet: IPacket): ICommunicationPromise { + return this.getAllAuthenticatedClients().filter { it.getClientValue() !is IWrapperInfo } + .map { it.sendUnitQuery(packet) } + .combineAllPromises() +} + +fun IClientManager<*>.sendPacketToAllAuthenticatedWrapperClients(packet: IPacket) { + this.getAllAuthenticatedClients().filter { it.getClientValue() is IWrapperInfo } + .forEach { it.sendUnitQuery(packet) } +} diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/external/ICloudModule.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/external/ICloudModule.kt new file mode 100644 index 000000000..b522d8bb6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/external/ICloudModule.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.external + +interface ICloudModule { + + /** + * Called when the plugin is enabled + */ + fun onEnable() + + /** + * Called when the plugin is disabled + */ + fun onDisable() + + /** + * Returns whether this module is reloadable + */ + fun isReloadable() = true + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/ILanguageManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/ILanguageManager.kt new file mode 100644 index 000000000..29c12bdff --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/ILanguageManager.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.language + +import eu.thesimplecloud.api.external.ICloudModule + +/** + * Created by IntelliJ IDEA. + * Date: 14.10.2020 + * Time: 22:24 + * @author Frederick Baier + */ +interface ILanguageManager { + + /** + * Registers a language file for the specified [cloudModule] + */ + fun registerLanguageFile(cloudModule: ICloudModule, languageFile: LoadedLanguageFile) + + /** + * Returns the replaced message found by the property with the [placeholderValues] + * If the [property] cannot be found it will return the [property] + */ + fun getMessage(property: String, vararg placeholderValues: String): String + + /** + * Unregisters the [LoadedLanguageFile] by the specified [cloudModule] + */ + fun unregisterLanguageFileByCloudModule(cloudModule: ICloudModule) + + /** + * Clears all language properties + */ + fun clearAll() + + /** + * Returns a list of all registered [LanguageProperty]s + */ + fun getAllProperties(): List + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageManager.kt new file mode 100644 index 000000000..fcd42cad6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageManager.kt @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.language + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.external.ICloudModule + + +open class LanguageManager : ILanguageManager { + + private val languageFiles = Maps.newConcurrentMap() + + override fun registerLanguageFile(cloudModule: ICloudModule, languageFile: LoadedLanguageFile) { + this.languageFiles[cloudModule] = languageFile + } + + override fun getMessage(property: String, vararg placeholderValues: String): String { + val allProperties = this.languageFiles.values.map { it.getProperties() }.flatten() + val languageProperty = allProperties.firstOrNull { it.property == property } ?: return property + return languageProperty.getReplacedMessage(*placeholderValues) + } + + override fun unregisterLanguageFileByCloudModule(cloudModule: ICloudModule) { + this.languageFiles.remove(cloudModule) + } + + override fun clearAll() { + this.languageFiles.clear() + } + + override fun getAllProperties(): List { + return this.languageFiles.values.map { it.getProperties() }.flatten() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguagePlaceholder.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguagePlaceholder.kt new file mode 100644 index 000000000..692326277 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguagePlaceholder.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.language + +/** + * Created by IntelliJ IDEA. + * Date: 15.10.2020 + * Time: 18:36 + * @author Frederick Baier + */ +class LanguagePlaceholder(val placeholderName: String) { + + fun getStringToReplace(): String { + return "%${placeholderName}%" + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageProperty.kt new file mode 100644 index 000000000..32a535492 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LanguageProperty.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.language + +class LanguageProperty(val property: String, val message: String) { + + + /** + * Returns all placeholders in this message. + * + * Messages look like this + * Service %SERVICE% was stopped. + */ + fun getAllPlaceHolders(): List { + val percentParts = this.message.split("%") + //is number not divisible by 2 + if (percentParts.lastIndex % 2 != 0) { + throw IllegalArgumentException("Invalid message format for property $property") + } + + val returnList = mutableListOf() + //all indices of placeholders + for (i in 1..percentParts.lastIndex step 2) { + returnList.add(LanguagePlaceholder(percentParts[i])) + } + return returnList + } + + fun getReplacedMessage(vararg replacements: String): String { + val allPlaceHolders = getAllPlaceHolders() + var message = this.message + val replacementsIterator = replacements.iterator() + for (placeHolder in allPlaceHolders) { + message = message.replace(placeHolder.getStringToReplace(), replacementsIterator.next()) + } + return message + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LoadedLanguageFile.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LoadedLanguageFile.kt new file mode 100644 index 000000000..6f421a851 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/language/LoadedLanguageFile.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.language + +/** + * Created by IntelliJ IDEA. + * Date: 15.10.2020 + * Time: 21:55 + * @author Frederick Baier + */ +class LoadedLanguageFile( + private val properties: List = ArrayList() +) { + + fun getProperties(): List { + return this.properties + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListener.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListener.kt new file mode 100644 index 000000000..2397c681a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListener.kt @@ -0,0 +1,103 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.listenerextension + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.eventapi.IEventExecutor +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import io.netty.util.concurrent.GlobalEventExecutor +import java.util.concurrent.TimeUnit + +open class AdvancedListener( + eventClass: Class, + autoUnregister: Boolean = true, + unregisterTimeInSeconds: Long = 5 * 60 +) : IAdvancedListener { + + private val conditions = ArrayList<(T) -> Boolean>() + private val actions = ArrayList<(T) -> Unit>() + private val listenerObj = object : IListener {} + + init { + + CloudAPI.instance.getEventManager().registerEvent( + CloudAPI.instance.getThisSidesCloudModule(), + eventClass, + listenerObj, object : IEventExecutor { + override fun execute(event: IEvent) { + if (!eventClass.isAssignableFrom(event.javaClass)) + return + event as T + if (conditions.all { it(event) }) actions.forEach { it(event) } + } + }) + if (autoUnregister) { + GlobalEventExecutor.INSTANCE.schedule({ + this.unregister() + }, unregisterTimeInSeconds, TimeUnit.SECONDS) + } + } + + override fun addCondition(predicate: (T) -> Boolean): IAdvancedListener { + this.conditions.add(predicate) + return this + } + + override fun addAction(function: (T) -> Unit): IAdvancedListener { + this.actions.add(function) + return this + } + + override fun unregisterWhen(advancedListener: IAdvancedListener<*>): IAdvancedListener { + advancedListener.addAction { this.unregister() } + return this + } + + override fun unregister() { + CloudAPI.instance.getEventManager().unregisterListener(listenerObj) + } + + override fun unregisterAfterCall(): IAdvancedListener { + this.addAction { this.unregister() } + return this + } + + override fun toPromise(): ICommunicationPromise { + val newPromise = CommunicationPromise(enableTimeout = false) + this.addAction { newPromise.trySuccess(it) } + this.unregisterAfterCall() + return newPromise + } + + override fun toUnitPromise(): ICommunicationPromise { + val newPromise = CommunicationPromise(enableTimeout = false) + this.addAction { newPromise.trySuccess(Unit) } + this.unregisterAfterCall() + return newPromise + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListenerExtension.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListenerExtension.kt new file mode 100644 index 000000000..b4494f398 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/AdvancedListenerExtension.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.listenerextension + +import eu.thesimplecloud.api.eventapi.IEvent + +inline fun cloudListener( + autoUnregister: Boolean = true, + unregisterTimeInSeconds: Long = 5 * 60 +): AdvancedListener { + return AdvancedListener(T::class.java, autoUnregister, unregisterTimeInSeconds) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/IAdvancedListener.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/IAdvancedListener.kt new file mode 100644 index 000000000..e5d92470b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/listenerextension/IAdvancedListener.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.listenerextension + +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +interface IAdvancedListener { + + /** + * Adds a condition to this listener + * @return this listener + */ + fun addCondition(predicate: (T) -> Boolean): IAdvancedListener + + /** + * Adds an action to this listener + * @return this listener + */ + fun addAction(function: (T) -> Unit): IAdvancedListener + + /** + * Unregisters this listener when the specified listener is called + * @return this listener + */ + fun unregisterWhen(advancedListener: IAdvancedListener<*>): IAdvancedListener + + /** + * Unregisters this listener + */ + fun unregister() + + /** + * Unregisters this listener after one call. + * @return this listener + */ + fun unregisterAfterCall(): IAdvancedListener + + /** + * Returns a promise that completes when the listener was called. + */ + fun toPromise(): ICommunicationPromise + + /** + * Returns a promise that completes when the listener was called. + */ + fun toUnitPromise(): ICommunicationPromise + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/GroupLocation.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/GroupLocation.kt new file mode 100644 index 000000000..2ed70557a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/GroupLocation.kt @@ -0,0 +1,84 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.location + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +open class GroupLocation( + private val serviceGroupName: String, + worldName: String, + x: Double, + y: Double, + z: Double, + yaw: Float, + pitch: Float +) : SimpleLocation(worldName, x, y, z, yaw, pitch) { + + /** + * Returns the group this location belongs to. + */ + fun getGroup(): ICloudServiceGroup? = + CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(serviceGroupName) + + override fun add(x: Double, y: Double, z: Double): GroupLocation { + return GroupLocation( + this.serviceGroupName, + this.worldName, + this.x + x, + this.y + y, + this.z + z, + this.yaw, + this.pitch + ) + } + + override fun setWorldName(worldName: String): GroupLocation { + return GroupLocation(this.serviceGroupName, worldName, this.x, this.y, this.z, this.yaw, this.pitch) + } + + /** + * Returns the template location of this location + */ + fun toTemplateLocation(): TemplateLocation { + val group = getGroup() ?: throw IllegalStateException("Group $serviceGroupName cannot be found") + return TemplateLocation(group.getTemplateName(), worldName, x, y, z, yaw, pitch) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is GroupLocation) return false + if (!super.equals(other)) return false + + if (serviceGroupName != other.serviceGroupName) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + serviceGroupName.hashCode() + return result + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/ServiceLocation.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/ServiceLocation.kt new file mode 100644 index 000000000..22f5ef421 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/ServiceLocation.kt @@ -0,0 +1,128 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.location + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService + + +class ServiceLocation( + val serviceName: String, + worldName: String, + x: Double, + y: Double, + z: Double, + yaw: Float, + pitch: Float +) : SimpleLocation(worldName, x, y, z, yaw, pitch) { + + val groupName = serviceName.split("-").dropLast(1).joinToString("-") + + constructor( + service: ICloudService, + worldName: String, + x: Double, + y: Double, + z: Double, + yaw: Float, + pitch: Float + ) : this(service.getName(), worldName, x, y, z, yaw, pitch) + + constructor(service: ICloudService, worldName: String, x: Double, y: Double, z: Double) : this( + service, + worldName, + x, + y, + z, + 0F, + 0F + ) + + constructor(serviceName: String, worldName: String, x: Double, y: Double, z: Double) : this( + serviceName, + worldName, + x, + y, + z, + 0F, + 0F + ) + + /** + * Returns this location converted to a [GroupLocation] + */ + fun toGroupLocation() = GroupLocation(groupName, worldName, x, y, z, yaw, pitch) + + /** + * Returns the template location of this location + */ + fun toTemplateLocation(): TemplateLocation { + val service = getService() ?: throw IllegalStateException("Service $serviceName cannot be found") + return TemplateLocation(service.getTemplateName(), worldName, x, y, z, yaw, pitch) + } + + /** + * Returns the service this location is belongs to. + */ + fun getService() = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) + + override fun add(x: Double, y: Double, z: Double): ServiceLocation { + return ServiceLocation( + this.serviceName, + this.worldName, + this.x + x, + this.y + y, + this.z + z, + this.yaw, + this.pitch + ) + } + + override fun setWorldName(worldName: String): ServiceLocation { + return ServiceLocation(this.serviceName, worldName, this.x, this.y, this.z, this.yaw, this.pitch) + } + + /** + * Returns a new [ServiceLocation] with a changed [serviceName] + */ + fun setServiceName(serviceName: String): ServiceLocation { + return ServiceLocation(serviceName, this.worldName, this.x, this.y, this.z, this.yaw, this.pitch) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is ServiceLocation) return false + if (!super.equals(other)) return false + + if (serviceName != other.serviceName) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + serviceName.hashCode() + return result + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/SimpleLocation.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/SimpleLocation.kt new file mode 100644 index 000000000..fff7b83de --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/SimpleLocation.kt @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.location + +open class SimpleLocation( + val worldName: String, + val x: Double, + val y: Double, + val z: Double, + val yaw: Float, + val pitch: Float +) { + constructor(worldName: String, x: Double, y: Double, z: Double) : this(worldName, x, y, z, 0F, 0F) + + /** + * Returns a new location with the specified [x], [y], [z] values added to the current ones. + */ + open fun add(x: Double, y: Double, z: Double): SimpleLocation { + return SimpleLocation(this.worldName, this.x + x, this.y + y, this.z + z, this.yaw, this.pitch) + } + + /** + * Returns a new location with a different [worldName] + */ + open fun setWorldName(worldName: String): SimpleLocation { + return SimpleLocation(worldName, this.x, this.y, this.z, this.yaw, this.pitch) + } + + /** + * Returns a service location with the specified [serviceName] + */ + fun toServiceLocation(serviceName: String): ServiceLocation { + return ServiceLocation(serviceName, worldName, x, y, z, yaw, pitch) + } + + + override fun hashCode(): Int { + var result = worldName.hashCode() + result = 31 * result + x.hashCode() + result = 31 * result + y.hashCode() + result = 31 * result + z.hashCode() + result = 31 * result + yaw.hashCode() + result = 31 * result + pitch.hashCode() + return result + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is SimpleLocation) return false + + if (worldName != other.worldName) return false + if (x != other.x) return false + if (y != other.y) return false + if (z != other.z) return false + if (yaw != other.yaw) return false + if (pitch != other.pitch) return false + + return true + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/TemplateLocation.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/TemplateLocation.kt new file mode 100644 index 000000000..af40c743b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/location/TemplateLocation.kt @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.location + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.template.ITemplate + +class TemplateLocation( + val templateName: String, + worldName: String, + x: Double, + y: Double, + z: Double, + yaw: Float, + pitch: Float +) : SimpleLocation(worldName, x, y, z, yaw, pitch) { + + /** + * Returns the template this location belongs to. + */ + fun getTemplate(): ITemplate? = CloudAPI.instance.getTemplateManager().getTemplateByName(templateName) + + override fun add(x: Double, y: Double, z: Double): TemplateLocation { + return TemplateLocation( + this.templateName, + this.worldName, + this.x + x, + this.y + y, + this.z + z, + this.yaw, + this.pitch + ) + } + + override fun setWorldName(worldName: String): TemplateLocation { + return TemplateLocation(this.templateName, this.worldName, this.x, this.y, this.z, this.yaw, this.pitch) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is TemplateLocation) return false + if (!super.equals(other)) return false + + if (templateName != other.templateName) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + templateName.hashCode() + return result + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannel.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannel.kt new file mode 100644 index 000000000..712f5eb68 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannel.kt @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.message + +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.api.wrapper.IWrapperInfo + +interface IMessageChannel : Nameable { + + /** + * Returns the class of this [IMessageChannel] + */ + fun getMessageClass(): Class + + /** + * Registers a listener + */ + fun registerListener(messageListener: IMessageListener) + + /** + * Unregisters a listener + */ + fun unregisterListener(messageListener: IMessageListener) + + /** + * Sends a message + * As receiver a [ICloudService] or [IWrapperInfo] can be used. + * If you want to send a message to the manager you must use [INetworkComponent.MANAGER_COMPONENT] + * @param msg the object to send + * @param receivers the list of receivers + */ + fun sendMessage(msg: T, receivers: List) + + /** + * Sends a message + * As receiver a [ICloudService] or [IWrapperInfo] can be used. + * If you want to send a message to the manager you must use [INetworkComponent.MANAGER_COMPONENT] + * @param msg the object to send + * @param receiver the receiver + */ + fun sendMessage(msg: T, receiver: INetworkComponent) = sendMessage(msg, listOf(receiver)) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannelManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannelManager.kt new file mode 100644 index 000000000..ba2ff4a7a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageChannelManager.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.message + +import eu.thesimplecloud.api.external.ICloudModule + +interface IMessageChannelManager { + + /** + * Registers a new [MessageChannel] + * + */ + fun registerMessageChannel(cloudModule: ICloudModule, name: String, clazz: Class): IMessageChannel + + /** + * Return the [IMessageChannel] found by the specified [name] + */ + fun getMessageChannelByName(name: String): IMessageChannel? + + /** + * Unregisters the message channel found by the specified [name] + */ + fun unregisterMessageChannel(name: String) + + /** + * Unregisters all message channel registered by the specified [cloudModule] + */ + fun unregisterMessageChannel(cloudModule: ICloudModule) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageListener.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageListener.kt new file mode 100644 index 000000000..51b3ef801 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/IMessageListener.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.message + +import eu.thesimplecloud.api.network.component.INetworkComponent + +interface IMessageListener { + + /** + * This method will be called when the listener receives a message, + */ + fun messageReceived(msg: T, sender: INetworkComponent) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/Message.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/Message.kt new file mode 100644 index 000000000..b94daf9cf --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/Message.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.message + +import eu.thesimplecloud.api.client.NetworkComponentReference + +data class Message( + val channel: String, + val className: String, + val messageString: String, + val senderReference: NetworkComponentReference, + val receivers: List +) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannel.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannel.kt new file mode 100644 index 000000000..c84fb2c39 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannel.kt @@ -0,0 +1,84 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.message + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.jsonlib.GsonCreator +import eu.thesimplecloud.jsonlib.JsonLib +import java.util.concurrent.CopyOnWriteArraySet + + +class MessageChannel(val cloudModule: ICloudModule, private val name: String, private val clazz: Class) : + IMessageChannel { + + companion object { + private val GSON = GsonCreator().create() + } + + private val listeners = CopyOnWriteArraySet>() + + override fun registerListener(messageListener: IMessageListener) { + this.listeners.add(messageListener) + } + + override fun unregisterListener(messageListener: IMessageListener) { + this.listeners.remove(messageListener) + } + + /** + * Notifies all listeners. + */ + fun notifyListeners(message: Message) { + if (message.className != clazz.name) + throw IllegalArgumentException("Invalid message class on message channel ${message.channel}: Expected ${clazz.name} but was ${message.className} ") + val jsonLib = JsonLib.fromJsonString(message.messageString) + val msg = jsonLib.getObject(clazz) + val networkComponent = message.senderReference.getNetworkComponent() + ?: throw IllegalArgumentException("Connected process of ${message.senderReference.name} is null") + this.listeners.forEach { it.messageReceived(msg, networkComponent) } + } + + override fun getName(): String { + return this.name + } + + override fun getMessageClass(): Class { + return this.clazz + } + + override fun sendMessage(msg: T, receivers: List) { + val thisComponent = CloudAPI.instance.getThisSidesNetworkComponent() + val messageString = GSON.toJson(msg) + val message = Message( + getName(), + clazz.name, + messageString, + thisComponent.toNetworkComponentReference(), + receivers.map { it.toNetworkComponentReference() }) + return (CloudAPI.instance.getMessageChannelManager() as MessageChannelManager) + .sendMessage(message) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannelManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannelManager.kt new file mode 100644 index 000000000..97f14825d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/message/MessageChannelManager.kt @@ -0,0 +1,91 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.message + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentReference +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.network.packets.message.PacketIOChannelMessage +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.server.INettyServer + +class MessageChannelManager : IMessageChannelManager { + + private val channels = Maps.newConcurrentMap>() + + override fun registerMessageChannel( + cloudModule: ICloudModule, + name: String, + clazz: Class + ): IMessageChannel { + if (this.channels.containsKey(name)) throw IllegalArgumentException("Channel is already registered") + val messageChannel = MessageChannel(cloudModule, name, clazz) + this.channels[name] = messageChannel + return messageChannel + } + + override fun getMessageChannelByName(name: String): IMessageChannel? { + return this.channels[name] as IMessageChannel? + } + + override fun unregisterMessageChannel(name: String) { + this.channels.remove(name) + } + + override fun unregisterMessageChannel(cloudModule: ICloudModule) { + val messageChannelNamesByModule = + this.channels.entries.filter { it.value.cloudModule == cloudModule }.map { it.key } + messageChannelNamesByModule.forEach { unregisterMessageChannel(it) } + } + + fun sendMessage(message: Message) { + val packetToSend = PacketIOChannelMessage(message) + if (CloudAPI.instance.isManager()) { + val server = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyServer<*> + val allNotManagerReceivers = message.receivers + .filter { it.componentType != NetworkComponentType.MANAGER } + .mapNotNull { it.getNetworkComponent() } + allNotManagerReceivers.forEach { + val client = server.getClientManager().getClientByClientValue(it) + client?.sendUnitQuery(packetToSend) + } + } else { + val client = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyClient + client.getConnection().sendUnitQuery(packetToSend) + } + } + + fun incomingMessage(message: Message) { + val channel = this.channels[message.channel] + if (CloudAPI.instance.isManager()) { + sendMessage(message) + if (message.receivers.contains(NetworkComponentReference.MANAGER_COMPONENT_REFERENCE)) + channel?.notifyListeners(message) + } else { + channel?.notifyListeners(message) + } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/IAuthenticatable.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/IAuthenticatable.kt new file mode 100644 index 000000000..852533c9f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/IAuthenticatable.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.component + +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClientValue + +interface IAuthenticatable { + + /** + * Returns whether this [IConnectedClientValue] is authenticated + */ + fun isAuthenticated(): Boolean + + /** + * Sets this [IConnectedClientValue] authenticated + */ + fun setAuthenticated(authenticated: Boolean) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/INetworkComponent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/INetworkComponent.kt new file mode 100644 index 000000000..d184e7b16 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/INetworkComponent.kt @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.component + +import eu.thesimplecloud.api.client.NetworkComponentReference +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.screen.ICommandExecutable + +interface INetworkComponent : IAuthenticatable, ICommandExecutable { + + companion object { + @JvmStatic + val MANAGER_COMPONENT = ManagerComponent + } + + /** + * Returns the [NetworkComponentType] of this process + */ + fun getNetworkComponentType(): NetworkComponentType + + /** + * Returns the [NetworkComponentReference] of this process. + */ + fun toNetworkComponentReference(): NetworkComponentReference { + return NetworkComponentReference(getNetworkComponentType(), getName()) + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/ManagerComponent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/ManagerComponent.kt new file mode 100644 index 000000000..53c2aebd3 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/component/ManagerComponent.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.component + +import eu.thesimplecloud.api.client.NetworkComponentType + +/** + * Created by IntelliJ IDEA. + * Date: 01.10.2020 + * Time: 17:08 + * @author Frederick Baier + */ +object ManagerComponent : INetworkComponent { + + override fun getNetworkComponentType(): NetworkComponentType { + return NetworkComponentType.MANAGER + } + + override fun isAuthenticated(): Boolean { + return true + } + + override fun setAuthenticated(authenticated: Boolean) { + throw UnsupportedOperationException("Cannot set authenticated state of the manager") + } + + override fun getName(): String { + return "Manager" + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOExecuteFunction.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOExecuteFunction.kt new file mode 100644 index 000000000..9d4dfb291 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOExecuteFunction.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets + +import eu.thesimplecloud.api.exception.SerializationException +import eu.thesimplecloud.api.utils.NoArgsFunction +import eu.thesimplecloud.api.utils.ObjectSerializer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.BytePacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOExecuteFunction() : BytePacket() { + + + constructor(function: () -> T) : this() { + val noArgsFunction = object : NoArgsFunction { + override fun invoke(): T { + return function() + } + } + val serializeString = ObjectSerializer.serialize(noArgsFunction) + this.buffer.writeBytes(serializeString.toByteArray(Charsets.ISO_8859_1)) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val string = String(this.buffer.array(), Charsets.ISO_8859_1) + val noArgsFunction = ObjectSerializer.deserialize>(string) as NoArgsFunction? + noArgsFunction ?: return failure(SerializationException("Object was null")) + return success(noArgsFunction.invoke()) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOPing.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOPing.kt new file mode 100644 index 000000000..f368052ef --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/PacketIOPing.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOPing() : ObjectPacket() { + + constructor(time: Long) : this() { + this.value = time + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + return success(System.currentTimeMillis() - value) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/event/PacketIOCallEvent.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/event/PacketIOCallEvent.kt new file mode 100644 index 000000000..ad4dcb9c6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/event/PacketIOCallEvent.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.event + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOCallEvent() : ObjectPacket() { + + constructor(synchronizedEvent: ISynchronizedEvent) : this() { + this.value = synchronizedEvent + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + CloudAPI.instance.getEventManager().call(value, fromPacket = true) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/language/PacketIOLanguage.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/language/PacketIOLanguage.kt new file mode 100644 index 000000000..32f126655 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/language/PacketIOLanguage.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.language + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.language.LanguageProperty +import eu.thesimplecloud.api.language.LoadedLanguageFile +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 31.10.2020 + * Time: 22:50 + * @author Frederick Baier + */ +class PacketIOLanguage() : ObjectPacket>() { + + + constructor(languageProperties: List) : this() { + this.value = languageProperties.toTypedArray() + } + + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val languageManager = CloudAPI.instance.getLanguageManager() + languageManager.clearAll() + languageManager.registerLanguageFile( + CloudAPI.instance.getThisSidesCloudModule(), + LoadedLanguageFile(value.toList()) + ) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/message/PacketIOChannelMessage.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/message/PacketIOChannelMessage.kt new file mode 100644 index 000000000..3642bad0b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/message/PacketIOChannelMessage.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.message + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.message.Message +import eu.thesimplecloud.api.message.MessageChannelManager +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOChannelMessage() : ObjectPacket() { + + constructor(message: Message) : this() { + this.value = message + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val message = this.value ?: return contentException("value") + val messageChannelManager = CloudAPI.instance.getMessageChannelManager() + as MessageChannelManager + messageChannelManager.incomingMessage(message) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOCloudPlayerForceCommandExecution.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOCloudPlayerForceCommandExecution.kt new file mode 100644 index 000000000..05db55b1f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOCloudPlayerForceCommandExecution.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOCloudPlayerForceCommandExecution() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, command: String) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()) + .append("command", command) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val command = this.jsonLib.getString("command") ?: return contentException("command") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) + cloudPlayer?.forceCommandExecution(command) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOConnectCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOConnectCloudPlayer.kt new file mode 100644 index 000000000..4cda90e1c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOConnectCloudPlayer.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.UnreachableComponentException +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.player.connection.ConnectionResponse +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOConnectCloudPlayer() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, service: ICloudService) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()).append("serviceName", service.getName()) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val serviceName = this.jsonLib.getString("serviceName") ?: return contentException("serviceName") + val cloudService = + CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) ?: return failure( + UnreachableComponentException("") + ) + return CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId)?.connect(cloudService) + ?: return failure(NoSuchElementException("Player not found")) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetAllOnlinePlayers.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetAllOnlinePlayers.kt new file mode 100644 index 000000000..4baa12cef --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetAllOnlinePlayers.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOGetAllOnlinePlayers() : ObjectPacket() { + + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return CloudAPI.instance.getCloudPlayerManager().getAllOnlinePlayers().then { it.toTypedArray() } + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetCloudPlayer.kt new file mode 100644 index 000000000..658d16d4f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetCloudPlayer.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOGetCloudPlayer() : JsonPacket() { + + + constructor(name: String) : this() { + this.jsonLib.append("name", name) + } + + constructor(uniqueId: UUID) : this() { + this.jsonLib.append("uniqueId", uniqueId) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val name = this.jsonLib.getString("name") + val uniqueId = this.jsonLib.getObject("uniqueId", UUID::class.java) + var cloudPlayer: ICloudPlayer? = null + if (name != null) { + cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(name) + } + if (uniqueId != null) { + cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + } + return CommunicationPromise.ofNullable(cloudPlayer, NoSuchElementException("Player not found")) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetNetworkOnlineCount.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetNetworkOnlineCount.kt new file mode 100644 index 000000000..a8733ead4 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetNetworkOnlineCount.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 25.09.2020 + * Time: 20:11 + * @author Frederick Baier + */ +class PacketIOGetNetworkOnlineCount : ObjectPacket() { + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return success(CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().size) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetOfflinePlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetOfflinePlayer.kt new file mode 100644 index 000000000..dab059c7a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetOfflinePlayer.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOGetOfflinePlayer() : JsonPacket() { + + constructor(uniqueId: UUID) : this() { + this.jsonLib.append("uniqueId", uniqueId) + } + + constructor(name: String) : this() { + this.jsonLib.append("name", name) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val uniqueId = this.jsonLib.getObject("uniqueId", UUID::class.java) + val name = this.jsonLib.getString("name") + if (uniqueId == null && name == null) return contentException("name and uniqueId null") + if (uniqueId != null) return CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(uniqueId) + return CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(name!!) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerLocation.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerLocation.kt new file mode 100644 index 000000000..6d50cbde7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerLocation.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOGetPlayerLocation() : ObjectPacket() { + + constructor(cloudPlayer: ICloudPlayer) : this() { + this.value = cloudPlayer.getUniqueId() + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(value) + ?: return failure(NoSuchElementException("Player does not exist")) + return cloudPlayer.getLocation() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerPing.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerPing.kt new file mode 100644 index 000000000..e7a969611 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayerPing.kt @@ -0,0 +1,28 @@ +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * Created by MrManHD + * Class create at 20.06.2023 19:48 + */ + +class PacketIOGetPlayerPing() : ObjectPacket() { + + constructor(cloudPlayer: ICloudPlayer) : this() { + this.value = cloudPlayer.getUniqueId() + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(value) + ?: return failure(NoSuchElementException("Player does not exist")) + return cloudPlayer.getPing() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayersConnectedToService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayersConnectedToService.kt new file mode 100644 index 000000000..6482bbbba --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetPlayersConnectedToService.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchServiceException +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 20.12.2020 + * Time: 10:01 + * @author Frederick Baier + */ +class PacketIOGetPlayersConnectedToService() : ObjectPacket() { + + constructor(service: ICloudService) : this() { + this.value = service.getName() + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val service = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(value) + ?: return failure(NoSuchServiceException("Service cannot be found")) + return service.getOnlinePlayers().then { it.toTypedArray() } + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetRegisteredPlayerCount.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetRegisteredPlayerCount.kt new file mode 100644 index 000000000..cd9081602 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOGetRegisteredPlayerCount.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 25.09.2020 + * Time: 20:11 + * @author Frederick Baier + */ +class PacketIOGetRegisteredPlayerCount : ObjectPacket() { + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return CloudAPI.instance.getCloudPlayerManager().getRegisteredPlayerCount() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOKickCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOKickCloudPlayer.kt new file mode 100644 index 000000000..2690ef7e4 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOKickCloudPlayer.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOKickCloudPlayer() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, message: String) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()).append("message", message) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val message = this.jsonLib.getString("message") ?: return contentException("message") + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId)?.kick(message) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOPlayerHasPermission.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOPlayerHasPermission.kt new file mode 100644 index 000000000..c47f85677 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOPlayerHasPermission.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOPlayerHasPermission() : JsonPacket() { + + constructor(uniqueId: UUID, permission: String) : this() { + this.jsonLib.append("uniqueId", uniqueId).append("permission", permission) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val uniqueId = this.jsonLib.getObject("uniqueId", UUID::class.java) ?: return contentException("uniqueId") + val permission = this.jsonLib.getString("permission") ?: return contentException("permission") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + cloudPlayer ?: return failure(NoSuchPlayerException("Player cannot be found")) + return cloudPlayer.hasPermission(permission) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSaveOfflinePlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSaveOfflinePlayer.kt new file mode 100644 index 000000000..ea4fe33a2 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSaveOfflinePlayer.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.player.OfflineCloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 16.06.2020 + * Time: 09:17 + * @author Frederick Baier + */ +class PacketIOSaveOfflinePlayer() : ObjectPacket() { + + constructor(offlinePlayer: OfflineCloudPlayer) : this() { + this.value = offlinePlayer + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + return value.update() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendMessageToCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendMessageToCloudPlayer.kt new file mode 100644 index 000000000..308a07a8a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendMessageToCloudPlayer.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer +import java.util.* + +class PacketIOSendMessageToCloudPlayer() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, component: Component) : this() { + val value = GsonComponentSerializer.gson().serialize(component) + this.jsonLib + .append("playerUniqueId", cloudPlayer.getUniqueId()) + .append("component", value) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val componentString = + this.jsonLib.getString("component") ?: return contentException("component") + + val component = GsonComponentSerializer.gson().deserialize(componentString) + + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId)?.sendMessage(component) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendPlayerToLobby.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendPlayerToLobby.kt new file mode 100644 index 000000000..fa4298e95 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendPlayerToLobby.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOSendPlayerToLobby() : ObjectPacket() { + + constructor(uniqueId: UUID) : this() { + this.value = uniqueId + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(value) + cloudPlayer ?: return failure(NoSuchPlayerException("Player cannot be found")) + return cloudPlayer.sendToLobby() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTablistToPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTablistToPlayer.kt new file mode 100644 index 000000000..7a9e93368 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTablistToPlayer.kt @@ -0,0 +1,57 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * Created by IntelliJ IDEA. + * Date: 20.11.2020 + * Time: 18:50 + * @author Frederick Baier + */ +class PacketIOSendTablistToPlayer() : JsonPacket() { + + constructor(uniqueId: UUID, headers: Array, footers: Array) : this() { + this.jsonLib.append("uniqueId", uniqueId) + .append("headers", headers) + .append("footers", footers) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val uniqueId = this.jsonLib.getObject("uniqueId", UUID::class.java) ?: return contentException("uniqueId") + val headers = this.jsonLib.getObject("headers", Array::class.java) ?: return contentException("headers") + val footers = this.jsonLib.getObject("footers", Array::class.java) ?: return contentException("footers") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + cloudPlayer ?: return failure(NoSuchPlayerException("Player cannot be found")) + cloudPlayer.sendTablist(headers, footers) + return unit() + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTitleToCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTitleToCloudPlayer.kt new file mode 100644 index 000000000..1214414ab --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSendTitleToCloudPlayer.kt @@ -0,0 +1,62 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOSendTitleToCloudPlayer() : JsonPacket() { + + constructor( + cloudPlayer: ICloudPlayer, + title: String, + subTitle: String, + fadeIn: Int, + stay: Int, + fadeOut: Int + ) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()) + .append("title", title) + .append("subTitle", subTitle) + .append("fadeIn", fadeIn) + .append("stay", stay) + .append("fadeOut", fadeOut) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val title = this.jsonLib.getString("title") ?: return contentException("title") + val subTitle = this.jsonLib.getString("subTitle") ?: return contentException("subTitle") + val fadeIn = this.jsonLib.getInt("fadeIn") ?: return contentException("fadeIn") + val stay = this.jsonLib.getInt("stay") ?: return contentException("stay") + val fadeOut = this.jsonLib.getInt("fadeOut") ?: return contentException("fadeOut") + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) + ?.sendTitle(title, subTitle, fadeIn, stay, fadeOut) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSetCloudPlayerUpdates.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSetCloudPlayerUpdates.kt new file mode 100644 index 000000000..d18001ed4 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOSetCloudPlayerUpdates.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOSetCloudPlayerUpdates() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, updates: Boolean, serviceName: String) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()) + .append("updates", updates).append("serviceName", serviceName) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val updates = this.jsonLib.getBoolean("updates") ?: return contentException("updates") + val serviceName = this.jsonLib.getString("serviceName") ?: return contentException("serviceName") + val cachedCloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) + cachedCloudPlayer?.let { + CloudAPI.instance.getCloudPlayerManager().setUpdates(cachedCloudPlayer, updates, serviceName) + } + return unit() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOTeleportPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOTeleportPlayer.kt new file mode 100644 index 000000000..c9f99f8bd --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/player/PacketIOTeleportPlayer.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.location.SimpleLocation +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketIOTeleportPlayer() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, simpleLocation: SimpleLocation) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()) + .append("simpleLocation", simpleLocation) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val simpleLocation = this.jsonLib.getObject("simpleLocation", SimpleLocation::class.java) + ?: return contentException("simpleLocation") + val cachedCloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) + cachedCloudPlayer ?: return failure(NoSuchElementException("Player does not exist")) + cachedCloudPlayer.teleport(simpleLocation) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/screen/PacketIOExecuteCommand.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/screen/PacketIOExecuteCommand.kt new file mode 100644 index 000000000..4e623289b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/screen/PacketIOExecuteCommand.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.screen + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.network.component.ManagerComponent +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOExecuteCommand() : JsonPacket() { + + constructor(cloudClientType: NetworkComponentType, serviceName: String, command: String) : this() { + this.jsonLib.append("cloudClientType", cloudClientType).append("serviceName", serviceName) + .append("command", command) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val cloudClientType = this.jsonLib.getObject("cloudClientType", NetworkComponentType::class.java) + ?: return contentException("cloudClientType") + val serviceName = this.jsonLib.getString("serviceName") ?: return contentException("serviceName") + val command = this.jsonLib.getString("command") ?: return contentException("command") + val commandExecutable: ICommandExecutable? = when (cloudClientType) { + NetworkComponentType.WRAPPER -> { + CloudAPI.instance.getWrapperManager().getWrapperByName(serviceName) + } + NetworkComponentType.SERVICE -> { + CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) + } + NetworkComponentType.MANAGER -> { + ManagerComponent + } + } + commandExecutable?.executeCommand(command) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOCopyService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOCopyService.kt new file mode 100644 index 000000000..50e0d2e09 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOCopyService.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchServiceException +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 09.06.2020 + * Time: 14:21 + * @author Frederick Baier + */ +class PacketIOCopyService() : JsonPacket() { + + constructor(service: ICloudService, path: String) : this() { + this.jsonLib.append("service", service.getName()).append("path", path) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val serviceName = this.jsonLib.getString("service") ?: return contentException("service") + val path = this.jsonLib.getString("path") ?: return contentException("path") + val service = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) + service ?: return failure(NoSuchServiceException("Service is not registered")) + return service.copy(path) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStartCloudService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStartCloudService.kt new file mode 100644 index 000000000..e81caf7d0 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStartCloudService.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOStartCloudService() : ObjectPacket() { + + constructor(configuration: IServiceStartConfiguration) : this() { + this.value = configuration + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val registeredPromise = CloudAPI.instance.getCloudServiceGroupManager().startNewService(value) + return registeredPromise.then { it.getName() } + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStopCloudService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStopCloudService.kt new file mode 100644 index 000000000..a9277083c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOStopCloudService.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOStopCloudService() : ObjectPacket() { + + constructor(name: String) : this() { + this.value = name + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val name = this.value ?: return contentException("value") + val cloudService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) ?: return failure( + NoSuchElementException("Serve") + ) + cloudService.shutdown() + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOWrapperStartService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOWrapperStartService.kt new file mode 100644 index 000000000..d1fd92b86 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/service/PacketIOWrapperStartService.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOWrapperStartService() : ObjectPacket() { + + constructor(name: String) : this() { + this.value = name + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val name = this.value ?: return contentException("value") + val cloudService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) + cloudService ?: throw IllegalStateException("Service to start was null. Name: $name") + cloudService.start() + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCloudServiceGroupData.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCloudServiceGroupData.kt new file mode 100644 index 000000000..c9690caed --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCloudServiceGroupData.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.servicegroup + +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultLobbyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultProxyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultServerGroup +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +abstract class PacketIOCloudServiceGroupData() : JsonPacket() { + + constructor(cloudServiceGroup: ICloudServiceGroup) : this() { + this.jsonLib.append("serviceType", cloudServiceGroup.getServiceType()).append("group", cloudServiceGroup) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val serviceType = + this.jsonLib.getObject("serviceType", ServiceType::class.java) ?: return contentException("serviceType") + val serviceGroupClass = when (serviceType) { + ServiceType.LOBBY -> DefaultLobbyGroup::class.java + ServiceType.SERVER -> DefaultServerGroup::class.java + ServiceType.PROXY -> DefaultProxyGroup::class.java + } + val serviceGroup = this.jsonLib.getObject("group", serviceGroupClass) ?: return contentException("group") + return handleData(serviceGroup) + } + + abstract fun handleData(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCreateServiceGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCreateServiceGroup.kt new file mode 100644 index 000000000..4f7b941ad --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/servicegroup/PacketIOCreateServiceGroup.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.servicegroup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOCreateServiceGroup : PacketIOCloudServiceGroupData { + + constructor(cloudServiceGroup: ICloudServiceGroup) : super(cloudServiceGroup) + constructor() : super() + + override fun handleData(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise { + return CloudAPI.instance.getCloudServiceGroupManager().createServiceGroup(cloudServiceGroup) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/serviceversion/PacketIOServiceVersions.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/serviceversion/PacketIOServiceVersions.kt new file mode 100644 index 000000000..dc7b0ecff --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/serviceversion/PacketIOServiceVersions.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.serviceversion + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.service.version.ServiceVersionHandler +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 11:15 + * @author Frederick Baier + */ +class PacketIOServiceVersions() : ObjectPacket>() { + + constructor(list: List) : this() { + this.value = list.toTypedArray() + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val serviceVersionHandler = CloudAPI.instance.getServiceVersionHandler() as ServiceVersionHandler + serviceVersionHandler.versions = value.asList() + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/cachelist/PacketIOUpdateCacheObject.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/cachelist/PacketIOUpdateCacheObject.kt new file mode 100644 index 000000000..d542bdca0 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/cachelist/PacketIOUpdateCacheObject.kt @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.cachelist + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOUpdateCacheObject() : JsonPacket() { + + constructor(cacheListName: String, value: Any, action: Action) : this() { + this.jsonLib.append("cacheListName", cacheListName) + .append("value", value) + .append("valueClass", value::class.java.name) + .append("action", action) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val cacheListName = this.jsonLib.getString("cacheListName") + ?: return contentException("cacheListName") + val valueClassName = this.jsonLib.getString("valueClass") + ?: return contentException("valueClass") + val action = this.jsonLib.getObject("action", Action::class.java) + ?: return contentException("action") + val valueClass = Class.forName( + valueClassName, + true, + connection.getCommunicationBootstrap().getClassLoaderToSearchObjectPacketsClasses() + ) + val value = this.jsonLib.getObject("value", valueClass) ?: return contentException("value") + value as ICacheValue + + return when (action) { + Action.UPDATE -> { + CloudAPI.instance.getCacheListManager().getCacheListenerByName(cacheListName) + ?.update(value, true) ?: CommunicationPromise.UNIT_PROMISE + } + Action.DELETE -> { + CloudAPI.instance.getCacheListManager().getCacheListenerByName(cacheListName) + ?.delete(value, true) ?: CommunicationPromise.UNIT_PROMISE + } + } + } + + enum class Action { + UPDATE, DELETE + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOGetAllCachedListProperties.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOGetAllCachedListProperties.kt new file mode 100644 index 000000000..337d6dcfa --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOGetAllCachedListProperties.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.list + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.combineAllPromises + +class PacketIOGetAllCachedListProperties() : ObjectPacket() { + + constructor(name: String) : this() { + this.value = name + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val synchronizedObjectList = + CloudAPI.instance.getSynchronizedObjectListManager().getSynchronizedObjectList(value) + synchronizedObjectList + ?: return failure(NoSuchElementException("No list object found by the specified name: $value")) + val allPromises = synchronizedObjectList.getAllCachedObjects() + .map { connection.sendUnitQuery(PacketIOUpdateListProperty(value, it)) } + return allPromises.combineAllPromises() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIORemoveListProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIORemoveListProperty.kt new file mode 100644 index 000000000..e8fe337f8 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIORemoveListProperty.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.list + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.sync.list.ISynchronizedObjectList +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIORemoveListProperty() : JsonPacket() { + + constructor(listName: String, property: IProperty<*>) : this() { + this.jsonLib.append("listName", listName).append("property", property) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val listName = this.jsonLib.getString("listName") ?: return contentException("listName") + val property = this.jsonLib.getObject("property", Property::class.java) ?: return contentException("property") + property as IProperty + try { + val synchronizedObjectList: ISynchronizedObjectList? = + CloudAPI.instance.getSynchronizedObjectListManager().getSynchronizedObjectList(listName) + synchronizedObjectList ?: return failure(NoSuchElementException()) + synchronizedObjectList.remove(property, true) + + } catch (ex: Exception) { + throw ex + } + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOUpdateListProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOUpdateListProperty.kt new file mode 100644 index 000000000..6dd534c58 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/list/PacketIOUpdateListProperty.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.list + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.sync.list.ISynchronizedObjectList +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOUpdateListProperty() : JsonPacket() { + + constructor(listName: String, property: IProperty<*>) : this() { + this.jsonLib.append("listName", listName).append("property", property) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val listName = this.jsonLib.getString("listName") ?: return contentException("listName") + val property = this.jsonLib.getObject("property", Property::class.java) as Property? + ?: return contentException("property") + try { + val synchronizedObjectList: ISynchronizedObjectList? = + CloudAPI.instance.getSynchronizedObjectListManager().getSynchronizedObjectList(listName) + synchronizedObjectList ?: return failure(NoSuchElementException()) + synchronizedObjectList.update(property, true) + + } catch (ex: Exception) { + throw ex + } + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOGetGlobalProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOGetGlobalProperty.kt new file mode 100644 index 000000000..7fc22ff62 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOGetGlobalProperty.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.`object` + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.sync.`object`.GlobalPropertyHolder +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 21.06.2020 + * Time: 09:41 + * @author Frederick Baier + */ +class PacketIOGetGlobalProperty() : ObjectPacket() { + + constructor(name: String) : this() { + this.value = name + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val globalPropertyHolder = CloudAPI.instance.getGlobalPropertyHolder() + as GlobalPropertyHolder + val property = globalPropertyHolder.getProperty(value) + property?.let { + globalPropertyHolder.addConnectionToUpdates(value, connection) + } + return CommunicationPromise.ofNullable(property, NoSuchElementException()) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIORemoveGlobalProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIORemoveGlobalProperty.kt new file mode 100644 index 000000000..8eb665d7a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIORemoveGlobalProperty.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.`object` + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.sync.`object`.GlobalPropertyHolder +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIORemoveGlobalProperty() : JsonPacket() { + + constructor(name: String) : this() { + this.jsonLib.append("name", name) + + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val name = this.jsonLib.getString("name") ?: return contentException("name") + (CloudAPI.instance.getGlobalPropertyHolder() as GlobalPropertyHolder).removePropertyFromPacket(name) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOUpdateGlobalProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOUpdateGlobalProperty.kt new file mode 100644 index 000000000..0497b512d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/network/packets/sync/object/PacketIOUpdateGlobalProperty.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.network.packets.sync.`object` + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.sync.`object`.GlobalPropertyHolder +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketIOUpdateGlobalProperty() : JsonPacket() { + + constructor(name: String, property: IProperty<*>) : this() { + this.jsonLib.append("property", property) + .append("name", name) + + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val name = this.jsonLib.getString("name") ?: return contentException("name") + val property = this.jsonLib.getObject("property", Property::class.java) + ?: return contentException("property") + (CloudAPI.instance.getGlobalPropertyHolder() as GlobalPropertyHolder).updatePropertyFromPacket(name, property) + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeFromClassParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeFromClassParser.kt new file mode 100644 index 000000000..477b58d4d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeFromClassParser.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser + +interface ITypeFromClassParser { + + /** + * Returns a set of types this parser supports. + */ + fun supportedTypes(): Set> + + /** + * Parses the specified [value] to the specified [clazz] + * Returns null if the value could not be parsed + */ + fun parseToObject(value: T, clazz: Class): R? + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeParser.kt new file mode 100644 index 000000000..93170da45 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/ITypeParser.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser + +/** + * Parses a object from one type to another + */ +interface ITypeParser { + + /** + * Parses the object [T] to [R] + * @return null if the parse failed + */ + fun parse(value: T): R? + + /** + * Returns a list of types this parser can parse + */ + fun allowedTypes(): List> + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/IJsonDataTypeParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/IJsonDataTypeParser.kt new file mode 100644 index 000000000..eb081ea3c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/IJsonDataTypeParser.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.jsondata + +import eu.thesimplecloud.api.parser.ITypeParser +import eu.thesimplecloud.jsonlib.JsonLib + +interface IJsonDataTypeParser : ITypeParser { +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/JsonDataParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/JsonDataParser.kt new file mode 100644 index 000000000..3b13d140b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/jsondata/JsonDataParser.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.jsondata + +import eu.thesimplecloud.api.parser.ITypeFromClassParser +import eu.thesimplecloud.jsonlib.JsonLib + +class JsonDataParser : ITypeFromClassParser { + + override fun supportedTypes(): Set> = emptySet() + + override fun parseToObject(value: JsonLib, clazz: Class): R? = null +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/IStringTypeParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/IStringTypeParser.kt new file mode 100644 index 000000000..c16745a2b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/IStringTypeParser.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string + +import eu.thesimplecloud.api.parser.ITypeParser + + +interface IStringTypeParser : ITypeParser \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/StringParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/StringParser.kt new file mode 100644 index 000000000..526e90fa6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/StringParser.kt @@ -0,0 +1,71 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string + +import eu.thesimplecloud.api.parser.ITypeFromClassParser +import eu.thesimplecloud.api.parser.string.typeparser.* +import eu.thesimplecloud.api.utils.enumValueOf +import eu.thesimplecloud.api.utils.getEnumValues +import eu.thesimplecloud.jsonlib.JsonLib +import java.util.* + +class StringParser : ITypeFromClassParser { + + private val parsableTypes = listOf(String::class.java, Int::class.java, UUID::class.java) + + private val customTypeParsers = mutableListOf( + CloudLobbyGroupParser(), + CloudProxyGroupParser(), + CloudServerGroupParser(), + CloudServiceGroupParser(), + CloudServiceParser(), + WrapperInfoParser(), + BooleanParser(), + TemplateParser(), + IntParser(), + DoubleParser(), + FloatParser() + ) + + override fun supportedTypes(): Set> = + customTypeParsers.map { it.allowedTypes() }.flatten().union(parsableTypes) + + override fun parseToObject(string: String, clazz: Class): R? { + if (clazz.isEnum) { + clazz as Class> + val enumValues = clazz.getEnumValues() + val indexOf = enumValues.map { it.toLowerCase() }.indexOf(string.toLowerCase()) + if (indexOf == -1) + return null + return clazz.enumValueOf(enumValues[indexOf]) as R + } + if (parsableTypes.contains(clazz)) { + return JsonLib.fromObject(string).getObjectOrNull(clazz) + } + val parser = customTypeParsers.firstOrNull { it.allowedTypes().contains(clazz) } + parser ?: throw IllegalArgumentException("Can't parse class to ${clazz.simpleName}: No parser found.") + parser as IStringTypeParser + return parser.parse(string) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/BooleanParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/BooleanParser.kt new file mode 100644 index 000000000..3a076fda4 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/BooleanParser.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.parser.string.IStringTypeParser + +class BooleanParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(Boolean::class.java) + + override fun parse(string: String): Boolean? { + when (string.toLowerCase()) { + "yes" -> return true + "no" -> return false + "true" -> return true + "false" -> return false + } + return null + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudLobbyGroupParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudLobbyGroupParser.kt new file mode 100644 index 000000000..a06cad078 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudLobbyGroupParser.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudLobbyGroup + +class CloudLobbyGroupParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(ICloudLobbyGroup::class.java) + + override fun parse(string: String): ICloudLobbyGroup? = + CloudAPI.instance.getCloudServiceGroupManager().getLobbyGroupByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudProxyGroupParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudProxyGroupParser.kt new file mode 100644 index 000000000..7b7b4ad85 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudProxyGroupParser.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudProxyGroup + +class CloudProxyGroupParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(ICloudProxyGroup::class.java) + + override fun parse(string: String): ICloudProxyGroup? = + CloudAPI.instance.getCloudServiceGroupManager().getProxyGroupByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServerGroupParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServerGroupParser.kt new file mode 100644 index 000000000..cd74ba77e --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServerGroupParser.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup + +class CloudServerGroupParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(ICloudServerGroup::class.java) + + override fun parse(string: String): ICloudServerGroup? = + CloudAPI.instance.getCloudServiceGroupManager().getServerGroupByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceGroupParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceGroupParser.kt new file mode 100644 index 000000000..66d107c84 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceGroupParser.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +class CloudServiceGroupParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(ICloudServiceGroup::class.java) + + override fun parse(string: String): ICloudServiceGroup? = + CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceParser.kt new file mode 100644 index 000000000..b7ff93df9 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/CloudServiceParser.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.service.ICloudService + +class CloudServiceParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(ICloudService::class.java) + + override fun parse(string: String): ICloudService? = + CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/DoubleParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/DoubleParser.kt new file mode 100644 index 000000000..599d320f5 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/DoubleParser.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.parser.string.IStringTypeParser + +/** + * Created by IntelliJ IDEA. + * Date: 07.06.2020 + * Time: 14:45 + * @author Frederick Baier + */ +class DoubleParser : IStringTypeParser { + override fun parse(value: String): Double? { + return runCatching { value.toDouble() }.getOrNull() + } + + override fun allowedTypes(): List> { + return listOf(Double::class.java) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/FloatParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/FloatParser.kt new file mode 100644 index 000000000..d8dd30f9d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/FloatParser.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.parser.string.IStringTypeParser + +/** + * Created by IntelliJ IDEA. + * Date: 07.06.2020 + * Time: 14:45 + * @author Frederick Baier + */ +class FloatParser : IStringTypeParser { + override fun parse(value: String): Float? { + return runCatching { value.toFloat() }.getOrNull() + } + + override fun allowedTypes(): List> { + return listOf(Float::class.java) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/IntParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/IntParser.kt new file mode 100644 index 000000000..425572035 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/IntParser.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.parser.string.IStringTypeParser + +/** + * Created by IntelliJ IDEA. + * Date: 07.06.2020 + * Time: 14:45 + * @author Frederick Baier + */ +class IntParser : IStringTypeParser { + override fun parse(value: String): Int? { + return runCatching { value.toInt() }.getOrNull() + } + + override fun allowedTypes(): List> { + return listOf(Int::class.java) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/TemplateParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/TemplateParser.kt new file mode 100644 index 000000000..d37d7cc3d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/TemplateParser.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.template.ITemplate + +class TemplateParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(ITemplate::class.java) + + override fun parse(string: String): ITemplate? = CloudAPI.instance.getTemplateManager().getTemplateByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/WrapperInfoParser.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/WrapperInfoParser.kt new file mode 100644 index 000000000..4ffd525cc --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/parser/string/typeparser/WrapperInfoParser.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.parser.string.typeparser + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.parser.string.IStringTypeParser +import eu.thesimplecloud.api.wrapper.IWrapperInfo + +class WrapperInfoParser : IStringTypeParser { + + override fun allowedTypes(): List> = listOf(IWrapperInfo::class.java) + + override fun parse(string: String): IWrapperInfo? = CloudAPI.instance.getWrapperManager().getWrapperByName(string) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/AbstractCloudPlayerManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/AbstractCloudPlayerManager.kt new file mode 100644 index 000000000..13dbe4947 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/AbstractCloudPlayerManager.kt @@ -0,0 +1,94 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.AbstractCacheList +import eu.thesimplecloud.api.cachelist.ICacheObjectUpdateExecutor +import eu.thesimplecloud.api.event.player.* +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +abstract class AbstractCloudPlayerManager : AbstractCacheList(spreadUpdates = false), + ICloudPlayerManager { + + private val updater = object : ICacheObjectUpdateExecutor { + override fun getIdentificationName(): String { + return "player-cache" + } + + override fun getCachedObjectByUpdateValue(value: ICloudPlayer): ICloudPlayer? { + return getCachedCloudPlayer(value.getName()) + } + + override fun determineEventsToCall(updater: ICloudPlayerUpdater, cachedValue: ICloudPlayer?): List { + val events = ArrayList() + val playerToUse = cachedValue ?: updater.getCloudPlayer() + events.add(CloudPlayerUpdatedEvent(playerToUse)) + if (cachedValue == null) { + events.add(CloudPlayerRegisteredEvent(playerToUse)) + return events + } + val connectedServer = updater.getConnectedServer() + connectedServer?.let { + if (updater.getConnectedServerName() != cachedValue.getConnectedServerName()) { + val oldServer = cachedValue.getConnectedServer() + events.add(CloudPlayerServerConnectEvent(playerToUse, oldServer, connectedServer)) + } + if (cachedValue.getServerConnectState() == PlayerServerConnectState.CONNECTING && updater.getServerConnectState() == PlayerServerConnectState.CONNECTED) { + events.add(CloudPlayerServerConnectedEvent(playerToUse, connectedServer)) + } + } + + return events + } + + override fun addNewValue(value: ICloudPlayer) { + values.add(value) + } + + } + + override fun getUpdateExecutor(): ICacheObjectUpdateExecutor { + return this.updater + } + + override fun delete(value: ICloudPlayer, fromPacket: Boolean): ICommunicationPromise { + val playerToUse = updater.getCachedObjectByUpdateValue(value) ?: value + return super.delete(value, fromPacket).addResultListener { + CloudAPI.instance.getEventManager().call(CloudPlayerUnregisteredEvent(playerToUse)) + } + } + + /** + * Creates a [ICommunicationPromise] with the [cloudPlayer] + * If the [cloudPlayer] is not null it will returns a promise completed with the player. + * If the [cloudPlayer] is null it will return a promise failed with [NoSuchElementException] + */ + fun promiseOfNullablePlayer(cloudPlayer: ICloudPlayer?): ICommunicationPromise { + return CommunicationPromise.ofNullable(cloudPlayer, NoSuchElementException("CloudPlayer not found.")) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/ICloudPlayerUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/ICloudPlayerUpdater.kt new file mode 100644 index 000000000..104fa384f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/ICloudPlayerUpdater.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import eu.thesimplecloud.api.service.ICloudService + +interface ICloudPlayerUpdater : ICacheValueUpdater { + + fun getCloudPlayer(): ICloudPlayer + + fun setDisplayName(name: String) + + fun getDisplayName(): String + + fun getServerConnectState(): PlayerServerConnectState + + fun getConnectedServerName(): String? + + fun getConnectedProxyName(): String + + fun getConnectedServer(): ICloudService? { + return getConnectedServerName()?.let { CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(it) } + } + + fun getConnectedProxy(): ICloudService? { + return CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(getConnectedProxyName()) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/IOfflineCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/IOfflineCloudPlayer.kt new file mode 100644 index 000000000..5f7eeb0f5 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/IOfflineCloudPlayer.kt @@ -0,0 +1,86 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.connection.IPlayerConnection +import eu.thesimplecloud.api.property.IPropertyMap +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +interface IOfflineCloudPlayer : Nameable, IPropertyMap { + + /** + * Returns the unique id of this player. + */ + fun getUniqueId(): UUID + + /** + * Returns the timestamp of the last login. + */ + fun getLastLogin(): Long + + /** + * Returns the timestamp of the first login. + */ + fun getFirstLogin(): Long + + /** + * Returns the online time of this player in milliseconds + */ + fun getOnlineTime(): Long + + /** + * Returns the las connection of this player. + */ + fun getLastPlayerConnection(): IPlayerConnection + + /** + * Returns whether this player is connected to the network. + */ + fun isOnline(): Boolean = false + + /** + * Sets the displayname of this player + * @param displayName the displayname of this player + */ + fun setDisplayName(displayName: String) + + /** + * Returns the displayname of this player + */ + fun getDisplayName(): String + + /** + * Returns a new [IOfflineCloudPlayer] with the data of this player + */ + fun toOfflinePlayer(): IOfflineCloudPlayer + + /** + * Updates this player to the network + * @return a promise that completes when the player was updated + */ + fun update(): ICommunicationPromise = CloudAPI.instance.getCloudPlayerManager().savePlayerToDatabase(this) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/OfflineCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/OfflineCloudPlayer.kt new file mode 100644 index 000000000..b27cd97bf --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/OfflineCloudPlayer.kt @@ -0,0 +1,94 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.api.player.connection.IPlayerConnection +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import java.util.* +import java.util.concurrent.ConcurrentMap + +open class OfflineCloudPlayer( + name: String, + uniqueId: UUID, + private val firstLogin: Long, + private val lastLogin: Long, + private val onlineTime: Long, + protected val lastPlayerConnection: DefaultPlayerConnection, + @Volatile var propertyMap: ConcurrentMap> = Maps.newConcurrentMap() +) : SimpleCloudPlayer(name, uniqueId), IOfflineCloudPlayer { + + @Volatile + private var displayName = name + + override fun getProperties(): Map> { + return this.propertyMap + } + + override fun getLastLogin(): Long = this.lastLogin + + override fun getFirstLogin(): Long = this.firstLogin + + override fun getOnlineTime(): Long = this.onlineTime + + override fun getLastPlayerConnection(): IPlayerConnection = this.lastPlayerConnection + + override fun setDisplayName(displayName: String) { + this.displayName = displayName + } + + override fun getDisplayName(): String { + return this.displayName + } + + override fun toOfflinePlayer(): IOfflineCloudPlayer { + return OfflineCloudPlayer( + getName(), + getUniqueId(), + getFirstLogin(), + getLastLogin(), + getOnlineTime(), + this.lastPlayerConnection, + this.propertyMap + ) + } + + override fun setProperty(name: String, value: T): IProperty { + require(value !is Property<*>) { "Cannot set ${value::class.java.name} as property" } + val property = Property(value) + this.propertyMap[name] = property + return property + } + + override fun clearProperties() { + this.propertyMap.clear() + } + + override fun removeProperty(name: String) { + this.propertyMap.remove(name) + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerMessageQueue.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerMessageQueue.kt new file mode 100644 index 000000000..fd50cb922 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerMessageQueue.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import net.kyori.adventure.text.Component +import java.util.concurrent.ConcurrentLinkedQueue + +class PlayerMessageQueue(private val player: ICloudPlayer) { + + private val queue = ConcurrentLinkedQueue() + + @Volatile + private var lastMessagePromise: ICommunicationPromise = CommunicationPromise.of(Unit) + + @Synchronized + fun queueMessage(component: Component): ICommunicationPromise { + val promise = CommunicationPromise(500) + this.queue.add(QueuedComponent(component, promise)) + if (this.lastMessagePromise.isDone) { + sendNextMessage() + } + return promise + } + + private fun sendNextMessage() { + val queuedText = queue.poll() + queuedText?.let { + val promise = CloudAPI.instance.getCloudPlayerManager().sendMessageToPlayer(player, queuedText.component) + this.lastMessagePromise = promise + promise.addCompleteListener { sendNextMessage() } + promise.addCompleteListener { queuedText.promise.trySuccess(Unit) } + } + } + + + private class QueuedComponent(val component: Component, val promise: ICommunicationPromise) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerServerConnectState.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerServerConnectState.kt new file mode 100644 index 000000000..c31af7e4b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/PlayerServerConnectState.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + +enum class PlayerServerConnectState { + + /** + * The player is currently connecting to a server + */ + CONNECTING, + + /** + * The player is fully connected to the server. + */ + CONNECTED + +} diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/SimpleCloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/SimpleCloudPlayer.kt new file mode 100644 index 000000000..bdd88986a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/SimpleCloudPlayer.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +open class SimpleCloudPlayer( + private val name: String, + private val uniqueId: UUID +) : Nameable { + + override fun getName(): String { + return name + } + + /** + * Returns the uniqueId of this player. + */ + fun getUniqueId(): UUID { + return uniqueId + } + + /** + * Returns a promise of the cloud player of this player. + */ + fun getCloudPlayer(): ICommunicationPromise { + return CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(uniqueId) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/ConnectionResponse.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/ConnectionResponse.kt new file mode 100644 index 000000000..60a8f3274 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/ConnectionResponse.kt @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.connection + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.player.CloudPlayerServerConnectedEvent +import eu.thesimplecloud.api.listenerextension.cloudListener +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.player.PlayerServerConnectState +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class ConnectionResponse(val playerUniqueId: UUID, val alreadyConnected: Boolean) { + + fun getCloudPlayer(): ICloudPlayer { + return CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) + ?: throw IllegalStateException("Unable to find player by uuid $playerUniqueId") + } + + fun createConnectedPromise(): ICommunicationPromise { + val cloudPlayer = this.getCloudPlayer() + if (alreadyConnected || cloudPlayer.getServerConnectState() == PlayerServerConnectState.CONNECTED) + return CommunicationPromise.of( + CloudPlayerServerConnectedEvent( + cloudPlayer, + cloudPlayer.getConnectedServer()!! + ) + ) + return cloudListener() + .addCondition { it.cloudPlayer === cloudPlayer } + .toPromise() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerAddress.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerAddress.kt new file mode 100644 index 000000000..b6fba766a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerAddress.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.connection + +class DefaultPlayerAddress( + private val hostname: String, + private val port: Int +) : IPlayerAddress { + + override fun getHostname(): String = this.hostname + + override fun getPort(): Int = this.port +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerConnection.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerConnection.kt new file mode 100644 index 000000000..883551329 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/DefaultPlayerConnection.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.connection + +import java.util.* + +data class DefaultPlayerConnection( + private val address: DefaultPlayerAddress, + private val name: String, + private val uniqueId: UUID, + private val onlineMode: Boolean, + private val version: Int +) : IPlayerConnection { + + override fun getAddress(): IPlayerAddress = this.address + + override fun getUniqueId(): UUID = this.uniqueId + + override fun getName(): String = this.name + + override fun isOnlineMode(): Boolean = this.onlineMode + + override fun getVersion(): Int = this.version +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerAddress.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerAddress.kt new file mode 100644 index 000000000..f0fb064cb --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerAddress.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.connection + +interface IPlayerAddress { + + /** + * Returns the ip address of the player + */ + fun getHostname(): String + + /** + * Returns the port of the player + */ + fun getPort(): Int + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerConnection.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerConnection.kt new file mode 100644 index 000000000..9ddc7b9ba --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/connection/IPlayerConnection.kt @@ -0,0 +1,62 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.connection + +import eu.thesimplecloud.api.CloudAPI +import java.util.* + +interface IPlayerConnection { + + /** + * Returns the address of this player. + */ + fun getAddress(): IPlayerAddress + + /** + * Returns the unique id of this player + */ + fun getUniqueId(): UUID + + /** + * Returns the username of this player + */ + fun getName(): String + + /** + * Returns whether the player's connection is in online mode. + */ + fun isOnlineMode(): Boolean + + /** + * Get the numerical client version of the player attempting to log in. + * + * @return the protocol version of the client + */ + fun getVersion(): Int + + /** + * Returns the cloud player this player connection is linked to + */ + fun getCloudPlayer() = CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(getUniqueId()) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayer.kt new file mode 100644 index 000000000..4c68ed52b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayer.kt @@ -0,0 +1,146 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.impl + +import eu.thesimplecloud.api.player.* +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.api.player.connection.IPlayerConnection +import eu.thesimplecloud.api.player.text.CloudText +import eu.thesimplecloud.api.player.text.CloudTextBuilder +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude +import net.kyori.adventure.text.Component +import java.util.* +import java.util.concurrent.ConcurrentMap + +class CloudPlayer( + name: String, + uniqueId: UUID, + firstLogin: Long, + lastLogin: Long, + onlineTime: Long, + @Volatile private var connectedProxyName: String, + @Volatile private var connectedServerName: String?, + playerConnection: DefaultPlayerConnection, + propertyMap: ConcurrentMap> +) : OfflineCloudPlayer( + name, + uniqueId, + firstLogin, + lastLogin, + onlineTime, + playerConnection, + propertyMap +), ICloudPlayer { + + @Volatile + @JsonLibExclude + @PacketExclude + private var playerUpdater: CloudPlayerUpdater? = CloudPlayerUpdater(this) + + @Volatile + private var connectState: PlayerServerConnectState = PlayerServerConnectState.CONNECTING + + @Volatile + private var online = true + + @PacketExclude + @Volatile + private var updatesEnabled = false + + @PacketExclude + @JsonLibExclude + private var playerMessageQueue: PlayerMessageQueue? = null + + override fun getPlayerConnection(): IPlayerConnection = this.lastPlayerConnection + + override fun getServerConnectState(): PlayerServerConnectState { + return this.connectState + } + + @Synchronized + override fun sendMessage(cloudText: CloudText): ICommunicationPromise { + return sendMessage(CloudTextBuilder().build(cloudText)) + } + + @Synchronized + override fun sendMessage(component: Component): ICommunicationPromise { + if (playerMessageQueue == null) playerMessageQueue = PlayerMessageQueue(this) + return this.playerMessageQueue!!.queueMessage(component) + } + + override fun getConnectedProxyName(): String = this.connectedProxyName + + override fun getConnectedServerName(): String? = this.connectedServerName + + override fun isOnline(): Boolean = this.online + + override fun enableUpdates() { + super.enableUpdates() + this.updatesEnabled = true + } + + override fun disableUpdates() { + super.disableUpdates() + this.updatesEnabled = false + } + + override fun isUpdatesEnabled(): Boolean { + return this.updatesEnabled + } + + override fun getUpdater(): ICloudPlayerUpdater { + if (this.playerUpdater == null) { + this.playerUpdater = CloudPlayerUpdater(this) + } + return this.playerUpdater!! + } + + override fun applyValuesFromUpdater(updater: ICloudPlayerUpdater) { + super.setDisplayName(updater.getDisplayName()) + updater as CloudPlayerUpdater + this.connectedServerName = updater.getConnectedServerName() + this.connectedProxyName = updater.getConnectedProxyName() + this.connectState = updater.getServerConnectState() + this.propertyMap = + getMapWithNewestProperties(updater.getCloudPlayer().getProperties()) as ConcurrentMap> + } + + @Synchronized + fun setOffline() { + this.online = false + } + + + override fun getOnlineTime(): Long { + return (System.currentTimeMillis() - getLastLogin()) + super.getOnlineTime() + } + + override fun toString(): String { + return JsonLib.fromObject(this).getAsJsonString() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayerUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayerUpdater.kt new file mode 100644 index 000000000..1d5f13b46 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/impl/CloudPlayerUpdater.kt @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.AbstractCacheValueUpdater +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.player.ICloudPlayerUpdater +import eu.thesimplecloud.api.player.PlayerServerConnectState +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class CloudPlayerUpdater( + private val cloudPlayer: ICloudPlayer +) : AbstractCacheValueUpdater(), ICloudPlayerUpdater { + + override fun getCloudPlayer(): ICloudPlayer { + return cloudPlayer + } + + override fun setDisplayName(name: String) { + changes["displayName"] = name + } + + override fun getDisplayName(): String { + return getChangedValue("displayName") ?: cloudPlayer.getDisplayName() + } + + fun setConnectedProxyName(name: String) { + changes["connectedProxy"] = name + } + + override fun getConnectedProxyName(): String { + return getChangedValue("connectedProxy") ?: cloudPlayer.getConnectedProxyName() + } + + fun setConnectedServerName(name: String) { + changes["connectedServer"] = name + } + + override fun getServerConnectState(): PlayerServerConnectState { + return getChangedValue("connectState") ?: cloudPlayer.getServerConnectState() + } + + fun setServerConnectState(state: PlayerServerConnectState) { + changes["connectState"] = state + } + + override fun getConnectedServerName(): String? { + return getChangedValue("connectedServer") ?: cloudPlayer.getConnectedServerName() + } + + override fun update(): ICommunicationPromise { + return CloudAPI.instance.getCloudPlayerManager().update(cloudPlayer) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudText.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudText.kt new file mode 100644 index 000000000..ee0503227 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudText.kt @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.text + +@Deprecated("Use adventure text component instead") +class CloudText(val text: String) { + + + /** + * The text shall be shown when hovering over the [text] + */ + @Volatile + var hover: String? = null + private set + + /** + * The action content to perform when the text is clicked. + */ + @Volatile + var click: String? = null + private set + + /** + * The action that will be performed when the text is clicked. + */ + @Volatile + var clickEventType: ClickEventType? = null + private set + + /** + * The [CloudText] to append to this text. + */ + @Volatile + var appendedCloudText: CloudText? = null + private set + + fun addHover(hover: String): CloudText { + this.hover = hover + return this + } + + fun addClickEvent(clickEventType: ClickEventType, value: String): CloudText { + this.clickEventType = clickEventType + click = value + return this + } + + fun setAppendedCloudText(cloudText: CloudText): CloudText { + this.appendedCloudText = cloudText + return this + } + + enum class ClickEventType { + RUN_COMMAND, SUGGEST_COMMAND, OPEN_URL + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudTextBuilder.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudTextBuilder.kt new file mode 100644 index 000000000..e2ae93c73 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/player/text/CloudTextBuilder.kt @@ -0,0 +1,97 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.player.text + +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.event.ClickEvent +import java.util.function.Consumer + +@Deprecated("Use adventure text component instead") +class CloudTextBuilder { + + private val colorCodes = listOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f') + private val specialCodes = listOf('k', 'l', 'm', 'n', 'o') + + fun build(cloudText: CloudText): Component { + var text: String = cloudText.text.replace("&", "§") + var currentColorCode = Character.MIN_VALUE + val currentSpecialCodes: MutableList = ArrayList() + val stringBuilder = StringBuilder() + var i = 0 + while (i < text.length) { + val c = text[i] + if (c == '§') { + i++ + if (i == text.length) { + i++ + continue + } + val nextCode = text[i] + if (colorCodes.contains(nextCode)) { + currentColorCode = nextCode + currentSpecialCodes.clear() + i++ + continue + } + if (specialCodes.contains(nextCode)) { + currentSpecialCodes.add(nextCode) + i++ + continue + } + if (nextCode == 'r') { + currentSpecialCodes.clear() + } + } else { + stringBuilder.append("§$currentColorCode") + currentSpecialCodes.forEach(Consumer { character: Char -> stringBuilder.append("§$character") }) + stringBuilder.append(c) + } + i++ + } + text = stringBuilder.toString() + val component = Component.text() + component.content(text) + + val hover = cloudText.hover + if (hover != null) { + component.hoverEvent(Component.text(hover)) + } + val click = cloudText.click + if (click != null) { + component.clickEvent( + ClickEvent.clickEvent( + ClickEvent.Action.valueOf(cloudText.clickEventType.toString()), + click + ) + ) + } + + val appendedCloudText = cloudText.appendedCloudText + if (appendedCloudText != null) { + val componentToAppend = build(appendedCloudText) + component.append(componentToAppend) + } + + return component.build() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IProperty.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IProperty.kt new file mode 100644 index 000000000..1e4aac442 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IProperty.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.property + + +interface IProperty { + + /** + * Returns the value of this property + * This is required when this function gets called from a module. + */ + fun getValue(): T + + /** + * Returns the value of this property converted to a json string. + */ + fun getValueAsString(): String +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IPropertyMap.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IPropertyMap.kt new file mode 100644 index 000000000..86719693c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/IPropertyMap.kt @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.property + +import com.google.common.collect.Maps +import java.util.concurrent.ConcurrentMap + +interface IPropertyMap { + + /** + * Returns all properties + */ + fun getProperties(): Map> + + /** + * Returns the property by the specified [name]. + */ + fun getProperty(name: String): IProperty? = getProperties()[name] as IProperty? + + /** + * Sets the specified [value] as property linked to the specified [name]. + * @return the created property + */ + fun setProperty(name: String, value: T): IProperty + + /** + * Clears all set properties + */ + fun clearProperties() + + /** + * Removes the [Property] found by the specified [name]. + */ + fun removeProperty(name: String) + + /** + * Returns whether this player has the specified [property] + */ + fun hasProperty(property: String) = getProperties().keys.contains(property) + + /** + * Returns the newer property according to [Property.lastUpdateTimeStamp] + */ + private fun getNewerProperty(propertyOne: IProperty<*>, propertyTwo: IProperty<*>): IProperty<*> { + propertyOne as Property<*> + propertyTwo as Property<*> + return if (propertyOne.lastUpdateTimeStamp > propertyTwo.lastUpdateTimeStamp) { + propertyOne + } else { + propertyTwo + } + } + + fun getMapWithNewestProperties(compareMap: Map>): ConcurrentMap> { + val ownMap = getProperties() + val allKeys = ownMap.keys.union(compareMap.keys) + val map = Maps.newConcurrentMap>() + for (key in allKeys) { + val valueOne = ownMap[key] as Property<*>? + val valueTwo = compareMap[key] as Property<*>? + //choose 0 as default value because it will be older than the other value and one of these value must be non-null + val valueOneLastUpdate = valueOne?.lastUpdateTimeStamp ?: 0 + val valueTwoLastUpdate = valueTwo?.lastUpdateTimeStamp ?: 0 + map[key] = if (valueOneLastUpdate > valueTwoLastUpdate) valueOne!! else valueTwo!! + } + return map + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/Property.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/Property.kt new file mode 100644 index 000000000..282485c1c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/property/Property.kt @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.property + +import eu.thesimplecloud.api.utils.DatabaseExclude +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude + + +class Property( + value: T +) : IProperty { + + @JsonLibExclude + @PacketExclude + @DatabaseExclude + @Volatile + private var savedValue: T? = value + + private val className: String = value::class.java.name + + @Volatile + private var valueAsString: String = JsonLib.fromObject(value).getAsJsonString() + + @DatabaseExclude + @JsonLibExclude + @Volatile + var lastUpdateTimeStamp = 0L + private set + + init { + setLastUpdateToNow() + } + + @Synchronized + override fun getValue(): T { + if (savedValue == null) { + val clazz = propertyClassFindFunction(className) as Class + savedValue = JsonLib.fromJsonString(valueAsString).getObject(clazz) + } + return savedValue!! + } + + fun resetValue() { + this.savedValue = null + } + + fun setLastUpdateToNow() { + this.lastUpdateTimeStamp = System.currentTimeMillis() + } + + override fun getValueAsString(): String { + return this.valueAsString + } + + fun setStringValue(string: String) { + this.valueAsString = string + } + + companion object { + @Volatile + var propertyClassFindFunction: (String) -> Class<*> = { + Class.forName(it, true, Property::class.java.classLoader) + } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecutable.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecutable.kt new file mode 100644 index 000000000..c8f6d3383 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecutable.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.screen + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClientValue + +interface ICommandExecutable : Nameable, IConnectedClientValue { + + /** + * Executes a command on this [ICommandExecutable] + */ + fun executeCommand(command: String) = CloudAPI.instance.getCommandExecuteManager().executeCommand(this, command) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecuteManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecuteManager.kt new file mode 100644 index 000000000..7ec0f127b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/screen/ICommandExecuteManager.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.screen + +interface ICommandExecuteManager { + + /** + * Executes a command on the specified [ICommandExecutable] + */ + fun executeCommand(commandExecutable: ICommandExecutable, command: String) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudService.kt new file mode 100644 index 000000000..32d9b3ad8 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudService.kt @@ -0,0 +1,261 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.event.service.CloudServiceConnectedEvent +import eu.thesimplecloud.api.event.service.CloudServiceStartedEvent +import eu.thesimplecloud.api.event.service.CloudServiceStartingEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.listenerextension.cloudListener +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.player.SimpleCloudPlayer +import eu.thesimplecloud.api.property.IPropertyMap +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.clientserverapi.lib.bootstrap.IBootstrap +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.flatten +import eu.thesimplecloud.clientserverapi.lib.promise.toListPromise +import java.util.* + +interface ICloudService : ICacheValue, ICloudServiceVariables, INetworkComponent, IBootstrap, + IPropertyMap { + + /** + * Returns the service group name of this service + * e.g Lobby + */ + fun getGroupName(): String + + /** + * Returns the number of this service. + * e.g. When the service name is Lobby-2 the service number will be 2 + */ + fun getServiceNumber(): Int + + /** + * Returns the Unique Id of this service + */ + fun getUniqueId(): UUID + + /** + * Returns the type of this service + */ + fun getServiceType(): ServiceType = getServiceGroup().getServiceType() + + /** + * Returns the version, this service is running on + */ + fun getServiceVersion(): ServiceVersion + + /** + * Returns the name of the template that this service uses + * e.g. Lobby + */ + fun getTemplateName(): String + + /** + * Returns the template that this service uses + * e.g. Lobby + */ + fun getTemplate(): ITemplate = CloudAPI.instance.getTemplateManager().getTemplateByName(getTemplateName()) + ?: throw IllegalStateException( + "Can't find the template of an registered service (templates: ${ + CloudAPI.instance.getTemplateManager().getAllCachedObjects().joinToString { it.getName() } + })" + ) + + /** + * Returns the service group of this service + */ + fun getServiceGroup(): ICloudServiceGroup = + CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(getGroupName()) + ?: throw IllegalStateException("Can't find the service group of an registered service") + + /** + * Returns the maximum amount of RAM for this service in MB + */ + fun getMaxMemory(): Int + + /** + * Returns the used amount of RAM for this service in MB + */ + fun getUsedMemory(): Int + + /** + * Returns the name of the wrapper this service is running on + */ + fun getWrapperName(): String? + + /** + * Returns the wrapper this service is running on + */ + fun getWrapper(): IWrapperInfo = + getWrapperName()?.let { CloudAPI.instance.getWrapperManager().getWrapperByName(it) } + ?: throw IllegalStateException("Can't find the wrapper where the service ${getName()} is running on. Wrapper-Name: ${getWrapperName()}") + + /** + * Returns the host of this service + */ + fun getHost(): String = getWrapper().getHost() + + /** + * Returns the port this service is bound to + */ + fun getPort(): Int + + /** + * Returns whether this service is static. + */ + fun isStatic(): Boolean = getServiceGroup().isStatic() + + /** + * Returns the percentage of occupied slots + */ + fun getOnlinePercentage(): Double { + return getOnlineCount().toDouble() / getMaxPlayers() + } + + /** + * Returns the name of this service. + * e.g. Lobby-1 + */ + override fun getName(): String = getGroupName() + "-" + getServiceNumber() + + /** + * Returns a promise of players currently connected to this service + */ + fun getOnlinePlayers(): ICommunicationPromise> { + return CloudAPI.instance.getCloudPlayerManager().getPlayersConnectedToService(this) + } + + /** + * Returns a promise of players currently connected to this service + * If you just need the name or the uniqueId of the the online players use [getOnlinePlayers] instead + * because this function takes much longer + */ + fun getOnlinePlayersDirect(): ICommunicationPromise> { + return getOnlinePlayers().then { simplePlayers -> simplePlayers.map { it.getCloudPlayer() }.toListPromise() } + .flatten() + } + + /** + * Returns weather this service is joinable for players. + */ + fun isOnline() = isServiceJoinable() + + /** + * Returns whether this service is full. + */ + fun isFull() = getOnlineCount() >= getMaxPlayers() + + override fun getNetworkComponentType(): NetworkComponentType = NetworkComponentType.SERVICE + + /** + * Creates a promise that completes when the service is starting. + */ + fun createStartingPromise(): ICommunicationPromise { + if (isActive() || getState() == ServiceState.CLOSED) + return CommunicationPromise.of(CloudServiceStartingEvent(this)) + return cloudListener() + .addCondition { it.cloudService === this@ICloudService } + .toPromise() + } + + /** + * Creates a promise that completes when the service is connected to the manager. + */ + fun createConnectedPromise(): ICommunicationPromise { + if (isAuthenticated() || getState() == ServiceState.CLOSED) + return CommunicationPromise.of(CloudServiceConnectedEvent(this)) + return cloudListener() + .addCondition { it.cloudService === this@ICloudService } + .toPromise() + } + + /** + * Creates a promise that completes when the service is started. + */ + fun createStartedPromise(): ICommunicationPromise { + if (isOnline() || getState() == ServiceState.CLOSED) + return CommunicationPromise.of(CloudServiceStartedEvent(this)) + return cloudListener() + .addCondition { it.cloudService === this@ICloudService } + .toPromise() + } + + /** + * Creates a promise that completes when the service is closed. + */ + fun createClosedPromise(): ICommunicationPromise { + if (getState() == ServiceState.CLOSED) + return CommunicationPromise.of(CloudServiceUnregisteredEvent(this)) + return cloudListener() + .addCondition { it.cloudService === this@ICloudService } + .toPromise() + } + + /** + * Returns whether this service is a lobby service. + */ + fun isLobby(): Boolean = getServiceType() == ServiceType.LOBBY + + /** + * Returns whether this service is a proxy service. + */ + fun isProxy(): Boolean = getServiceType() == ServiceType.PROXY + + /** + * Updates this service to the network + */ + fun update(): ICommunicationPromise { + return getUpdater().update() + } + + /** + * Copies the service to the template directory. + * @return a promise that completes when the service was copied. + */ + fun copy(path: String): ICommunicationPromise { + return CloudAPI.instance.getCloudServiceManager().copyService(this, path) + } + + /** + * Returns true when this service is starting or visible + */ + fun isStartingOrVisible() = getState() == ServiceState.STARTING || getState() == ServiceState.VISIBLE + + override fun isActive(): Boolean = getState() != ServiceState.PREPARED && getState() != ServiceState.CLOSED + + override fun start() = CloudAPI.instance.getCloudServiceManager().startService(this) + + override fun shutdown() = CloudAPI.instance.getCloudServiceManager().stopService(this) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceManager.kt new file mode 100644 index 000000000..98f7444ae --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceManager.kt @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service + +import eu.thesimplecloud.api.cachelist.ICacheList +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +interface ICloudServiceManager : ICacheList { + + /** + * Removes the [ICloudService] found by the specified name + */ + fun deleteCloudService(name: String) + + /** + * Returns the [ICloudService] found by the specified name + */ + fun getCloudServiceByName(name: String): ICloudService? = + getAllCachedObjects().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns a list of all registered services found by this group name + */ + fun getCloudServicesByGroupName(groupName: String): List = + getAllCachedObjects().filter { it.getGroupName().equals(groupName, true) }.sortedBy { it.getServiceNumber() } + + /** + * Returns a list of services found by the specified group name which are in LOBBY state + */ + fun getCloudServicesInLobbyStateByGroupName(groupName: String): List = + getCloudServicesByGroupName(groupName).filter { it.getState() == ServiceState.VISIBLE } + + /** + * Returns a list of services found by the specified group name which are in LOBBY state and are not full + */ + fun getNotFullServicesInLobbyStateByGroupName(groupName: String): List = + getCloudServicesInLobbyStateByGroupName(groupName).filter { it.getOnlineCount() < it.getMaxPlayers() } + + /** + * Returns a list of all services running on the specified wrapper + */ + fun getServicesRunningOnWrapper(wrapperName: String): List = + getAllCachedObjects().filter { it.getWrapperName().equals(wrapperName, true) } + + /** + * Starts the specified service + * @return a promise that completes when the service connects to the manager + */ + fun startService(cloudService: ICloudService): ICommunicationPromise = + throw UnsupportedOperationException("Can not start a service here.") + + /** + * Stops the specified service + * @return a promise that completes when the service was stopped. + */ + fun stopService(cloudService: ICloudService): ICommunicationPromise + + /** + * Copies the service to the template directory. + * @return q promise that completes when the service was copied. + */ + fun copyService(cloudService: ICloudService, path: String): ICommunicationPromise +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceUpdater.kt new file mode 100644 index 000000000..f48825b5c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceUpdater.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service + +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater + +/** + * Created by IntelliJ IDEA. + * Date: 22.01.2021 + * Time: 18:17 + * @author Frederick Baier + */ +interface ICloudServiceUpdater : ICloudServiceVariables, ICacheValueUpdater { + + fun getCloudService(): ICloudService + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceVariables.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceVariables.kt new file mode 100644 index 000000000..1b9295600 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ICloudServiceVariables.kt @@ -0,0 +1,101 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service + +import eu.thesimplecloud.api.network.component.IAuthenticatable +import eu.thesimplecloud.api.utils.time.Timestamp + +/** + * Created by IntelliJ IDEA. + * Date: 18.01.2021 + * Time: 17:13 + * @author Frederick Baier + */ +interface ICloudServiceVariables : IAuthenticatable { + + /** + * Returns the state of this service. + */ + fun getState(): ServiceState + + /** + * Returns the amount of players that are currently on this service + */ + fun getOnlineCount(): Int + + /** + * Returns the last time stamp a player interacted with the server. + */ + fun getLastPlayerUpdate(): Timestamp + + /** + * Returns the maximum amount of players for this service + */ + fun getMaxPlayers(): Int + + /** + * Returns the MOTD of this service. + */ + fun getMOTD(): String + + /** + * Returns the display name of this service. + */ + fun getDisplayName(): String + + /** + * Returns weather this service is joinable for players. + */ + fun isServiceJoinable() = getState() == ServiceState.VISIBLE || getState() == ServiceState.INVISIBLE + + /** + * Sets the state of this service + */ + fun setState(serviceState: ServiceState) + + /** + * Sets the amount of online players. + */ + fun setOnlineCount(amount: Int) + + /** + * Sets the last time a player interacted with the server. + */ + fun setLastPlayerUpdate(timeStamp: Timestamp) + + /** + * Sets the maximum amount of players for this service. + * The amount has no effect on players trying to join. + */ + fun setMaxPlayers(amount: Int) + + /** + * Sets the MOTD of this service. + */ + fun setMOTD(motd: String) + + /** + * Set the display name of this service. + */ + fun setDisplayName(displayname: String) +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceState.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceState.kt new file mode 100644 index 000000000..8126f85b1 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceState.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service + +enum class ServiceState { + + /** + * The service was registered but not started yet. + */ + PREPARED, + + /** + * The service is registered and is currently starting + */ + STARTING, + + /** + * The service was started and will now be shown on the cloud signs. + */ + VISIBLE, + + /** + * The service is online and will not be shown on the cloud signs. + */ + INVISIBLE, + + /** + * The service was stopped + */ + CLOSED + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceType.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceType.kt new file mode 100644 index 000000000..e94dd3ae0 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/ServiceType.kt @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service + +enum class ServiceType { + + /** + * Represents a proxy service + */ + PROXY, + + /** + * Represents a normal minecraft server + */ + SERVER, + + /** + * Represents a lobby server + */ + LOBBY; + + /** + * Returns whether this service type is a proxy service + */ + fun isProxy(): Boolean { + return this == PROXY + } + + /** + * Returns whether this service type is a server service + */ + fun isServer(): Boolean { + return this == SERVER + } + + /** + * Returns whether this service type is a lobby service + */ + fun isLobby(): Boolean { + return this == LOBBY + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/AbstractCloudServiceManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/AbstractCloudServiceManager.kt new file mode 100644 index 000000000..102cd2cd1 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/AbstractCloudServiceManager.kt @@ -0,0 +1,101 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.AbstractCacheList +import eu.thesimplecloud.api.cachelist.ICacheObjectUpdateExecutor +import eu.thesimplecloud.api.event.service.* +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.ICloudServiceUpdater +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.utils.time.Timestamp +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +abstract class AbstractCloudServiceManager : AbstractCacheList(), + ICloudServiceManager { + + private val updater = object : ICacheObjectUpdateExecutor { + + override fun getCachedObjectByUpdateValue(value: ICloudService): ICloudService? { + return getCloudServiceByName(value.getName()) + } + + override fun determineEventsToCall(updater: ICloudServiceUpdater, cachedValue: ICloudService?): List { + val serviceToUse = cachedValue ?: updater.getCloudService() + if (cachedValue == null) { + return listOf(CloudServiceRegisteredEvent(serviceToUse), CloudServiceUpdatedEvent(serviceToUse)) + } + val nowStarting = + cachedValue.getState() == ServiceState.PREPARED && updater.getState() == ServiceState.STARTING + val nowOnline = !cachedValue.isOnline() && updater.isServiceJoinable() + val nowConnected = !cachedValue.isAuthenticated() && updater.isAuthenticated() + val nowInvisible = + cachedValue.getState() == ServiceState.VISIBLE && updater.getState() == ServiceState.INVISIBLE + + val events = ArrayList() + events.add(CloudServiceUpdatedEvent(cachedValue)) + + if (nowStarting) { + events.add(CloudServiceStartingEvent(cachedValue)) + } + if (nowConnected) { + events.add(CloudServiceConnectedEvent(cachedValue)) + } + if (nowOnline) { + events.add(CloudServiceStartedEvent(cachedValue)) + } + if (nowInvisible) { + events.add(CloudServiceInvisibleEvent(cachedValue)) + } + return events + } + + override fun addNewValue(value: ICloudService) { + value.setLastPlayerUpdate(Timestamp()) + values.add(value) + } + + override fun getIdentificationName(): String { + return "service-cache" + } + + } + + override fun getUpdateExecutor(): ICacheObjectUpdateExecutor { + return this.updater + } + + override fun deleteCloudService(name: String) { + getCloudServiceByName(name)?.let { + this.delete(it) + } + } + + override fun delete(value: ICloudService, fromPacket: Boolean): ICommunicationPromise { + CloudAPI.instance.getEventManager().call(CloudServiceUnregisteredEvent(value)) + return super.delete(value, fromPacket) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudService.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudService.kt new file mode 100644 index 000000000..27df50028 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudService.kt @@ -0,0 +1,203 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.impl + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ICloudServiceUpdater +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.utils.time.Timestamp +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude +import java.util.* +import java.util.concurrent.ConcurrentMap + +data class DefaultCloudService( + private val groupName: String, + private val serviceNumber: Int, + private var displayname: String, + private val uniqueId: UUID, + private val templateName: String, + @Volatile private var wrapperName: String?, + @Volatile private var port: Int, + private val maxMemory: Int, + @Volatile private var maxPlayers: Int, + @Volatile private var motd: String, + private val serviceVersion: ServiceVersion +) : ICloudService { + + @JsonLibExclude + @PacketExclude + @Volatile + private var serviceUpdater: DefaultCloudServiceUpdater? = DefaultCloudServiceUpdater(this) + + @Volatile + private var serviceState = ServiceState.PREPARED + + @Volatile + private var onlineCount = 0 + + @Volatile + private var usedMemory = 0 + + @Volatile + private var authenticated = false + + @JsonLibExclude + @Volatile + private var lastPlayerUpdate = Timestamp() + + @Volatile + var propertyMap: ConcurrentMap> = Maps.newConcurrentMap() + + override fun getGroupName(): String = this.groupName + + override fun getServiceNumber(): Int = this.serviceNumber + + override fun getUniqueId(): UUID = this.uniqueId + + + override fun getServiceVersion(): ServiceVersion = this.serviceVersion + + override fun getTemplateName(): String = this.templateName + + override fun getPort(): Int = this.port + override fun getDisplayName(): String = this.displayname + + override fun setDisplayName(displayname: String) { + this.displayname = displayname + } + + override fun getUpdater(): ICloudServiceUpdater { + if (this.serviceUpdater == null) { + this.serviceUpdater = DefaultCloudServiceUpdater(this) + } + return this.serviceUpdater!! + } + + fun setPort(port: Int) { + this.port = port + } + + override fun getWrapperName(): String? = this.wrapperName + + fun setWrapperName(wrapperName: String?) { + this.wrapperName = wrapperName + } + + override fun getState(): ServiceState = this.serviceState + + override fun setState(serviceState: ServiceState) { + getUpdater().setState(serviceState) + } + + override fun getOnlineCount(): Int { + return this.onlineCount + } + + override fun setOnlineCount(amount: Int) { + getUpdater().setOnlineCount(amount) + } + + override fun getMaxPlayers(): Int { + return this.maxPlayers + } + + override fun setMaxPlayers(amount: Int) { + getUpdater().setMaxPlayers(amount) + } + + override fun getMOTD(): String = this.motd + + override fun setMOTD(motd: String) { + getUpdater().setMOTD(motd) + } + + override fun isAuthenticated(): Boolean = this.authenticated + + override fun setAuthenticated(authenticated: Boolean) { + this.authenticated = authenticated + } + + override fun getMaxMemory(): Int = this.maxMemory + + + override fun getUsedMemory(): Int = this.usedMemory + + override fun getLastPlayerUpdate(): Timestamp = this.lastPlayerUpdate + + override fun setLastPlayerUpdate(timeStamp: Timestamp) { + getUpdater().setLastPlayerUpdate(timeStamp) + } + + + override fun toString(): String { + return JsonLib.fromObject(this).getAsJsonString() + } + + override fun getProperties(): Map> = this.propertyMap + + override fun setProperty(name: String, value: T): IProperty { + require(value !is Property<*>) { "Cannot set ${value::class.java.name} as property" } + val property = Property(value) + this.propertyMap[name] = property + return property + } + + override fun clearProperties() { + this.propertyMap.clear() + } + + override fun removeProperty(name: String) { + this.propertyMap.remove(name) + } + + override fun applyValuesFromUpdater(updater: ICloudServiceUpdater) { + this.serviceState = updater.getState() + this.onlineCount = updater.getOnlineCount() + this.lastPlayerUpdate = updater.getLastPlayerUpdate() + this.motd = updater.getMOTD() + this.maxPlayers = updater.getMaxPlayers() + this.displayname = updater.getDisplayName() + + val updateService = updater.getCloudService() + this.authenticated = updateService.isAuthenticated() + this.wrapperName = updateService.getWrapperName() + this.port = updateService.getPort() + this.usedMemory = updateService.getUsedMemory() + this.propertyMap = + this.getMapWithNewestProperties(updateService.getProperties()) as ConcurrentMap> + + if (this.getOnlineCount() != updateService.getOnlineCount()) + this.lastPlayerUpdate = Timestamp() + } + + fun setUsedMemory(usedMemory: Int) { + this.usedMemory = usedMemory + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudServiceUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudServiceUpdater.kt new file mode 100644 index 000000000..4ee8b6204 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/impl/DefaultCloudServiceUpdater.kt @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.AbstractCacheValueUpdater +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ICloudServiceUpdater +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.utils.time.Timestamp +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 18.01.2021 + * Time: 17:22 + * @author Frederick Baier + */ +class DefaultCloudServiceUpdater( + private val delegateService: ICloudService +) : AbstractCacheValueUpdater(), ICloudServiceUpdater { + + override fun getCloudService(): ICloudService { + return this.delegateService + } + + override fun getState(): ServiceState { + return getChangedValue("serviceState") ?: delegateService.getState() + } + + override fun setState(serviceState: ServiceState) { + changes["serviceState"] = serviceState + } + + override fun getOnlineCount(): Int { + return getChangedValue("onlineCount") ?: delegateService.getOnlineCount() + } + + override fun setOnlineCount(amount: Int) { + changes["onlineCount"] = amount + } + + override fun getLastPlayerUpdate(): Timestamp { + return getChangedValue("lastPlayerUpdate") ?: delegateService.getLastPlayerUpdate() + } + + override fun setLastPlayerUpdate(timeStamp: Timestamp) { + changes["lastPlayerUpdate"] = timeStamp + } + + override fun getMaxPlayers(): Int { + return getChangedValue("maxPlayers") ?: delegateService.getMaxPlayers() + } + + override fun setMaxPlayers(amount: Int) { + changes["maxPlayers"] = amount + } + + override fun getMOTD(): String { + return getChangedValue("motd") ?: delegateService.getMOTD() + } + + override fun getDisplayName(): String { + return getChangedValue("displayname") ?: delegateService.getDisplayName() + } + + override fun isAuthenticated(): Boolean { + return getChangedValue("authenticated") ?: delegateService.isAuthenticated() + } + + override fun setAuthenticated(authenticated: Boolean) { + changes["authenticated"] = authenticated + } + + override fun setMOTD(motd: String) { + changes["motd"] = motd + } + + override fun setDisplayName(displayname: String) { + changes["displayname"] = displayname + } + + override fun update(): ICommunicationPromise { + val promise = CloudAPI.instance.getCloudServiceManager().update(delegateService) + reset() + return promise + } + + private fun reset() { + this.changes.clear() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/IServiceStartConfiguration.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/IServiceStartConfiguration.kt new file mode 100644 index 000000000..8917f9ce0 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/IServiceStartConfiguration.kt @@ -0,0 +1,79 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.start.configuration + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.start.future.IServiceStartPromise +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.template.ITemplate + +interface IServiceStartConfiguration { + + /** + * Returns the name of the group of the service to start. + */ + fun getServiceGroupName(): String + + /** + * Sets the maximum amount of players + * @return this [IServiceStartConfiguration] + */ + fun setMaxPlayers(maxPlayers: Int): IServiceStartConfiguration + + /** + * Sets the maximum amount of memory + * @param memory the amount of memory in MB + * @return this [IServiceStartConfiguration] + */ + fun setMaxMemory(memory: Int): IServiceStartConfiguration + + /** + * Sets the template for the new service + * @return this [IServiceStartConfiguration] + */ + fun setTemplate(template: ITemplate): IServiceStartConfiguration + + /** + * Sets the number of this service. + * e.g: Lobby-2 -> 2 is the service number + * @return this [IServiceStartConfiguration] + */ + fun setServiceNumber(number: Int): IServiceStartConfiguration + + /** + * Returns the group of the new service. + */ + fun getServiceGroup(): ICloudServiceGroup { + return CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(getServiceGroupName()) + ?: throw IllegalStateException("ServiceGroup by name ${getServiceGroupName()} is null") + } + + /** + * Starts the service + * @return a custom promise that completes when the new service was registered + */ + fun startService(): IServiceStartPromise { + return CloudAPI.instance.getCloudServiceGroupManager().startNewService(this) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/ServiceStartConfiguration.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/ServiceStartConfiguration.kt new file mode 100644 index 000000000..e73de8546 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/configuration/ServiceStartConfiguration.kt @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.start.configuration + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.template.ITemplate + +/** + * Creates a new [ServiceStartConfiguration] with the default values of the specified service group + */ +class ServiceStartConfiguration(serviceGroup: ICloudServiceGroup) : IServiceStartConfiguration { + + /** + * The name of the group + */ + val groupName = serviceGroup.getName() + + /** + * The memory amount in MB for the new service. + */ + @Volatile + var maxMemory = serviceGroup.getMaxMemory() + private set + + /** + * The maximum amount of players for the new service. + */ + @Volatile + var maxPlayers = serviceGroup.getMaxPlayers() + private set + + /** + * The template the new service shall use. + */ + @Volatile + var template = serviceGroup.getTemplateName() + private set + + /** + * The number of the new service. + * e.g: Lobby-2 -> 2 is the service number + */ + @Volatile + var serviceNumber: Int? = null + private set + + + override fun getServiceGroupName(): String { + return this.groupName + } + + override fun setMaxMemory(memory: Int): ServiceStartConfiguration { + require(memory >= 100) { "The specified memory must be at least 100" } + this.maxMemory = memory + return this + } + + override fun setMaxPlayers(maxPlayers: Int): ServiceStartConfiguration { + require(maxPlayers > 0) { "The specified amount of maxPlayers must be positive." } + this.maxPlayers = maxPlayers + return this + } + + override fun setTemplate(template: ITemplate): ServiceStartConfiguration { + this.template = template.getName() + return this + } + + override fun setServiceNumber(number: Int): ServiceStartConfiguration { + require(number > 0) { "The specified number must be positive." } + this.serviceNumber = number + return this + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/IServiceStartPromise.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/IServiceStartPromise.kt new file mode 100644 index 000000000..9798fcf66 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/IServiceStartPromise.kt @@ -0,0 +1,87 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.start.future + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromiseListener +import io.netty.util.concurrent.Future +import io.netty.util.concurrent.GenericFutureListener +import java.util.function.Consumer + +/** + * Created by IntelliJ IDEA. + * Date: 20.12.2020 + * Time: 18:49 + * @author Frederick Baier + */ +interface IServiceStartPromise : ICommunicationPromise { + + /** + * Calls the specified [consumer] when the service was registered + */ + fun onServiceRegistered(consumer: Consumer): IServiceStartPromise + + /** + * Calls the specified [consumer] when the service is starting + */ + fun onServiceStarting(consumer: Consumer): IServiceStartPromise + + /** + * Calls the specified [consumer] when the service was started + */ + fun onServiceStarted(consumer: Consumer): IServiceStartPromise + + + override fun addCommunicationPromiseListeners(vararg listener: ICommunicationPromiseListener): IServiceStartPromise + + override fun addCompleteListener(listener: (ICommunicationPromise) -> Unit): IServiceStartPromise + + override fun addCompleteListener(listener: ICommunicationPromiseListener): IServiceStartPromise + + override fun addFailureListener(listener: (Throwable) -> Unit): IServiceStartPromise + + override fun addListener(listener: GenericFutureListener>?): IServiceStartPromise + + override fun addListeners(vararg listeners: GenericFutureListener>?): IServiceStartPromise + + override fun addResultListener(listener: (ICloudService) -> Unit): IServiceStartPromise + + override fun await(): IServiceStartPromise + + override fun awaitUninterruptibly(): IServiceStartPromise + + override fun removeListener(listener: GenericFutureListener>?): IServiceStartPromise + + override fun removeListeners(vararg listeners: GenericFutureListener>?): IServiceStartPromise + + override fun setFailure(cause: Throwable): IServiceStartPromise + + override fun setSuccess(result: ICloudService): IServiceStartPromise + + override fun sync(): IServiceStartPromise + + override fun syncUninterruptibly(): ICommunicationPromise + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/ServiceStartPromise.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/ServiceStartPromise.kt new file mode 100644 index 000000000..ce29ecd7c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/start/future/ServiceStartPromise.kt @@ -0,0 +1,234 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.start.future + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromiseListener +import eu.thesimplecloud.clientserverapi.lib.promise.flatten +import io.netty.util.concurrent.Future +import io.netty.util.concurrent.GenericFutureListener +import java.util.concurrent.TimeUnit +import java.util.function.Consumer + +/** + * Created by IntelliJ IDEA. + * Date: 20.12.2020 + * Time: 18:49 + * @author Frederick Baier + */ +class ServiceStartPromise( + private val delegatePromise: ICommunicationPromise +) : IServiceStartPromise { + + override fun onServiceRegistered(consumer: Consumer): IServiceStartPromise { + delegatePromise.then { consumer.accept(it) } + return this + } + + override fun onServiceStarting(consumer: Consumer): IServiceStartPromise { + delegatePromise.then { it.createStartingPromise() }.flatten(timeoutEnabled = false) + .then { consumer.accept(it.cloudService) } + return this + } + + override fun onServiceStarted(consumer: Consumer): IServiceStartPromise { + delegatePromise.then { it.createStartedPromise() }.flatten(timeoutEnabled = false) + .then { consumer.accept(it.cloudService) } + return this + } + + override fun addCommunicationPromiseListeners(vararg listener: ICommunicationPromiseListener): IServiceStartPromise { + delegatePromise.addCommunicationPromiseListeners(*listener) + return this + } + + override fun addCompleteListener(listener: (ICommunicationPromise) -> Unit): IServiceStartPromise { + delegatePromise.addCompleteListener(listener) + return this + } + + override fun addCompleteListener(listener: ICommunicationPromiseListener): IServiceStartPromise { + delegatePromise.addCompleteListener(listener) + return this + } + + override fun addFailureListener(listener: (Throwable) -> Unit): IServiceStartPromise { + delegatePromise.addFailureListener(listener) + return this + } + + override fun addListener(listener: GenericFutureListener>?): IServiceStartPromise { + delegatePromise.addListener(listener) + return this + } + + override fun addListeners(vararg listeners: GenericFutureListener>?): IServiceStartPromise { + delegatePromise.addListeners(*listeners) + return this + } + + override fun addResultListener(listener: (ICloudService) -> Unit): IServiceStartPromise { + delegatePromise.addResultListener(listener) + return this + } + + override fun await(): IServiceStartPromise { + delegatePromise.await() + return this + } + + override fun await(timeout: Long, unit: TimeUnit?): Boolean { + return delegatePromise.await(timeout, unit) + } + + override fun await(timeoutMillis: Long): Boolean { + return delegatePromise.await(timeoutMillis) + } + + override fun awaitUninterruptibly(): IServiceStartPromise { + delegatePromise.awaitUninterruptibly() + return this + } + + override fun awaitUninterruptibly(timeout: Long, unit: TimeUnit?): Boolean { + return delegatePromise.awaitUninterruptibly(timeout, unit) + } + + override fun awaitUninterruptibly(timeoutMillis: Long): Boolean { + return delegatePromise.awaitUninterruptibly(timeoutMillis) + } + + override fun cancel(mayInterruptIfRunning: Boolean): Boolean { + return delegatePromise.cancel(mayInterruptIfRunning) + } + + override fun cause(): Throwable { + return delegatePromise.cause() + } + + override fun combine( + communicationPromise: ICommunicationPromise<*>, + sumUpTimeouts: Boolean + ): ICommunicationPromise { + return delegatePromise.combine(communicationPromise, sumUpTimeouts) + } + + override fun combineAll( + promises: List>, + sumUpTimeouts: Boolean + ): ICommunicationPromise { + return delegatePromise.combineAll(promises, sumUpTimeouts) + } + + override fun copyStateFromOtherPromise(otherPromise: ICommunicationPromise) { + return delegatePromise.copyStateFromOtherPromise(otherPromise) + } + + override fun get(): ICloudService { + return delegatePromise.get() + } + + override fun get(timeout: Long, unit: TimeUnit): ICloudService { + return delegatePromise.get(timeout, unit) + } + + override fun getNow(): ICloudService? { + return delegatePromise.getNow() + } + + override fun getTimeout(): Long { + return delegatePromise.getTimeout() + } + + override fun isCancellable(): Boolean { + return delegatePromise.isCancellable + } + + override fun isCancelled(): Boolean { + return delegatePromise.isCancelled + } + + override fun isDone(): Boolean { + return delegatePromise.isDone + } + + override fun isSuccess(): Boolean { + return delegatePromise.isSuccess + } + + override fun isTimeoutEnabled(): Boolean { + return delegatePromise.isTimeoutEnabled() + } + + override fun removeListener(listener: GenericFutureListener>?): IServiceStartPromise { + delegatePromise.removeListener(listener) + return this + } + + override fun removeListeners(vararg listeners: GenericFutureListener>?): IServiceStartPromise { + delegatePromise.removeListeners(*listeners) + return this + } + + override fun setFailure(cause: Throwable): IServiceStartPromise { + delegatePromise.setFailure(cause) + return this + } + + override fun setSuccess(result: ICloudService): IServiceStartPromise { + delegatePromise.setSuccess(result) + return this + } + + override fun setUncancellable(): Boolean { + return delegatePromise.setUncancellable() + } + + override fun sync(): IServiceStartPromise { + delegatePromise.sync() + return this + } + + override fun syncUninterruptibly(): ICommunicationPromise { + return delegatePromise.syncUninterruptibly() + } + + override fun thenDelayed( + delay: Long, + timeUnit: TimeUnit, + function: (ICloudService) -> R? + ): ICommunicationPromise { + return delegatePromise.thenDelayed(delay, timeUnit, function) + } + + override fun tryFailure(cause: Throwable?): Boolean { + return delegatePromise.tryFailure(cause) + } + + override fun trySuccess(result: ICloudService?): Boolean { + return delegatePromise.trySuccess(result) + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/IServiceVersionHandler.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/IServiceVersionHandler.kt new file mode 100644 index 000000000..f181ff691 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/IServiceVersionHandler.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version + +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.api.service.version.type.ServiceVersionType + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 09:58 + * @author Frederick Baier + */ +interface IServiceVersionHandler { + + /** + * Returns all available versions for the specified [serviceVersionType] + */ + fun getVersions(serviceAPIType: ServiceAPIType): List + + /** + * Returns all versions with the specified [prefix] + */ + fun getVersionsByPrefix(prefix: String): List + + /** + * Returns all version prefixes + */ + fun getAllAvailablePrefixes(): Set + + /** + * Returns all versions suffixes for one [prefix] + */ + fun getAllVersionSuffixes(prefix: String): List + + /** + * Returns the prefixes for the specified [serviceAPIType] + */ + fun getPrefixesByServiceAPIType(serviceAPIType: ServiceAPIType): Set + + /** + * Returns the prefixes for the specified [serviceVersionType] + */ + fun getVersionsByServiceVersionType(serviceVersionType: ServiceVersionType): List + + /** + * Returns the prefixes for the specified [serviceVersionType] + */ + fun getPrefixesByServiceVersionType(serviceVersionType: ServiceVersionType): Set + + /** + * Returns the [ServiceVersion] found by the specified [name] + */ + fun getServiceVersionByName(name: String): ServiceVersion? + + /** + * Returns a list of all [ServiceVersion]s + */ + fun getAllVersions(): List + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersion.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersion.kt new file mode 100644 index 000000000..e71d286c4 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersion.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version + +import eu.thesimplecloud.api.service.version.type.ServiceAPIType + +/** + * Created by IntelliJ IDEA. + * Date: 14.06.2020 + * Time: 10:57 + * @author Frederick Baier + */ +data class ServiceVersion( + val name: String, + val serviceAPIType: ServiceAPIType, + val downloadURL: String, + val isPaperClip: Boolean = false +) \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersionHandler.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersionHandler.kt new file mode 100644 index 000000000..61534a73f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/ServiceVersionHandler.kt @@ -0,0 +1,92 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version + +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.api.service.version.type.ServiceVersionType + +/** + * Created by IntelliJ IDEA. + * Date: 14.06.2020 + * Time: 13:27 + * @author Frederick Baier + */ +open class ServiceVersionHandler( + @Volatile + var versions: List = emptyList() +) : IServiceVersionHandler { + + + override fun getVersions(serviceAPIType: ServiceAPIType): List { + return this.versions.filter { it.serviceAPIType == serviceAPIType } + } + + override fun getVersionsByPrefix(prefix: String): List { + if (prefix.contains("_")) return emptyList() + val serviceVersions = versions.filter { it.name.startsWith(prefix.uppercase()) } + if (serviceVersions.isEmpty()) return emptyList() + //check if all versions have the same version type + val firstVersionType = serviceVersions.first().serviceAPIType + if (!serviceVersions.all { it.serviceAPIType == firstVersionType }) + throw IllegalStateException("API types of prefix $prefix are not equal") + return serviceVersions + } + + override fun getAllAvailablePrefixes(): Set { + return this.versions.map { getPrefixFromFullName(it.name) }.toSet() + } + + override fun getAllVersionSuffixes(prefix: String): List { + return getVersionsByPrefix(prefix) + .map { it.name } + .map { it.replace((prefix + "_").toUpperCase(), "") } + } + + override fun getPrefixesByServiceAPIType(serviceAPIType: ServiceAPIType): Set { + return getVersions(serviceAPIType).map { getPrefixFromFullName(it.name) }.toSet() + } + + override fun getVersionsByServiceVersionType(serviceVersionType: ServiceVersionType): List { + return this.versions.filter { it.serviceAPIType.serviceVersionType == serviceVersionType } + } + + override fun getPrefixesByServiceVersionType(serviceVersionType: ServiceVersionType): Set { + return getVersionsByServiceVersionType(serviceVersionType) + .map { getPrefixFromFullName(it.name) }.toSet() + } + + + override fun getServiceVersionByName(name: String): ServiceVersion? { + return this.versions.firstOrNull { it.name == name } + } + + override fun getAllVersions(): List { + return this.versions + } + + private fun getPrefixFromFullName(fullName: String): String { + return fullName.split("_")[0] + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/CombinedServiceVersionLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/CombinedServiceVersionLoader.kt new file mode 100644 index 000000000..61d5a213f --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/CombinedServiceVersionLoader.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.loader + +import eu.thesimplecloud.api.service.version.ServiceVersion + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:08 + * @author Frederick Baier + */ +object CombinedServiceVersionLoader : IServiceVersionLoader { + + private val loaders = listOf(ServiceVersionWebLoader(), LocalServiceVersionHandler()) + + override fun loadVersions(): List { + return loaders.map { it.loadVersions() }.flatten() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/IServiceVersionLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/IServiceVersionLoader.kt new file mode 100644 index 000000000..90a809c04 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/IServiceVersionLoader.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.loader + +import eu.thesimplecloud.api.service.version.ServiceVersion + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:06 + * @author Frederick Baier + */ +interface IServiceVersionLoader { + + /** + * Loads all [ServiceVersion]s this loader can access + */ + fun loadVersions(): List + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/LocalServiceVersionHandler.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/LocalServiceVersionHandler.kt new file mode 100644 index 000000000..4a560e606 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/LocalServiceVersionHandler.kt @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.loader + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:10 + * @author Frederick Baier + */ +class LocalServiceVersionHandler : IServiceVersionLoader { + + private val file = File(DirectoryPaths.paths.storagePath + "localServiceVersions.json") + + override fun loadVersions(): List { + if (!file.exists()) return emptyList() + return JsonLib.fromJsonFile(file)!!.getObject(Array::class.java).toList() + } + + fun saveServiceVersion(serviceVersion: ServiceVersion) { + val existingVersions = loadVersions().toMutableList() + existingVersions.removeIf { it.name.equals(serviceVersion.name, true) } + existingVersions.add(serviceVersion) + JsonLib.fromObject(existingVersions).saveAsFile(file) + } + + fun deleteServiceVersion(name: String) { + val existingVersions = loadVersions().toMutableList() + existingVersions.removeIf { it.name.equals(name, true) } + JsonLib.fromObject(existingVersions).saveAsFile(file) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/ServiceVersionWebLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/ServiceVersionWebLoader.kt new file mode 100644 index 000000000..b49771df6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/loader/ServiceVersionWebLoader.kt @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.loader + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.runner.utils.WebContentLoader +import java.io.File +import java.io.FileNotFoundException + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:07 + * @author Frederick Baier + */ +class ServiceVersionWebLoader : IServiceVersionLoader { + + private val file = File(DirectoryPaths.paths.storagePath + "onlineServiceVersions.json") + + override fun loadVersions(): List { + val version = this::class.java.`package`.implementationVersion.substring(0, 3) + val contentString = + WebContentLoader().loadContent("https://api.thesimplecloud.eu/versions?implementationVersion[\$lte]=$version") + return if (contentString == null) { + loadFromFile() + } else { + processWebContent(contentString) + } + } + + private fun loadFromFile(): List { + if (!file.exists()) throw FileNotFoundException("File ${file.absolutePath} does not exist and the web server to load the service versions from is not available") + return JsonLib.fromJsonFile(file)!!.getObject(Array::class.java).toList() + } + + private fun processWebContent(contentString: String): List { + val jsonLib = JsonLib.fromJsonString(contentString) + jsonLib.saveAsFile(file) + return jsonLib.getObject(Array::class.java).toList() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/MinecraftEdition.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/MinecraftEdition.kt new file mode 100644 index 000000000..0b4185640 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/MinecraftEdition.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.type + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 11:27 + * @author Frederick Baier + */ +enum class MinecraftEdition { + + JAVA, PE + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceAPIType.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceAPIType.kt new file mode 100644 index 000000000..38973959e --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceAPIType.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.type + +/** + * Created by IntelliJ IDEA. + * Date: 14.06.2020 + * Time: 10:58 + * @author Frederick Baier + */ +enum class ServiceAPIType( + val minecraftEdition: MinecraftEdition, + val serviceVersionType: ServiceVersionType +) { + + /** + * Represents a jar with the spigot api + */ + SPIGOT(MinecraftEdition.JAVA, ServiceVersionType.SERVER), + + /** + * Represents a jar with the bungeecord api + */ + BUNGEECORD(MinecraftEdition.JAVA, ServiceVersionType.PROXY), + + /** + * Represents a jar with the velocity api + */ + VELOCITY(MinecraftEdition.JAVA, ServiceVersionType.PROXY); + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceVersionType.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceVersionType.kt new file mode 100644 index 000000000..570b5cc98 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/service/version/type/ServiceVersionType.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.service.version.type + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 11:27 + * @author Frederick Baier + */ +enum class ServiceVersionType { + + /** + * Minecraft proxy like bungeecord, waterfall, waterdog + */ + PROXY, + + /** + * Minecraft server like spigot, paper, nukkit + */ + SERVER + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroup.kt new file mode 100644 index 000000000..e0bc7fb61 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroup.kt @@ -0,0 +1,124 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.service.start.configuration.ServiceStartConfiguration +import eu.thesimplecloud.api.service.start.future.IServiceStartPromise +import eu.thesimplecloud.api.template.ITemplate + +interface ICloudServiceGroup : ICacheValue, ICloudServiceGroupVariables { + + /** + * Returns the name of this service group + * e.g. Lobby + */ + fun getName(): String + + /** + * Returns the type of this service group + */ + fun getServiceType(): ServiceType + + /** + * Returns the template that this service uses + * e.g. Lobby + */ + fun getTemplate(): ITemplate = CloudAPI.instance.getTemplateManager().getTemplateByName(getTemplateName()) + ?: throw IllegalStateException( + "Can't find the template of an registered group (group: ${getName()} templates: ${ + CloudAPI.instance.getTemplateManager().getAllCachedObjects().joinToString { it.getName() } + })" + ) + + /** + * Returns whether this service is static. + */ + fun isStatic(): Boolean + + /** + * Returns the javaCommand for the ICloudServiceGroup + */ + fun getJavaCommandName(): String + + /** + * Returns the start priority services of this group will have. Services with higher priority will start first. + */ + fun getStartPriority(): Int + + /** + * Starts a new service by this group + * @return a promise which is called when the new service was registered. + * The promise will fail with: + * - [NoSuchElementException] if the group does not exist. + */ + fun startNewService(): IServiceStartPromise = createStartConfiguration().startService() + + /** + * Returns a new [IServiceStartConfiguration] + */ + fun createStartConfiguration(): IServiceStartConfiguration = ServiceStartConfiguration(this) + + /** + * Returns a list of all registered services by this group + */ + fun getAllServices(): List = + CloudAPI.instance.getCloudServiceManager().getCloudServicesByGroupName(getName()) + + /** + * Returns the amount of online players in this group + */ + fun getOnlinePlayerCount(): Int = getAllServices().sumBy { it.getOnlineCount() } + + /** + * Returns the amount of registered services + */ + fun getRegisteredServiceCount(): Int = getAllServices().size + + /** + * Returns the amount of online services + */ + fun getOnlineServiceCount(): Int = getAllServices().filter { it.isOnline() }.size + + /** + * Stops all services of this group. + */ + fun shutdownAllServices() = getAllServices().forEach { it.shutdown() } + + /** + * Deletes this service group from the cloud + * @throws IllegalStateException if services of this group are registered + */ + @Throws(IllegalStateException::class) + fun delete() = CloudAPI.instance.getCloudServiceGroupManager().delete(this) + + /** + * Updates the group to the network + */ + fun update() = getUpdater().update() + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupManager.kt new file mode 100644 index 000000000..f1c977e60 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupManager.kt @@ -0,0 +1,248 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup + +import eu.thesimplecloud.api.cachelist.ICacheList +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.service.start.configuration.ServiceStartConfiguration +import eu.thesimplecloud.api.service.start.future.IServiceStartPromise +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudLobbyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudProxyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultLobbyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultProxyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultServerGroup +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +interface ICloudServiceGroupManager : ICacheList { + + + /** + * Creates a new [ICloudServerGroup] by the specified parameters and returns a promise that is called when the group is registered + */ + fun createServerGroup( + groupName: String, + templateName: String, + memory: Int, + maxPlayers: Int, + minimumOnlineServiceCount: Int, + maximumOnlineServiceCount: Int, + maintenance: Boolean, + static: Boolean, + percentToStartNewService: Int, + wrapperName: String?, + serviceVersion: ServiceVersion, + startPriority: Int, + permission: String?, + javaCommand: String, + hiddenAtProxyGroups: List = emptyList() + ): ICommunicationPromise = + createServiceGroup( + DefaultServerGroup( + groupName, + templateName, + memory, + maxPlayers, + minimumOnlineServiceCount, + maximumOnlineServiceCount, + maintenance, + static, + percentToStartNewService, + wrapperName, + serviceVersion, + startPriority, + permission, + javaCommand, + hiddenAtProxyGroups + ) + ) as ICommunicationPromise + + /** + * Creates a new [ICloudLobbyGroup] by the specified parameters and returns a promise that is called when the group is registered + */ + fun createLobbyGroup( + groupName: String, + templateName: String, + memory: Int, + maxPlayers: Int, + minimumOnlineServiceCount: Int, + maximumOnlineServiceCount: Int, + maintenance: Boolean, + static: Boolean, + percentToStartNewService: Int, + wrapperName: String?, + priority: Int, + permission: String?, + serviceVersion: ServiceVersion, + startPriority: Int, + javaCommand: String, + hiddenAtProxyGroups: List = emptyList() + ): ICommunicationPromise = + createServiceGroup( + DefaultLobbyGroup( + groupName, + templateName, + memory, + maxPlayers, + minimumOnlineServiceCount, + maximumOnlineServiceCount, + maintenance, + static, + percentToStartNewService, + wrapperName, + priority, + permission, + serviceVersion, + startPriority, + javaCommand, + hiddenAtProxyGroups + ) + ) as ICommunicationPromise + + /** + * Creates a new [ICloudProxyGroup] by the specified parameters and returns a promise that is called when the group is registered + */ + fun createProxyGroup( + groupName: String, + templateName: String, + memory: Int, + maxPlayers: Int, + minimumOnlineServiceCount: Int, + maximumOnlineServiceCount: Int, + maintenance: Boolean, + static: Boolean, + percentToStartNewService: Int, + wrapperName: String?, + startPort: Int, + serviceVersion: ServiceVersion, + startPriority: Int, + permission: String? + ): ICommunicationPromise = + createServiceGroup( + DefaultProxyGroup( + groupName, + templateName, + memory, + maxPlayers, + minimumOnlineServiceCount, + maximumOnlineServiceCount, + maintenance, + static, + percentToStartNewService, + wrapperName, + startPort, + serviceVersion, + startPriority, + "java", + permission + ) + ) as ICommunicationPromise + + /** + * Creates a service group and returns a promise that is called when the group is registered + * [ICommunicationPromise.isSuccess] indicates whether the creation was successful + * The promise will fail with: + * - [IllegalArgumentException] if the group is already registered. + */ + fun createServiceGroup(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise + + /** + * Returns the [ICloudServiceGroup] found by the specified name + */ + fun getServiceGroupByName(name: String): ICloudServiceGroup? = + getAllCachedObjects().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns the [ICloudServerGroup] found by the specified name + */ + fun getServerGroupByName(name: String): ICloudServerGroup? = + getServerGroups().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns the [ICloudLobbyGroup] found by the specified name + */ + fun getLobbyGroupByName(name: String): ICloudLobbyGroup? = + getLobbyGroups().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns the [ICloudProxyGroup] found by the specified name + */ + fun getProxyGroupByName(name: String): ICloudProxyGroup? = + getProxyGroups().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns all registered proxy groups + */ + fun getProxyGroups(): List = + getAllCachedObjects().filter { it.getServiceType() == ServiceType.PROXY }.map { it as ICloudProxyGroup } + + /** + * Returns all registered lobby groups + */ + fun getLobbyGroups(): List = + getAllCachedObjects().filter { it.getServiceType() == ServiceType.LOBBY }.map { it as ICloudLobbyGroup } + + /** + * Returns all registered server groups + */ + fun getServerGroups(): List = + getAllCachedObjects().filter { it.getServiceType() == ServiceType.SERVER }.map { it as ICloudServerGroup } + + /* + * Returns all registered server or lobby groups + */ + fun getServerOrLobbyGroups(): List = getAllCachedObjects().filterIsInstance() + + /** + * Returns all groups that only start on the specified [wrapperName] + */ + fun getServiceGroupsByWrapperName(wrapperName: String): List { + return getAllCachedObjects().filter { it.getWrapperName() == wrapperName } + } + + /** + * Starts a new service by the specified group + * @return a promise that is completed when the service was registered with its name, or + * when an exception is encountered. [ICommunicationPromise.isSuccess] indicates success + * or failure. + * The promise will fail with: + * - [NoSuchElementException] if the specified group is not registered. + */ + fun startNewService(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise { + return startNewService(ServiceStartConfiguration(cloudServiceGroup)) + } + + /** + * Starts a new service by the specified [serviceStartConfiguration] + * @return a custom promise that is completed when the service was registered with its name, or + * when an exception is encountered. [ICommunicationPromise.isSuccess] indicates success + * or failure. + * The promise will fail with: + * - [IllegalArgumentException] if the service to start is already running + */ + fun startNewService(serviceStartConfiguration: IServiceStartConfiguration): IServiceStartPromise + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupUpdater.kt new file mode 100644 index 000000000..7a1f49c4a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupUpdater.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup + +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater + +interface ICloudServiceGroupUpdater : ICacheValueUpdater, ICloudServiceGroupVariables { + + fun getServiceGroup(): ICloudServiceGroup + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupVariables.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupVariables.kt new file mode 100644 index 000000000..92ef6c286 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/ICloudServiceGroupVariables.kt @@ -0,0 +1,141 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup + +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.service.version.ServiceVersion + +interface ICloudServiceGroupVariables { + + /** + * Returns the template that this service group uses + * e.g. Lobby + */ + fun getTemplateName(): String + + /** + * Sets the name of the template for this service group + */ + fun setTemplateName(name: String) + + /** + * Returns the version, services of this group are running on + */ + fun getServiceVersion(): ServiceVersion + + /** + * Sets the [ServiceVersion] of this group + */ + fun setServiceVersion(serviceVersion: ServiceVersion) + + /** + * Returns the maximum amount of RAM for the services of this service group in MB + */ + fun getMaxMemory(): Int + + /** + * Sets maximum amount of RAM for the services of this service group in MB + */ + fun setMaxMemory(memory: Int) + + /** + * Returns the maximum amount of players for the services of this service group + */ + fun getMaxPlayers(): Int + + /** + * Sets the maximum amount of players for the services of this service group + */ + fun setMaxPlayers(maxPlayers: Int) + + /** + * Returns the minimum amount of services that should be simultaneously in LOBBY state + */ + fun getMinimumOnlineServiceCount(): Int + + /** + * Sets the minimum amount of services that should be simultaneously in LOBBY state + */ + fun setMinimumOnlineServiceCount(count: Int) + + /** + * Returns the maximum amount of services that should be simultaneously in LOBBY state + */ + fun getMaximumOnlineServiceCount(): Int + + /** + * Sets the maximum amount of services that should be simultaneously in LOBBY state + */ + fun setMaximumOnlineServiceCount(count: Int) + + /** + * Returns whether this service group is in maintenance + */ + fun isInMaintenance(): Boolean + + /** + * Sets the maintenance state of this service group + */ + fun setMaintenance(maintenance: Boolean) + + /** + * Returns the percent of online players that a service must reach until a new service starts. + */ + fun getPercentToStartNewService(): Int + + /** + * Sets the percent of online players that a service must reach until a new service starts. + */ + fun setPercentToStartNewService(percentage: Int) + + /** + * Returns the wrapper where all service of this group should run and null if there is no specified wrapper. + */ + fun getWrapperName(): String? + + /** + * Sets the name of the wrapper services of this groups shall start on + */ + fun setWrapperName(name: String?) + + /** + * Returns the permission a player needs to join a service of this group or null if there is no permission set. + */ + fun getPermission(): String? + + /** + * Sets the permission a player needs to join a service of this group + */ + fun setPermission(permission: String?) + + /** + * Returns whether the state shall automatically be updated to [ServiceState.VISIBLE] + */ + fun isStateUpdatingEnabled(): Boolean + + /** + * Sets whether this group shall update its state automatically to [ServiceState.VISIBLE] + */ + fun setStateUpdating(stateUpdating: Boolean) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudLobbyGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudLobbyGroup.kt new file mode 100644 index 000000000..8bc4e5ce5 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudLobbyGroup.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.grouptype + +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.servicegroup.grouptype.updater.ICloudLobbyGroupUpdater + +interface ICloudLobbyGroup : ICloudServerGroup { + + /** + * Returns the priority of this lobby group. + * When a player joins the lobby groups permissions with higher priority will be checked first. + */ + fun getPriority(): Int + + /** + * Sets the priority of this lobby group. + */ + fun setPriority(priority: Int) + + override fun getServiceType(): ServiceType = ServiceType.LOBBY + + override fun getUpdater(): ICloudLobbyGroupUpdater + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudProxyGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudProxyGroup.kt new file mode 100644 index 000000000..995f69a4a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudProxyGroup.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.grouptype + +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.grouptype.updater.ICloudProxyGroupUpdater + +interface ICloudProxyGroup : ICloudServiceGroup { + + /** + * Returns the start port of this proxy group. + * All services started by this group will be started on this port or if it is already in use the port will be counted up + */ + fun getStartPort(): Int + + /** + * Sets the start port of this proxy group. + */ + fun setStartPort(port: Int) + + override fun getServiceType(): ServiceType = ServiceType.PROXY + + override fun getUpdater(): ICloudProxyGroupUpdater +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudServerGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudServerGroup.kt new file mode 100644 index 000000000..b2dc60c61 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/ICloudServerGroup.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.grouptype + +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +interface ICloudServerGroup : ICloudServiceGroup { + + /** + * Returns the names of proxy groups this group is hidden on + */ + fun getHiddenAtProxyGroups(): List + + override fun getServiceType(): ServiceType = ServiceType.SERVER + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudLobbyGroupUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudLobbyGroupUpdater.kt new file mode 100644 index 000000000..60ac46b9d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudLobbyGroupUpdater.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.grouptype.updater + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater + +interface ICloudLobbyGroupUpdater : ICloudServiceGroupUpdater { + + /** + * Returns the priority of this lobby group. + * When a player joins the lobby groups permissions with higher priority will be checked first. + */ + fun getPriority(): Int + + /** + * Sets the priority of this lobby group. + */ + fun setPriority(priority: Int) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudProxyGroupUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudProxyGroupUpdater.kt new file mode 100644 index 000000000..5c8cf4b12 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/grouptype/updater/ICloudProxyGroupUpdater.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.grouptype.updater + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater + +interface ICloudProxyGroupUpdater : ICloudServiceGroupUpdater { + + /** + * Returns the start port of this proxy group. + * All services started by this group will be started on this port or if it is already in use the port will be counted up + */ + fun getStartPort(): Int + + /** + * Sets the start port of this proxy group. + */ + fun setStartPort(port: Int) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractCloudServiceGroupManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractCloudServiceGroupManager.kt new file mode 100644 index 000000000..1e4e8eb5c --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractCloudServiceGroupManager.kt @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.AbstractCacheList +import eu.thesimplecloud.api.cachelist.ICacheObjectUpdateExecutor +import eu.thesimplecloud.api.event.group.CloudServiceGroupCreatedEvent +import eu.thesimplecloud.api.event.group.CloudServiceGroupUpdatedEvent +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +abstract class AbstractCloudServiceGroupManager : AbstractCacheList(), + ICloudServiceGroupManager { + + private val updater = object : ICacheObjectUpdateExecutor { + override fun getIdentificationName(): String { + return "group-cache" + } + + override fun getCachedObjectByUpdateValue(value: ICloudServiceGroup): ICloudServiceGroup? { + return getServiceGroupByName(value.getName()) + } + + override fun determineEventsToCall( + updater: ICloudServiceGroupUpdater, + cachedValue: ICloudServiceGroup? + ): List { + if (cachedValue == null) return listOf(CloudServiceGroupCreatedEvent(updater.getServiceGroup())) + return listOf(CloudServiceGroupUpdatedEvent(cachedValue)) + } + + override fun addNewValue(value: ICloudServiceGroup) { + values.add(value) + } + + } + + override fun delete(value: ICloudServiceGroup, fromPacket: Boolean): ICommunicationPromise { + if (CloudAPI.instance.getCloudServiceManager().getCloudServicesByGroupName(value.getName()).isNotEmpty()) + throw IllegalStateException("Cannot delete service group while services of this group are registered") + return super.delete(value, fromPacket) + } + + override fun getUpdateExecutor(): ICacheObjectUpdateExecutor { + return this.updater + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractServiceGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractServiceGroup.kt new file mode 100644 index 000000000..b6386458b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/AbstractServiceGroup.kt @@ -0,0 +1,145 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater + +abstract class AbstractServiceGroup( + private val name: String, + @Volatile private var templateName: String, + @Volatile private var maxMemory: Int, + @Volatile private var maxPlayers: Int, + @Volatile private var minimumOnlineServiceCount: Int, + @Volatile private var maximumOnlineServiceCount: Int, + @Volatile private var maintenance: Boolean, + private val static: Boolean, + @Volatile private var percentToStartNewService: Int, + @Volatile private var wrapperName: String?, + serviceVersion: ServiceVersion, + private val startPriority: Int, + @Volatile private var javaCommandName: String, + @Volatile private var permission: String?, + @Volatile private var stateUpdating: Boolean = true +) : ICloudServiceGroup { + + @Volatile + private var serviceVersion = serviceVersion.name + + override fun getName(): String = this.name + + override fun getPermission(): String? { + return this.permission + } + + override fun setPermission(permission: String?) { + getUpdater().setPermission(permission) + } + + override fun getTemplateName(): String = this.templateName + + override fun setTemplateName(name: String) { + getUpdater().setTemplateName(name) + } + + override fun getMaxMemory(): Int = this.maxMemory + + override fun setMaxMemory(memory: Int) { + getUpdater().setMaxMemory(memory) + } + + override fun getMaxPlayers(): Int = this.maxPlayers + + override fun setMaxPlayers(maxPlayers: Int) { + getUpdater().setMaxPlayers(maxPlayers) + } + + override fun getMinimumOnlineServiceCount(): Int = this.minimumOnlineServiceCount + + override fun setMinimumOnlineServiceCount(count: Int) { + getUpdater().setMinimumOnlineServiceCount(count) + } + + override fun getMaximumOnlineServiceCount(): Int = this.maximumOnlineServiceCount + + override fun setMaximumOnlineServiceCount(count: Int) { + getUpdater().setMaximumOnlineServiceCount(count) + } + + override fun isInMaintenance(): Boolean = this.maintenance + + override fun setMaintenance(maintenance: Boolean) { + getUpdater().setMaintenance(maintenance) + } + + override fun isStatic(): Boolean = this.static + + override fun getJavaCommandName(): String = this.javaCommandName + + override fun getPercentToStartNewService(): Int = this.percentToStartNewService + + override fun setPercentToStartNewService(percentage: Int) { + getUpdater().setPercentToStartNewService(percentage) + } + + override fun getWrapperName(): String? = this.wrapperName + + override fun setWrapperName(name: String?) { + getUpdater().setWrapperName(name) + } + + override fun setServiceVersion(serviceVersion: ServiceVersion) { + getUpdater().setServiceVersion(serviceVersion) + } + + override fun getServiceVersion(): ServiceVersion { + return CloudAPI.instance.getServiceVersionHandler().getServiceVersionByName(serviceVersion)!! + } + + override fun isStateUpdatingEnabled(): Boolean { + return this.stateUpdating + } + + override fun setStateUpdating(stateUpdating: Boolean) { + getUpdater().setStateUpdating(stateUpdating) + } + + override fun getStartPriority(): Int = this.startPriority + + override fun applyValuesFromUpdater(updater: ICloudServiceGroupUpdater) { + this.templateName = updater.getTemplateName() + this.maxMemory = updater.getMaxMemory() + this.maxPlayers = updater.getMaxPlayers() + this.minimumOnlineServiceCount = updater.getMinimumOnlineServiceCount() + this.maximumOnlineServiceCount = updater.getMaximumOnlineServiceCount() + this.maintenance = updater.isInMaintenance() + this.percentToStartNewService = updater.getPercentToStartNewService() + this.wrapperName = updater.getWrapperName() + this.permission = updater.getPermission() + this.stateUpdating = updater.isStateUpdatingEnabled() + this.serviceVersion = updater.getServiceVersion().name + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultLobbyGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultLobbyGroup.kt new file mode 100644 index 000000000..4f4a0044a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultLobbyGroup.kt @@ -0,0 +1,96 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl + +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudLobbyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.updater.ICloudLobbyGroupUpdater +import eu.thesimplecloud.api.servicegroup.impl.updater.DefaultLobbyGroupUpdater +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude + +class DefaultLobbyGroup( + name: String, + templateName: String, + maxMemory: Int, + maxPlayers: Int, + minimumOnlineServiceCount: Int, + maximumOnlineServiceCount: Int, + maintenance: Boolean, + static: Boolean, + percentToStartNewService: Int, + wrapperName: String?, + @Volatile private var priority: Int, + permission: String?, + serviceVersion: ServiceVersion, + startPriority: Int, + javaCommand: String, + hiddenAtProxyGroups: List = emptyList() +) : DefaultServerGroup( + name, + templateName, + maxMemory, + maxPlayers, + minimumOnlineServiceCount, + maximumOnlineServiceCount, + maintenance, + static, + percentToStartNewService, + wrapperName, + serviceVersion, + startPriority, + permission, + javaCommand, + hiddenAtProxyGroups +), ICloudLobbyGroup { + + @Volatile + @JsonLibExclude + @PacketExclude + private var updater: DefaultLobbyGroupUpdater? = DefaultLobbyGroupUpdater(this) + + override fun getPriority(): Int = this.priority + + override fun setPriority(priority: Int) { + getUpdater().setPriority(priority) + } + + override fun getUpdater(): ICloudLobbyGroupUpdater { + if (this.updater == null) { + this.updater = DefaultLobbyGroupUpdater(this) + } + return this.updater!! + } + + override fun applyValuesFromUpdater(updater: ICloudServiceGroupUpdater) { + super.applyValuesFromUpdater(updater) + updater as ICloudLobbyGroupUpdater + this.priority = updater.getPriority() + } + + override fun toString(): String { + return JsonLib.fromObject(this).getAsJsonString() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultProxyGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultProxyGroup.kt new file mode 100644 index 000000000..711c60a46 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultProxyGroup.kt @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl + +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudProxyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.updater.ICloudProxyGroupUpdater +import eu.thesimplecloud.api.servicegroup.impl.updater.DefaultProxyGroupUpdater +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude + +class DefaultProxyGroup( + name: String, + templateName: String, + maxMemory: Int, + maxPlayers: Int, + minimumOnlineServiceCount: Int, + maximumOnlineServiceCount: Int, + maintenance: Boolean, + static: Boolean, + percentToStartNewService: Int, + wrapperName: String?, + @Volatile private var startPort: Int, + serviceVersion: ServiceVersion, + startPriority: Int, + javaCommand: String, + permission: String? +) : AbstractServiceGroup( + name, + templateName, + maxMemory, + maxPlayers, + minimumOnlineServiceCount, + maximumOnlineServiceCount, + maintenance, + static, + percentToStartNewService, + wrapperName, + serviceVersion, + startPriority, + javaCommand, + permission +), ICloudProxyGroup { + + @Volatile + @JsonLibExclude + @PacketExclude + private var updater: DefaultProxyGroupUpdater? = DefaultProxyGroupUpdater(this) + + override fun getStartPort(): Int = this.startPort + + override fun setStartPort(port: Int) { + getUpdater().setStartPort(port) + } + + override fun getUpdater(): ICloudProxyGroupUpdater { + if (this.updater == null) { + this.updater = DefaultProxyGroupUpdater(this) + } + return this.updater!! + } + + override fun applyValuesFromUpdater(updater: ICloudServiceGroupUpdater) { + super.applyValuesFromUpdater(updater) + updater as ICloudProxyGroupUpdater + this.startPort = updater.getStartPort() + } + + override fun toString(): String { + return JsonLib.fromObject(this).getAsJsonString() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultServerGroup.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultServerGroup.kt new file mode 100644 index 000000000..f0e797438 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/DefaultServerGroup.kt @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl + +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.api.servicegroup.impl.updater.DefaultServiceGroupUpdater +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude + +open class DefaultServerGroup( + name: String, + templateName: String, + maxMemory: Int, + maxPlayers: Int, + minimumOnlineServiceCount: Int, + maximumOnlineServiceCount: Int, + maintenance: Boolean, + static: Boolean, + percentToStartNewService: Int, + wrapperName: String?, + serviceVersion: ServiceVersion, + startPriority: Int, + permission: String?, + javaCommand: String, + private val hiddenAtProxyGroups: List = emptyList() +) : AbstractServiceGroup( + name, + templateName, + maxMemory, + maxPlayers, + minimumOnlineServiceCount, + maximumOnlineServiceCount, + maintenance, + static, + percentToStartNewService, + wrapperName, + serviceVersion, + startPriority, + javaCommand, + permission +), ICloudServerGroup { + + @Volatile + @JsonLibExclude + @PacketExclude + private var updater: DefaultServiceGroupUpdater? = null + + override fun getHiddenAtProxyGroups(): List = this.hiddenAtProxyGroups + + override fun getUpdater(): ICloudServiceGroupUpdater { + if (this.updater == null) { + this.updater = DefaultServiceGroupUpdater(this) + } + return this.updater!! + } + + override fun toString(): String { + return JsonLib.fromObject(this).getAsJsonString() + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultLobbyGroupUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultLobbyGroupUpdater.kt new file mode 100644 index 000000000..ab698674b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultLobbyGroupUpdater.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl.updater + +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudLobbyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.updater.ICloudLobbyGroupUpdater + +class DefaultLobbyGroupUpdater(private val lobbyGroup: ICloudLobbyGroup) : DefaultServiceGroupUpdater(lobbyGroup), + ICloudLobbyGroupUpdater { + + override fun getServiceGroup(): ICloudLobbyGroup { + return this.lobbyGroup + } + + override fun getPriority(): Int { + return getChangedValue("priority") ?: lobbyGroup.getPriority() + } + + override fun setPriority(priority: Int) { + changes["priority"] = priority + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultProxyGroupUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultProxyGroupUpdater.kt new file mode 100644 index 000000000..3fd3306b5 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultProxyGroupUpdater.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl.updater + +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudProxyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.updater.ICloudProxyGroupUpdater +import eu.thesimplecloud.jsonlib.JsonLibExclude + +class DefaultProxyGroupUpdater(@JsonLibExclude private val proxyGroup: ICloudProxyGroup) : + DefaultServiceGroupUpdater(proxyGroup), ICloudProxyGroupUpdater { + + override fun getServiceGroup(): ICloudProxyGroup { + return this.proxyGroup + } + + override fun getStartPort(): Int { + return getChangedValue("port") ?: proxyGroup.getStartPort() + } + + override fun setStartPort(port: Int) { + changes["port"] = port + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultServiceGroupUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultServiceGroupUpdater.kt new file mode 100644 index 000000000..cac5dc1f6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/servicegroup/impl/updater/DefaultServiceGroupUpdater.kt @@ -0,0 +1,132 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.servicegroup.impl.updater + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.AbstractCacheValueUpdater +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupUpdater +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.jsonlib.JsonLibExclude + +open class DefaultServiceGroupUpdater( + @JsonLibExclude private val serviceGroup: ICloudServiceGroup +) : AbstractCacheValueUpdater(), ICloudServiceGroupUpdater { + + override fun getServiceGroup(): ICloudServiceGroup { + return this.serviceGroup + } + + override fun update(): ICommunicationPromise { + return CloudAPI.instance.getCloudServiceGroupManager().update(getServiceGroup()) + } + + override fun getTemplateName(): String { + return getChangedValue("templateName") ?: serviceGroup.getTemplateName() + } + + override fun setTemplateName(name: String) { + changes["templateName"] = name + } + + override fun getServiceVersion(): ServiceVersion { + return getChangedValue("serviceVersion") ?: serviceGroup.getServiceVersion() + } + + override fun setServiceVersion(serviceVersion: ServiceVersion) { + changes["serviceVersion"] = serviceVersion + } + + override fun getMaxMemory(): Int { + return getChangedValue("maxMemory") ?: serviceGroup.getMaxMemory() + } + + override fun setMaxMemory(memory: Int) { + changes["maxMemory"] = memory + } + + override fun getMaxPlayers(): Int { + return getChangedValue("maxPlayers") ?: serviceGroup.getMaxPlayers() + } + + override fun setMaxPlayers(maxPlayers: Int) { + changes["maxPlayers"] = maxPlayers + } + + override fun getMinimumOnlineServiceCount(): Int { + return getChangedValue("minimumOnlineServiceCount") ?: serviceGroup.getMinimumOnlineServiceCount() + } + + override fun setMinimumOnlineServiceCount(count: Int) { + changes["minimumOnlineServiceCount"] = count + } + + override fun getMaximumOnlineServiceCount(): Int { + return getChangedValue("maximumOnlineServiceCount") ?: serviceGroup.getMaximumOnlineServiceCount() + } + + override fun setMaximumOnlineServiceCount(count: Int) { + changes["maximumOnlineServiceCount"] = count + } + + override fun isInMaintenance(): Boolean { + return getChangedValue("maintenance") ?: serviceGroup.isInMaintenance() + } + + override fun setMaintenance(maintenance: Boolean) { + changes["maintenance"] = maintenance + } + + override fun getPercentToStartNewService(): Int { + return getChangedValue("percentToStartNewService") ?: serviceGroup.getPercentToStartNewService() + } + + override fun setPercentToStartNewService(percentage: Int) { + changes["percentToStartNewService"] = percentage + } + + override fun getWrapperName(): String? { + return getChangedValue("wrapperName") ?: serviceGroup.getWrapperName() + } + + override fun setWrapperName(name: String?) { + changes["wrapperName"] = name + } + + override fun getPermission(): String? { + return getChangedValue("permission") ?: serviceGroup.getPermission() + } + + override fun setPermission(permission: String?) { + changes["permission"] = permission + } + + override fun isStateUpdatingEnabled(): Boolean { + return getChangedValue("stateUpdating") ?: serviceGroup.isStateUpdatingEnabled() + } + + override fun setStateUpdating(stateUpdating: Boolean) { + changes["stateUpdating"] = stateUpdating + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/AbstractSynchronizedObjectList.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/AbstractSynchronizedObjectList.kt new file mode 100644 index 000000000..de8724bf2 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/AbstractSynchronizedObjectList.kt @@ -0,0 +1,89 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.sync.list + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.sync.list.SynchronizedListObjectRemovedEvent +import eu.thesimplecloud.api.event.sync.list.SynchronizedListObjectUpdatedEvent +import eu.thesimplecloud.api.extension.sendPacketToAllAuthenticatedNonWrapperClients +import eu.thesimplecloud.api.network.packets.sync.list.PacketIORemoveListProperty +import eu.thesimplecloud.api.network.packets.sync.list.PacketIOUpdateListProperty +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.server.INettyServer +import java.util.concurrent.CopyOnWriteArrayList + +abstract class AbstractSynchronizedObjectList( + protected val values: CopyOnWriteArrayList> = CopyOnWriteArrayList() +) : ISynchronizedObjectList { + + + override fun update(property: IProperty, fromPacket: Boolean): ICommunicationPromise { + val cachedValue = getCachedObjectByUpdateValue(property.getValue()) + if (cachedValue == null) { + this.values.add(property as Property) + } else { + if (cachedValue !== property.getValue()) { + cachedValue as Property + cachedValue.resetValue() + cachedValue.setStringValue(property.getValueAsString()) + } + } + if (CloudAPI.instance.isManager() || fromPacket) { + CloudAPI.instance.getEventManager() + .call(SynchronizedListObjectUpdatedEvent(getCachedObjectByUpdateValue(property.getValue())!!)) + } + return forwardPacketIfNecessary(PacketIOUpdateListProperty(getIdentificationName(), property), fromPacket) + } + + override fun getAllCachedObjects(): Collection> = this.values + + override fun remove(property: IProperty, fromPacket: Boolean): ICommunicationPromise { + val cachedObject = getCachedObjectByUpdateValue(property.getValue()) ?: return CommunicationPromise.UNIT_PROMISE + + + if (CloudAPI.instance.isManager() || fromPacket) { + this.values.remove(cachedObject) + CloudAPI.instance.getEventManager().call(SynchronizedListObjectRemovedEvent(cachedObject)) + } + + return forwardPacketIfNecessary(PacketIORemoveListProperty(getIdentificationName(), property), fromPacket) + } + + private fun forwardPacketIfNecessary(packet: IPacket, fromPacket: Boolean): ICommunicationPromise { + if (CloudAPI.instance.isManager()) { + val server = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyServer<*> + return server.getClientManager().sendPacketToAllAuthenticatedNonWrapperClients(packet) + } else if (!fromPacket) { + //send update to the manager + val client = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyClient + return client.getConnection().sendUnitQuery(packet) + } + return CommunicationPromise.UNIT_PROMISE + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/ISynchronizedObjectList.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/ISynchronizedObjectList.kt new file mode 100644 index 000000000..3c541545b --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/ISynchronizedObjectList.kt @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.sync.list + +import eu.thesimplecloud.api.network.packets.sync.list.PacketIOUpdateListProperty +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +interface ISynchronizedObjectList { + + /** + * Returns the unique name to identify this [ISynchronizedObjectList] + */ + fun getIdentificationName(): String + + /** + * Returns all cached objects. + */ + fun getAllCachedObjects(): Collection> + + /** + * Updates an object + */ + fun update(property: IProperty, fromPacket: Boolean = false): ICommunicationPromise + + /** + * Returns the cashed value found by the [value] to update. + */ + fun getCachedObjectByUpdateValue(value: T): IProperty? + + /** + * Removes the [property] object from the cache. + */ + fun remove(property: IProperty, fromPacket: Boolean = false): ICommunicationPromise + + /** + * Sends an update to one connection + * @return the a promise that completes when the packet was handled. + */ + fun updateToConnection(property: IProperty<*>, connection: IConnection): ICommunicationPromise { + return connection.sendUnitQuery(PacketIOUpdateListProperty(getIdentificationName(), property)) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/ISynchronizedObjectListManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/ISynchronizedObjectListManager.kt new file mode 100644 index 000000000..184a0de05 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/ISynchronizedObjectListManager.kt @@ -0,0 +1,71 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.sync.list.manager + +import eu.thesimplecloud.api.network.packets.sync.list.PacketIOUpdateListProperty +import eu.thesimplecloud.api.sync.list.ISynchronizedObjectList +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.combineAllPromises + +interface ISynchronizedObjectListManager { + + /** + * Registers a synchronized object list linked to the objects name + * @return a promise that completes when the list was synchronized. + */ + fun registerSynchronizedObjectList( + synchronizedObjectList: ISynchronizedObjectList, + syncContent: Boolean = true + ): ICommunicationPromise + + /** + * Returns the [ISynchronizedObjectList] found by the specified [name] + */ + fun getSynchronizedObjectList(name: String): ISynchronizedObjectList? + + /** + * Removes the [ISynchronizedObjectList] registered to the specified [name] + */ + fun unregisterSynchronizedObjectList(name: String) + + /** + * Synchronizes the content of a [ISynchronizedObjectList] with the specified [connection] + */ + fun synchronizeListWithConnection( + synchronizedObjectList: ISynchronizedObjectList, + connection: IConnection + ): ICommunicationPromise { + return synchronizedObjectList.getAllCachedObjects() + .map { + connection.sendUnitQuery( + PacketIOUpdateListProperty( + synchronizedObjectList.getIdentificationName(), + it + ) + ) + } + .combineAllPromises() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/SynchronizedObjectListManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/SynchronizedObjectListManager.kt new file mode 100644 index 000000000..cbf164f03 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/list/manager/SynchronizedObjectListManager.kt @@ -0,0 +1,74 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.sync.list.manager + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.network.packets.sync.list.PacketIOGetAllCachedListProperties +import eu.thesimplecloud.api.sync.list.ISynchronizedObjectList +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.combineAllPromises + +class SynchronizedObjectListManager : ISynchronizedObjectListManager { + + private val nameToSynchronizedObjectList = Maps.newConcurrentMap>() + + + override fun registerSynchronizedObjectList( + synchronizedObjectList: ISynchronizedObjectList, + syncContent: Boolean + ): ICommunicationPromise { + if (syncContent && CloudAPI.instance.isManager()) { + val oldObject = getSynchronizedObjectList(synchronizedObjectList.getIdentificationName()) + oldObject?.let { oldList -> + oldList.getAllCachedObjects().map { oldList.remove(it) }.combineAllPromises().awaitUninterruptibly() + } + } + this.nameToSynchronizedObjectList[synchronizedObjectList.getIdentificationName()] = synchronizedObjectList + if (syncContent) { + if (!CloudAPI.instance.isManager()) { + val client = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyClient + return client.getConnection() + .sendUnitQuery( + PacketIOGetAllCachedListProperties(synchronizedObjectList.getIdentificationName()), + 4000 + ).syncUninterruptibly() + } else { + //manager + synchronizedObjectList as ISynchronizedObjectList + synchronizedObjectList.getAllCachedObjects().forEach { synchronizedObjectList.update(it) } + } + } + return CommunicationPromise.of(Unit) + } + + override fun getSynchronizedObjectList(name: String): ISynchronizedObjectList? = + this.nameToSynchronizedObjectList[name] as ISynchronizedObjectList? + + override fun unregisterSynchronizedObjectList(name: String) { + this.nameToSynchronizedObjectList.remove(name) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/GlobalPropertyHolder.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/GlobalPropertyHolder.kt new file mode 100644 index 000000000..f6614b0e8 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/GlobalPropertyHolder.kt @@ -0,0 +1,129 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.sync.`object` + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.sync.`object`.GlobalPropertyUpdatedEvent +import eu.thesimplecloud.api.network.packets.sync.`object`.PacketIOGetGlobalProperty +import eu.thesimplecloud.api.network.packets.sync.`object`.PacketIORemoveGlobalProperty +import eu.thesimplecloud.api.network.packets.sync.`object`.PacketIOUpdateGlobalProperty +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.concurrent.CopyOnWriteArraySet + +class GlobalPropertyHolder : IGlobalPropertyHolder { + + private val propertyNameToUpdateClient = Maps.newConcurrentMap>() + + private val nameToValue: MutableMap> = Maps.newConcurrentMap() + + fun addConnectionToUpdates(propertyName: String, connection: IConnection) { + val list = this.propertyNameToUpdateClient.getOrPut(propertyName) { CopyOnWriteArraySet() } + list.add(connection) + } + + fun removeConnectionFromUpdates(connection: IConnection) { + this.propertyNameToUpdateClient.values.forEach { it.remove(connection) } + } + + override fun getProperties(): Map> { + return this.nameToValue + } + + override fun setProperty(name: String, value: T): IProperty { + val newProperty = Property(value) + writeUpdateToMap(name, newProperty) + updatePropertyToNetwork(name, newProperty) + return newProperty + } + + override fun clearProperties() { + throw UnsupportedOperationException("Cannot clear global properties") + } + + override fun removeProperty(name: String) { + this.nameToValue.remove(name) + removePropertyFromNetwork(name) + } + + override fun requestProperty(name: String): ICommunicationPromise> { + if (CloudAPI.instance.isManager()) throw UnsupportedOperationException("Cannot request properties from manager") + val client = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyClient + return client.getConnection().sendQuery>(PacketIOGetGlobalProperty(name), 5000) + .addResultListener { updatePropertyFromPacket(name, it) } + } + + fun updatePropertyFromPacket(name: String, property: IProperty<*>) { + writeUpdateToMap(name, property) + CloudAPI.instance.getEventManager().call(GlobalPropertyUpdatedEvent(name, property)) + + if (CloudAPI.instance.isManager()) + updatePropertyToNetwork(name, property) + } + + fun removePropertyFromPacket(name: String) { + this.nameToValue.remove(name) + + if (CloudAPI.instance.isManager()) + removePropertyFromNetwork(name) + } + + private fun writeUpdateToMap(name: String, property: IProperty<*>) { + val cachedProperty = this.nameToValue[name] + if (cachedProperty == null) { + this.nameToValue[name] = property + return + } + cachedProperty as Property<*> + cachedProperty.setStringValue(property.getValueAsString()) + cachedProperty.resetValue() + } + + private fun updatePropertyToNetwork(name: String, property: IProperty<*>) { + val updatePacket = PacketIOUpdateGlobalProperty(name, property) + forwardPacket(name, updatePacket) + } + + private fun removePropertyFromNetwork(name: String) { + val updatePacket = PacketIORemoveGlobalProperty(name) + forwardPacket(name, updatePacket) + } + + private fun forwardPacket(name: String, packet: IPacket) { + if (CloudAPI.instance.isManager()) { + this.propertyNameToUpdateClient[name]?.forEach { + it.sendUnitQuery(packet) + } + } else { + val client = CloudAPI.instance.getThisSidesCommunicationBootstrap() as INettyClient + client.getConnection().sendUnitQuery(packet) + } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/IGlobalPropertyHolder.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/IGlobalPropertyHolder.kt new file mode 100644 index 000000000..ad3379962 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/sync/object/IGlobalPropertyHolder.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.sync.`object` + +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.IPropertyMap +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +interface IGlobalPropertyHolder : IPropertyMap { + + /** + * Returns a [ICommunicationPromise] that completes once the requested [IProperty] is available. + */ + fun requestProperty(name: String): ICommunicationPromise> +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplate.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplate.kt new file mode 100644 index 000000000..88f9ca1f6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplate.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template + +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +interface ITemplate : ICacheValue, ITemplateVariables { + + /** + * Returns the name of this template. + */ + fun getName(): String + + /** + * Returns the directory of this template. + */ + fun getDirectory(): File = File(DirectoryPaths.paths.templatesPath + getName() + "/") + + /** + * Updates this template + */ + fun update() = getUpdater().update() +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateManager.kt new file mode 100644 index 000000000..64681cdc7 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateManager.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template + +import eu.thesimplecloud.api.cachelist.ICacheList + + +interface ITemplateManager : ICacheList { + + /** + * Removes the template found by the specified name + */ + fun deleteTemplate(name: String) + + /** + * Returns the first template found by the specified name + */ + fun getTemplateByName(name: String): ITemplate? = + getAllCachedObjects().firstOrNull { it.getName().equals(name, true) } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateUpdater.kt new file mode 100644 index 000000000..453ae8e0d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateUpdater.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template + +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater + +/** + * Created by IntelliJ IDEA. + * Date: 23.01.2021 + * Time: 21:28 + * @author Frederick Baier + */ +interface ITemplateUpdater : ICacheValueUpdater, ITemplateVariables { + + fun getTemplate(): ITemplate + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateVariables.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateVariables.kt new file mode 100644 index 000000000..4f5155779 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/ITemplateVariables.kt @@ -0,0 +1,71 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template + +import eu.thesimplecloud.api.CloudAPI + +/** + * Created by IntelliJ IDEA. + * Date: 23.01.2021 + * Time: 22:19 + * @author Frederick Baier + */ +interface ITemplateVariables { + + /** + * Returns the names of all templates this group inherits from. + */ + fun getInheritedTemplateNames(): Set + + /** + * Adds a template as inherited + */ + fun addInheritanceTemplate(template: ITemplate) + + /** + * Removes a template from the list of inherited templates + */ + fun removeInheritanceTemplate(template: ITemplate) + + /** + * Returns all templates this group inherits from. + */ + fun inheritedTemplates(): List = + getInheritedTemplateNames().mapNotNull { CloudAPI.instance.getTemplateManager().getTemplateByName(it) } + + /** + * Adds the specified name to the list of all module names, this template shall copy in the plugins directory of a service. + */ + fun addModuleNameToCopy(name: String) + + /** + * Removes the specified name from the list of all module names, this template shall copy in the plugins directory of a service. + */ + fun removeModuleNameToCopy(name: String) + + /** + * Returns a list of names of all modules, this template shall copy in the plugins directory of a service. + */ + fun getModuleNamesToCopy(): Set + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplate.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplate.kt new file mode 100644 index 000000000..0f2528a48 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplate.kt @@ -0,0 +1,78 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template.impl + +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.template.ITemplateUpdater +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.JsonLibExclude + +data class DefaultTemplate(private val name: String) : ITemplate { + + @Volatile + private var inheritedTemplateNames: Set = emptySet() + + @Volatile + private var moduleNamesToCopy: Set = emptySet() + + @PacketExclude + @JsonLibExclude + @Volatile + private var templateUpdater: DefaultTemplateUpdater? = DefaultTemplateUpdater(this) + + override fun getName(): String = this.name + + override fun getInheritedTemplateNames(): Set = this.inheritedTemplateNames + + override fun addInheritanceTemplate(template: ITemplate) { + getUpdater().addInheritanceTemplate(template) + } + + override fun removeInheritanceTemplate(template: ITemplate) { + getUpdater().removeInheritanceTemplate(template) + } + + override fun addModuleNameToCopy(name: String) { + getUpdater().addModuleNameToCopy(name) + } + + override fun removeModuleNameToCopy(name: String) { + getUpdater().removeModuleNameToCopy(name) + } + + override fun getModuleNamesToCopy(): Set = this.moduleNamesToCopy + + override fun getUpdater(): ITemplateUpdater { + if (this.templateUpdater == null) { + this.templateUpdater = DefaultTemplateUpdater(this) + } + return this.templateUpdater!! + } + + override fun applyValuesFromUpdater(updater: ITemplateUpdater) { + this.inheritedTemplateNames = HashSet(updater.getInheritedTemplateNames()) + this.moduleNamesToCopy = HashSet(updater.getModuleNamesToCopy()) + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateManager.kt new file mode 100644 index 000000000..bb021ad55 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateManager.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template.impl + +import eu.thesimplecloud.api.cachelist.AbstractCacheList +import eu.thesimplecloud.api.cachelist.ICacheObjectUpdateExecutor +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.template.ITemplateManager +import eu.thesimplecloud.api.template.ITemplateUpdater + +open class DefaultTemplateManager : AbstractCacheList(), ITemplateManager { + + private val updater = object : ICacheObjectUpdateExecutor { + override fun getIdentificationName(): String { + return "template-cache" + } + + override fun getCachedObjectByUpdateValue(value: ITemplate): ITemplate? { + return getTemplateByName(value.getName()) + } + + override fun determineEventsToCall(updater: ITemplateUpdater, cachedValue: ITemplate?): List { + return emptyList() + } + + override fun addNewValue(value: ITemplate) { + values.add(value) + } + + } + + override fun deleteTemplate(name: String) { + getTemplateByName(name)?.let { this.delete(it) } + } + + override fun getUpdateExecutor(): ICacheObjectUpdateExecutor { + return this.updater + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateUpdater.kt new file mode 100644 index 000000000..d8a97506a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/template/impl/DefaultTemplateUpdater.kt @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.template.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.template.ITemplateUpdater +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.concurrent.ConcurrentHashMap + +/** + * Created by IntelliJ IDEA. + * Date: 23.01.2021 + * Time: 21:32 + * @author Frederick Baier + */ +class DefaultTemplateUpdater( + private val template: ITemplate +) : ITemplateUpdater { + + @Volatile + private var inheritedTemplateNames: MutableSet = ConcurrentHashMap.newKeySet() + + @Volatile + private var moduleNamesToCopy: MutableSet = ConcurrentHashMap.newKeySet() + + override fun getTemplate(): ITemplate { + return template + } + + override fun update(): ICommunicationPromise { + return CloudAPI.instance.getTemplateManager().update(template) + } + + override fun getInheritedTemplateNames(): Set { + return this.inheritedTemplateNames + } + + override fun addInheritanceTemplate(template: ITemplate) { + removeInheritanceTemplate(template) + this.inheritedTemplateNames.add(template.getName()) + } + + override fun removeInheritanceTemplate(template: ITemplate) { + this.inheritedTemplateNames.removeIf { it.equals(template.getName(), true) } + } + + override fun addModuleNameToCopy(name: String) { + removeModuleNameToCopy(name) + this.moduleNamesToCopy.add(name) + } + + override fun removeModuleNameToCopy(name: String) { + this.moduleNamesToCopy.removeIf { it.equals(name, true) } + } + + override fun getModuleNamesToCopy(): Set { + return this.moduleNamesToCopy + } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ClassExtension.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ClassExtension.kt new file mode 100644 index 000000000..1c37c9ad2 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ClassExtension.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import java.lang.reflect.Field + +fun Class<*>.getAllFieldsFromClassAndSubClasses(): Set { + val fields = this.declaredFields.toSet() + if (this.superclass != null) + return fields.union(this.superclass.getAllFieldsFromClassAndSubClasses()) + return fields +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ConfigurationFileEditor.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ConfigurationFileEditor.kt new file mode 100644 index 000000000..288edf9e8 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ConfigurationFileEditor.kt @@ -0,0 +1,118 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import java.io.File +import java.nio.charset.StandardCharsets + +/** + * Created by IntelliJ IDEA. + * Date: 16.06.2021 + * Time: 09:26 + * @author Frederick Baier + * + * A simple file editor to edit configuration files + * @param lines the lines of the files (all spaces at the beginning of lines will be cut off) + * @param keyValueSplitter the splitter of name and value. For YML it would be ": " + * + */ +class ConfigurationFileEditor( + private val linesWithSpaces: List, + private val keyValueSplitter: String +) { + + constructor(file: File, keyValueSplitter: String) : this(file.readLines(StandardCharsets.UTF_8), keyValueSplitter) + + private val lines = this.linesWithSpaces.map { removeFirstSpaces(it) } + + private val keyToValues = HashMap(getKeyToValueMapByLines(this.lines)) + + private fun getKeyToValueMapByLines(lines: List): Map { + val keyValueSplitArrays = lines.filter { it.contains(keyValueSplitter) }.map { it.split(keyValueSplitter) } + return keyValueSplitArrays.map { it[0] to (it.getOrNull(1) ?: "") }.toMap() + } + + fun getValue(key: String): String? { + return this.keyToValues[key] + } + + fun setValue(key: String, value: String) { + if (!this.keyToValues.containsKey(key)) throw IllegalStateException("Key '${key}' does not exist") + this.keyToValues[key] = value + } + + fun saveToFile(file: File) { + val linesToSave = generateNewLines() + file.writeText(linesToSave.joinToString("\n")) + } + + private fun generateNewLines(): List { + val mutableLines = ArrayList(this.linesWithSpaces) + for ((key, value) in this.keyToValues) { + val lineIndex = getLineIndexByKey(key) + val newLine = constructNewLine(key, value, lineIndex) + mutableLines[lineIndex] = newLine + } + return mutableLines + } + + private fun constructNewLine(key: String, value: String, lineIndex: Int): String { + val lineWithoutSpaces = key + this.keyValueSplitter + value + val amountOfStartSpaces = getAmountOfStartSpacesInLine(this.linesWithSpaces[lineIndex]) + val spacesString = getStringWithSpaces(amountOfStartSpaces) + return spacesString + lineWithoutSpaces + } + + private fun getStringWithSpaces(amount: Int): String { + return (0 until amount).joinToString("") { " " } + } + + private fun removeFirstSpaces(string: String): String { + val amountOfSpaces = getAmountOfStartSpacesInLine(string) + return string.drop(amountOfSpaces) + } + + private fun getAmountOfStartSpacesInLine(line: String): Int { + var line = line + var amountOfSPaces = 0 + while (line.startsWith(" ")) { + line = line.drop(1) + amountOfSPaces++ + } + return amountOfSPaces + } + + private fun getLineIndexByKey(key: String): Int { + val lineStart = key + this.keyValueSplitter + val line = lines.firstOrNull { it.startsWith(lineStart) } ?: return -1 + return this.lines.indexOf(line) + } + + companion object { + const val YAML_SPLITTER = ": " + const val PROPERTIES_SPLITTER = "=" + const val TOML_SPLITTER = " = " + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/DatabaseExclude.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/DatabaseExclude.kt new file mode 100644 index 000000000..5936fb218 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/DatabaseExclude.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +/** + * Created by IntelliJ IDEA. + * Date: 17.06.2020 + * Time: 09:47 + * @author Frederick Baier + */ +/** + * Fields annotated with this annotation will not be saved in the database + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FIELD) +annotation class DatabaseExclude \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/EnumExtension.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/EnumExtension.kt new file mode 100644 index 000000000..6a03e33b9 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/EnumExtension.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +fun Class>.getEnumValues(): List { + val method = this.getMethod("values") + val values = method.invoke(null) as Array> + return values.map { it.name } +} + +fun > Class.enumValueOf(string: String): T { + val method = this.getMethod("valueOf", String::class.java) + return method.invoke(null, string) as T +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/FileFinder.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/FileFinder.kt new file mode 100644 index 000000000..901f4fcb6 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/FileFinder.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import org.apache.commons.io.FileUtils +import org.apache.commons.io.filefilter.IOFileFilter +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 09.06.2020 + * Time: 15:47 + * @author Frederick Baier + */ +object FileFinder { + + fun getAllFiles(directory: File): List { + if (!directory.exists()) return emptyList() + val acceptAllFilter = object : IOFileFilter { + override fun accept(file: File?): Boolean { + return true + } + + override fun accept(dir: File?, name: String?): Boolean { + return true + } + } + return FileUtils.listFilesAndDirs(directory, acceptAllFilter, acceptAllFilter) + .filter { !it.isDirectory } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ManifestLoader.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ManifestLoader.kt new file mode 100644 index 000000000..406441076 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ManifestLoader.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import java.io.File +import java.util.jar.JarFile + + +class ManifestLoader { + + companion object { + fun getMainClassFromManifestFile(file: File): String { + val jarFile = JarFile(file) + val version = jarFile.manifest.mainAttributes.getValue("Main-Class") + jarFile.close() + return version + } + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/Nameable.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/Nameable.kt new file mode 100644 index 000000000..b5ab2d1a1 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/Nameable.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +interface Nameable { + + /** + * Returns the name of this object. + */ + fun getName(): String + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/NoArgsFunction.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/NoArgsFunction.kt new file mode 100644 index 000000000..bb2e5c170 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/NoArgsFunction.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import java.io.Serializable + +@FunctionalInterface +interface NoArgsFunction : Serializable { + + /** + * Represents a function that needs no parameters and returns the type [R] + */ + operator fun invoke(): R + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ObjectSerializer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ObjectSerializer.kt new file mode 100644 index 000000000..973b4510d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ObjectSerializer.kt @@ -0,0 +1,69 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.ObjectInputStream +import java.io.ObjectOutputStream + +object ObjectSerializer { + + /** + * Serialize given object into [String] using [ObjectOutputStream]. + * @param obj object to serialize + * @see ObjectInputStream + * @return the serialization result, empty string for _null_ input + */ + fun serialize(obj: T?): String { + if (obj == null) { + return "" + } + + val baos = ByteArrayOutputStream() + val oos = ObjectOutputStream(baos) + oos.writeObject(obj) + oos.close() + + return baos.toString("ISO-8859-1") + } + + /** + * Deserialize given [String] using [ObjectInputStream]. + * @param string the string to deserialize + * @return deserialized object, null, in case of error. + */ + fun deserialize(string: String): T? { + if (string.isEmpty()) { + return null + } + + var bais = ByteArrayInputStream(string.toByteArray(charset("ISO-8859-1"))) + var ois = ObjectInputStream(bais) + + return ois.readObject() as T + } + + fun deserialize(string: String, clazz: Class): T? = deserialize(string) + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/StringIterableExtension.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/StringIterableExtension.kt new file mode 100644 index 000000000..26425884a --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/StringIterableExtension.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 21:03 + * @author Frederick Baier + */ + +fun Iterable.containsIgnoreCase(element: String): Boolean { + return this.any { it.equals(element, true) } +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ZipUtils.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ZipUtils.kt new file mode 100644 index 000000000..08e226593 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/ZipUtils.kt @@ -0,0 +1,79 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils + +import java.io.File +import java.net.URI +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.Path +import java.util.zip.ZipFile + + +class ZipUtils { + + fun deletePath(file: File, path: String) { + val env = HashMap() + env["create"] = "true" + env["encoding"] = "UTF-8" + + val zipFile = ZipFile(file) + val entries = zipFile.entries() + val uri = URI.create("jar:" + file.toURI().toString()) + val fileSystem = FileSystems.newFileSystem(uri, env) + while (entries.hasMoreElements()) { + val nextElement = entries.nextElement() + if (nextElement.name.startsWith(path) && !nextElement.isDirectory) { + val pathInZipfile: Path = fileSystem.getPath(nextElement.name) + Files.delete(pathInZipfile) + } + } + zipFile.close() + fileSystem.close() + + } + + fun hasPath(file: File, path: String): Boolean { + val env = HashMap() + env["create"] = "true" + env["encoding"] = "UTF-8" + + val zipFile = ZipFile(file) + val entries = zipFile.entries() + val uri = URI.create("jar:" + file.toURI().toString()) + val fileSystem = FileSystems.newFileSystem(uri, env) + while (entries.hasMoreElements()) { + val nextElement = entries.nextElement() + if (nextElement.name.startsWith(path) && !nextElement.isDirectory) { + zipFile.close() + fileSystem.close() + return true + } + } + zipFile.close() + fileSystem.close() + return false + } + +} + diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/TimeAmountMeasurer.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/TimeAmountMeasurer.kt new file mode 100644 index 000000000..cbc71c50d --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/TimeAmountMeasurer.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils.time + +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 19:02 + * @author Frederick Baier + */ +class TimeAmountMeasurer( + private val expireTimeInMs: Long +) { + + private val timeStamps = CopyOnWriteArrayList() + + fun addEntry() { + this.timeStamps.removeIf { it.hasTimePassed(expireTimeInMs) } + this.timeStamps.add(Timestamp()) + } + + fun getMeasuredAmount(): Int { + return this.timeStamps.count { !it.hasTimePassed(expireTimeInMs) } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/Timestamp.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/Timestamp.kt new file mode 100644 index 000000000..1769ef3b8 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/utils/time/Timestamp.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.utils.time + +/** + * Created by IntelliJ IDEA. + * Date: 27.09.2020 + * Time: 13:56 + * @author Frederick Baier + */ +data class Timestamp( + val time: Long = System.currentTimeMillis() +) { + + fun isAfter(timestamp: Timestamp): Boolean { + return !isBefore(timestamp) + } + + fun isBefore(timestamp: Timestamp): Boolean { + return this.time < timestamp.time + } + + fun hasTimePassed(timeInMillis: Long): Boolean { + return getTimePassed() > timeInMillis + } + + fun getTimeLeftTo(timestamp: Timestamp): Long { + return timestamp.time - this.time + } + + fun getTimePassed(): Long { + return System.currentTimeMillis() - this.time + } + + companion object { + fun createTimeStampFromNow(additionalTime: Long): Timestamp { + return Timestamp(System.currentTimeMillis() + additionalTime) + } + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfo.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfo.kt new file mode 100644 index 000000000..5c2139234 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfo.kt @@ -0,0 +1,94 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.wrapper + + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.ICacheValue +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.service.ICloudService + + +interface IWrapperInfo : ICacheValue, INetworkComponent { + + /** + * Returns the host of this wrapper. + */ + fun getHost(): String + + /** + * Returns the amount of services this wrapper can start simultaneously + */ + fun getMaxSimultaneouslyStartingServices(): Int + + /** + * Returns the amount of RAM the wrapper uses at the moment in MB + */ + fun getUsedMemory(): Int + + /** + * Returns the amount of RAM this wrapper has at maximum + */ + fun getMaxMemory(): Int + + /** + * Returns the CPU usage of this wrapper. + * The returned value will be between 0 - 1 + */ + fun getCpuUsage(): Float + + /** + * Returns the amount of RAM the wrapper has left + */ + fun getUnusedMemory(): Int { + return getMaxMemory() - getUsedMemory() + } + + /** + * Returns whether this wrapper has the specified memory left + */ + fun hasEnoughMemory(memory: Int): Boolean { + return getUnusedMemory() >= memory + } + + /** + * Returns whether the wrapper has received the templates. + */ + fun hasTemplatesReceived(): Boolean + + /** + * Returns the amount of services this wrapper is currently starting + */ + fun getCurrentlyStartingServices(): Int + + /** + * Returns a list of services running on this wrapper + */ + fun getServicesRunningOnThisWrapper(): List { + return CloudAPI.instance.getCloudServiceManager().getServicesRunningOnWrapper(getName()) + } + + override fun getNetworkComponentType(): NetworkComponentType = NetworkComponentType.WRAPPER + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfoUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfoUpdater.kt new file mode 100644 index 000000000..cc755b067 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperInfoUpdater.kt @@ -0,0 +1,92 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.wrapper + +import eu.thesimplecloud.api.cachelist.value.ICacheValueUpdater +import eu.thesimplecloud.api.network.component.IAuthenticatable + +interface IWrapperInfoUpdater : ICacheValueUpdater, IAuthenticatable { + + fun getWrapperInfo(): IWrapperInfo + + /** + * Sets the amount of services this wrapper can start simultaneously + */ + fun setMaxSimultaneouslyStartingServices(amount: Int) + + /** + * Returns the amount of services this wrapper can start simultaneously + */ + fun getMaxSimultaneouslyStartingServices(): Int + + /** + * Sets the maximum MB of RAM for this wrapper + */ + fun setMaxMemory(memory: Int) + + /** + * Returns the maximum MB of RAM for this wrapper + */ + fun getMaxMemory(): Int + + /** + * Sets the amount of RAM in MB the wrapper currently uses + */ + fun setUsedMemory(memory: Int) + + /** + * Return the amount of RAM in MB the wrapper currently uses + */ + fun getUsedMemory(): Int + + /** + * Sets the CPU usage of this wrapper + */ + fun setCpuUsage(usage: Float) + + /** + * Returns the CPU usage of this wrapper + */ + fun getCpuUsage(): Float + + /** + * Sets whether the wrapper has received the templates + */ + fun setTemplatesReceived(boolean: Boolean) + + /** + * Returns whether the wrapper has received the templates + */ + fun hasTemplatesReceived(): Boolean + + /** + * Sets the amount of services this wrapper is currently starting + */ + fun setCurrentlyStartingServices(startingServices: Int) + + /** + * Return the amount of services this wrapper is currently starting + */ + fun getCurrentlyStartingServices(): Int + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperManager.kt new file mode 100644 index 000000000..15a052bb4 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/IWrapperManager.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.wrapper + +import eu.thesimplecloud.api.cachelist.ICacheList + + +interface IWrapperManager : ICacheList { + + /** + * Returns the [IWrapperInfo] found by the specified name + */ + fun getWrapperByName(name: String): IWrapperInfo? = + getAllCachedObjects().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns the [IWrapperInfo] found by the specified host + */ + fun getWrapperByHost(host: String): IWrapperInfo? = + getAllCachedObjects().firstOrNull { it.getHost().equals(host, true) } + + /** + * Returns the [IWrapperInfo] that has enough memory, is authenticated and has received all templates. + */ + fun getWrapperByUnusedMemory(memory: Int): IWrapperInfo? { + val wrappers = getAllCachedObjects() + .filter { it.isAuthenticated() && it.hasTemplatesReceived() && it.hasEnoughMemory(memory) } + .filter { it.getCurrentlyStartingServices() != it.getMaxSimultaneouslyStartingServices() } + return wrappers.minByOrNull { it.getUsedMemory().toDouble() / it.getMaxMemory() } + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfo.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfo.kt new file mode 100644 index 000000000..f5eaba0e5 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfo.kt @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.wrapper.impl + +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.api.wrapper.IWrapperInfoUpdater +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.GsonCreator +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.jsonlib.JsonLibExclude + +data class DefaultWrapperInfo( + private val name: String, + private val host: String, + @Volatile private var maxSimultaneouslyStartingServices: Int, + @Volatile private var maxMemory: Int +) : IWrapperInfo { + + @JsonLibExclude + @PacketExclude + @Volatile + private var wrapperUpdater: DefaultWrapperInfoUpdater? = DefaultWrapperInfoUpdater(this) + + @JsonLibExclude + @Volatile + private var authenticated = false + + @JsonLibExclude + @Volatile + private var usedMemory: Int = 0 + + @JsonLibExclude + @Volatile + private var templatesReceived = false + + @JsonLibExclude + @Volatile + private var currentlyStartingServices = 0 + + @JsonLibExclude + @Volatile + private var cpuUsage = 0.0F + + override fun setAuthenticated(authenticated: Boolean) { + getUpdater().setAuthenticated(authenticated) + } + + override fun getName(): String = this.name + + override fun getHost(): String = this.host + + override fun getMaxSimultaneouslyStartingServices(): Int = this.maxSimultaneouslyStartingServices + + override fun getUsedMemory(): Int = this.usedMemory + + override fun getMaxMemory(): Int = this.maxMemory + + override fun getCpuUsage(): Float { + return this.cpuUsage + } + + override fun isAuthenticated(): Boolean = this.authenticated + + override fun hasTemplatesReceived(): Boolean = this.templatesReceived + + override fun getCurrentlyStartingServices(): Int = this.currentlyStartingServices + + override fun getUpdater(): IWrapperInfoUpdater { + if (this.wrapperUpdater == null) { + this.wrapperUpdater = DefaultWrapperInfoUpdater(this) + } + return this.wrapperUpdater ?: throw NullPointerException("WrapperUpdater was null") + } + + override fun applyValuesFromUpdater(updater: IWrapperInfoUpdater) { + this.cpuUsage = updater.getCpuUsage() + this.maxMemory = updater.getMaxMemory() + this.usedMemory = updater.getUsedMemory() + + this.currentlyStartingServices = updater.getCurrentlyStartingServices() + this.maxSimultaneouslyStartingServices = updater.getMaxSimultaneouslyStartingServices() + + this.templatesReceived = updater.hasTemplatesReceived() + this.authenticated = updater.isAuthenticated() + } + + override fun toString(): String { + val gson = GsonCreator().excludeAnnotations(PacketExclude::class.java).create() + return JsonLib.fromObject(this, gson).getAsJsonString() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfoUpdater.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfoUpdater.kt new file mode 100644 index 000000000..1c9837fd2 --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperInfoUpdater.kt @@ -0,0 +1,99 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.wrapper.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.value.AbstractCacheValueUpdater +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.api.wrapper.IWrapperInfoUpdater +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class DefaultWrapperInfoUpdater( + private val wrapperInfo: IWrapperInfo +) : AbstractCacheValueUpdater(), IWrapperInfoUpdater { + + override fun getWrapperInfo(): IWrapperInfo { + return wrapperInfo + } + + override fun setMaxSimultaneouslyStartingServices(amount: Int) { + changes["simultaneouslyStartingServices"] = amount + } + + override fun getMaxSimultaneouslyStartingServices(): Int { + return getChangedValue("simultaneouslyStartingServices") ?: wrapperInfo.getMaxSimultaneouslyStartingServices() + } + + override fun setMaxMemory(memory: Int) { + changes["maxMemory"] = memory + } + + override fun getMaxMemory(): Int { + return getChangedValue("maxMemory") ?: wrapperInfo.getMaxMemory() + } + + override fun setUsedMemory(memory: Int) { + changes["usedMemory"] = memory + } + + override fun getUsedMemory(): Int { + return getChangedValue("usedMemory") ?: wrapperInfo.getUsedMemory() + } + + override fun setCpuUsage(usage: Float) { + changes["cpuUsage"] = usage + } + + override fun getCpuUsage(): Float { + return getChangedValue("cpuUsage") ?: wrapperInfo.getCpuUsage() + } + + override fun setTemplatesReceived(boolean: Boolean) { + changes["templatesReceived"] = boolean + } + + override fun hasTemplatesReceived(): Boolean { + return getChangedValue("templatesReceived") ?: wrapperInfo.hasTemplatesReceived() + } + + override fun setCurrentlyStartingServices(startingServices: Int) { + changes["currentlyStartingServices"] = startingServices + } + + override fun getCurrentlyStartingServices(): Int { + return getChangedValue("currentlyStartingServices") ?: wrapperInfo.getCurrentlyStartingServices() + } + + override fun setAuthenticated(authenticated: Boolean) { + changes["authenticated"] = authenticated + } + + override fun isAuthenticated(): Boolean { + return getChangedValue("authenticated") ?: wrapperInfo.isAuthenticated() + } + + override fun update(): ICommunicationPromise { + return CloudAPI.instance.getWrapperManager().update(wrapperInfo) + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperManager.kt b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperManager.kt new file mode 100644 index 000000000..3347c3dcf --- /dev/null +++ b/simplecloud-api/src/main/kotlin/eu/thesimplecloud/api/wrapper/impl/DefaultWrapperManager.kt @@ -0,0 +1,71 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.wrapper.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.cachelist.AbstractCacheList +import eu.thesimplecloud.api.cachelist.ICacheObjectUpdateExecutor +import eu.thesimplecloud.api.event.wrapper.WrapperUpdatedEvent +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.api.wrapper.IWrapperInfoUpdater +import eu.thesimplecloud.api.wrapper.IWrapperManager +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +open class DefaultWrapperManager : AbstractCacheList(), IWrapperManager { + + private val updateLifecycle = object : ICacheObjectUpdateExecutor { + + override fun getCachedObjectByUpdateValue(value: IWrapperInfo): IWrapperInfo? { + return getWrapperByName(value.getName()) + } + + override fun determineEventsToCall(updater: IWrapperInfoUpdater, cachedValue: IWrapperInfo?): List { + val wrapperToUse = cachedValue ?: updater.getWrapperInfo() + return listOf(WrapperUpdatedEvent(wrapperToUse)) + } + + override fun addNewValue(value: IWrapperInfo) { + values.add(value) + } + + override fun getIdentificationName(): String { + return "wrapper-cache" + } + + } + + override fun getUpdateExecutor(): ICacheObjectUpdateExecutor { + return this.updateLifecycle + } + + override fun delete(value: IWrapperInfo, fromPacket: Boolean): ICommunicationPromise { + if (value.getServicesRunningOnThisWrapper().isNotEmpty()) + throw IllegalStateException("Cannot delete wrapper while services are still running on this wrapper") + if (CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupsByWrapperName(value.getName()).isNotEmpty()) + throw IllegalStateException("Cannot delete wrapper while groups are only able to start on this wrapper") + return super.delete(value, fromPacket) + } + + +} \ No newline at end of file diff --git a/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/AdvancedListenerTest.kt b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/AdvancedListenerTest.kt new file mode 100644 index 000000000..e3346fcf6 --- /dev/null +++ b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/AdvancedListenerTest.kt @@ -0,0 +1,96 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.player.CloudPlayerLoginEvent +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.listenerextension.cloudListener +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito.* +import java.util.* + +class AdvancedListenerTest { + + @Before + fun before() { + val cloudAPI = spy(EmptyMockCloudAPIImpl::class.java) + val cloudModule = object : ICloudModule { + override fun onEnable() { + } + + override fun onDisable() { + } + } + `when`(cloudAPI.getThisSidesCloudModule()).thenReturn(cloudModule) + val eventManager = BasicEventManager() + `when`(cloudAPI.getEventManager()).thenReturn(eventManager) + } + + @Test + fun listener_call_test() { + val runnable = mock(Runnable::class.java) + val advancedListener = cloudListener() + advancedListener.unregisterAfterCall() + advancedListener.addAction { runnable.run() } + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + verify(runnable, times(1)).run() + } + + @Test + fun listener_unregister_test() { + val runnable = mock(Runnable::class.java) + val advancedListener = cloudListener() + advancedListener.addAction { runnable.run() } + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + advancedListener.unregister() + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + verify(runnable, times(2)).run() + } + + @Test + fun listener_promise_test() { + val runnable = mock(Runnable::class.java) + val advancedListener = cloudListener() + advancedListener.toPromise().addResultListener { runnable.run() } + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + Thread.sleep(100) + verify(runnable, times(1)).run() + } + + @Test + fun listener_auto_unregister_test() { + val runnable = mock(Runnable::class.java) + val advancedListener = cloudListener(true, 1) + advancedListener.addAction { runnable.run() } + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + Thread.sleep(1024) + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(UUID.randomUUID(), "")) + verify(runnable, times(1)).run() + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EmptyMockCloudAPIImpl.kt b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EmptyMockCloudAPIImpl.kt new file mode 100644 index 000000000..23f6ed3f7 --- /dev/null +++ b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EmptyMockCloudAPIImpl.kt @@ -0,0 +1,96 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.ILanguageManager +import eu.thesimplecloud.api.message.IMessageChannelManager +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.version.IServiceVersionHandler +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.sync.list.manager.ISynchronizedObjectListManager +import eu.thesimplecloud.api.sync.`object`.IGlobalPropertyHolder +import eu.thesimplecloud.clientserverapi.lib.bootstrap.ICommunicationBootstrap +import org.mockito.Mockito.mock + +open class EmptyMockCloudAPIImpl : CloudAPI() { + override fun getCloudServiceGroupManager(): ICloudServiceGroupManager { + return mock(ICloudServiceGroupManager::class.java) + } + + override fun getCloudServiceManager(): ICloudServiceManager { + return mock(ICloudServiceManager::class.java) + } + + override fun getCloudPlayerManager(): ICloudPlayerManager { + return mock(ICloudPlayerManager::class.java) + } + + override fun getEventManager(): IEventManager { + return mock(IEventManager::class.java) + } + + override fun getCommandExecuteManager(): ICommandExecuteManager { + return mock(ICommandExecuteManager::class.java) + } + + override fun getGlobalPropertyHolder(): IGlobalPropertyHolder { + return mock(IGlobalPropertyHolder::class.java) + } + + override fun getThisSidesCommunicationBootstrap(): ICommunicationBootstrap { + return mock(ICommunicationBootstrap::class.java) + } + + override fun getSynchronizedObjectListManager(): ISynchronizedObjectListManager { + throw UnsupportedOperationException() + } + + override fun getServiceVersionHandler(): IServiceVersionHandler { + return mock(IServiceVersionHandler::class.java) + } + + override fun getLanguageManager(): ILanguageManager { + return mock(ILanguageManager::class.java) + } + + override fun getMessageChannelManager(): IMessageChannelManager { + return mock(IMessageChannelManager::class.java) + } + + override fun getThisSidesName(): String { + return "" + } + + override fun getThisSidesNetworkComponent(): INetworkComponent { + return mock(INetworkComponent::class.java) + } + + override fun getThisSidesCloudModule(): ICloudModule { + return mock(ICloudModule::class.java) + } +} \ No newline at end of file diff --git a/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EventApiTest.kt b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EventApiTest.kt new file mode 100644 index 000000000..47688aae2 --- /dev/null +++ b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/eventapi/EventApiTest.kt @@ -0,0 +1,105 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.eventapi + +import eu.thesimplecloud.api.external.ICloudModule +import org.junit.Assert +import org.junit.Test +import org.mockito.Mockito.* + +class EventApiTest { + + val eventManager = BasicEventManager() + val cloudModule = object : ICloudModule { + override fun onEnable() { + } + + override fun onDisable() { + } + + } + + + @Test + fun testListenerCall() { + val testListener = TestListener() + eventManager.registerListener(cloudModule, testListener) + val testEvent = TestEvent("test123") + eventManager.call(testEvent) + Assert.assertEquals("test123", testListener.testString) + } + + @Test + fun testUnregister() { + val testListener = TestListener() + eventManager.registerListener(cloudModule, testListener) + eventManager.unregisterListener(testListener) + val testEvent = TestEvent("12test") + eventManager.call(testEvent) + Assert.assertEquals(null, testListener.testString) + } + + @Test + fun testUnregisterByModule() { + val testListener = TestListener() + eventManager.registerListener(cloudModule, testListener) + eventManager.unregisterAllListenersByCloudModule(cloudModule) + val testEvent = TestEvent("12test") + eventManager.call(testEvent) + Assert.assertEquals(null, testListener.testString) + } + + @Test + fun testUnregisterAll() { + val testListener = TestListener() + val testEvent = TestEvent("12test") + eventManager.registerListener(cloudModule, testListener) + eventManager.unregisterAll() + eventManager.call(testEvent) + Assert.assertEquals(null, testListener.testString) + } + + @Test + fun testRegisterSingleEvent() { + val listenerObj = object : IListener {} + val eventExecutor = spy(IEventExecutor::class.java) + eventManager.registerEvent(cloudModule, TestEvent::class.java, listenerObj, eventExecutor) + val testEvent = TestEvent("") + eventManager.call(testEvent) + verify(eventExecutor, times(1)).execute(testEvent) + } + + class TestEvent(val testString: String) : IEvent + + open class TestListener : IListener { + + var testString: String? = null + + @CloudEventHandler + fun on(event: TestEvent) { + testString = event.testString + } + + } + +} \ No newline at end of file diff --git a/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/serviceversion/ServiceVersionHandlerTest.kt b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/serviceversion/ServiceVersionHandlerTest.kt new file mode 100644 index 000000000..df9936dcc --- /dev/null +++ b/simplecloud-api/src/test/kotlin/eu/thesimplecloud/api/serviceversion/ServiceVersionHandlerTest.kt @@ -0,0 +1,189 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.api.serviceversion + +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.service.version.ServiceVersionHandler +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.api.service.version.type.ServiceVersionType +import eu.thesimplecloud.jsonlib.JsonLib +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * Created by IntelliJ IDEA. + * Date: 14.06.2020 + * Time: 18:47 + * @author Frederick Baier + */ +class ServiceVersionHandlerTest { + + val testContent = "[\n" + + " {\n" + + " \"name\": \"BUNGEECORD\",\n" + + " \"serviceAPIType\": \"BUNGEECORD\",\n" + + " \"downloadURL\": \"https://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"TRAVERTINE\",\n" + + " \"serviceAPIType\": \"BUNGEECORD\",\n" + + " \"downloadURL\": \"https://papermc.io/ci/job/Travertine/lastSuccessfulBuild/artifact/Travertine-Proxy/bootstrap/target/Travertine.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"WATERFALL\",\n" + + " \"serviceAPIType\": \"BUNGEECORD\",\n" + + " \"downloadURL\": \"https://papermc.io/ci/job/Waterfall/lastSuccessfulBuild/artifact/Waterfall-Proxy/bootstrap/target/Waterfall.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"HEXACORD\",\n" + + " \"serviceAPIType\": \"BUNGEECORD\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/hexacord/HexaCord-v246.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"VELOCITY\",\n" + + " \"serviceAPIType\": \"VELOCITY\",\n" + + " \"downloadURL\": \"https://ci.velocitypowered.com/job/velocity-1.1.0/lastSuccessfulBuild/artifact/proxy/build/libs/velocity-proxy-1.1.0-SNAPSHOT-all.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_7_10\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.7.10-SNAPSHOT-b1657.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_8_8\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.8.8-R0.1-SNAPSHOT-latest.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_9_4\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.9.4-R0.1-SNAPSHOT-latest.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_10_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.10.2-R0.1-SNAPSHOT-latest.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_11_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.11.2.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_12_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.12.2.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_13_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.13.2.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_14_4\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.14.4.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"SPIGOT_1_15_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://cdn.getbukkit.org/spigot/spigot-1.15.2.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_7_10\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/PaperSpigot-1.7.10-R0.1-SNAPSHOT-latest.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_8_8\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/PaperSpigot-1.8.8-R0.1-SNAPSHOT-latest.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_11_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/PaperSpigot-1.11.2-b1104.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_12_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/Paper-1.12.2-b1618.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_13_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/Paper-1.13.2-b655.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_14_4\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/Paper-1.14.4-b243.jar\"\n" + + " },\n" + + " {\n" + + " \"name\": \"PAPER_1_15_2\",\n" + + " \"serviceAPIType\": \"SPIGOT\",\n" + + " \"downloadURL\": \"https://yivesmirror.com/files/paper/Paper-1.15.2-b350.jar\"\n" + + " }\n" + + "]" + + @Test + fun versions_test() { + val list = JsonLib.fromJsonString(testContent).getObject(Array::class.java).toList() + val serviceVersionHandler = ServiceVersionHandler(list) + assertEquals(4, serviceVersionHandler.getVersions(ServiceAPIType.BUNGEECORD).size) + assertEquals(1, serviceVersionHandler.getVersions(ServiceAPIType.VELOCITY).size) + assertEquals(16, serviceVersionHandler.getVersions(ServiceAPIType.SPIGOT).size) + } + + @Test + fun prefix_test() { + val list = JsonLib.fromJsonString(testContent).getObject(Array::class.java).toList() + val serviceVersionHandler = ServiceVersionHandler(list) + assertEquals(1, serviceVersionHandler.getVersionsByPrefix("BUNGEECORD").size) + assertEquals(7, serviceVersionHandler.getVersionsByPrefix("PAPER").size) + assertEquals(9, serviceVersionHandler.getVersionsByPrefix("SPIGOT").size) + } + + @Test + fun suffix_test() { + val list = JsonLib.fromJsonString(testContent).getObject(Array::class.java).toList() + val serviceVersionHandler = ServiceVersionHandler(list) + assertEquals( + mutableListOf("1_7_10", "1_8_8", "1_11_2", "1_12_2", "1_13_2", "1_14_4", "1_15_2"), + serviceVersionHandler.getAllVersionSuffixes("PAPER") + ) + assertEquals(7, serviceVersionHandler.getVersionsByPrefix("PAPER").size) + assertEquals(9, serviceVersionHandler.getVersionsByPrefix("SPIGOT").size) + } + + @Test + fun prefix_by_service_version_test() { + val list = JsonLib.fromJsonString(testContent).getObject(Array::class.java).toList() + val serviceVersionHandler = ServiceVersionHandler(list) + assertEquals( + mutableSetOf("SPIGOT", "PAPER"), + serviceVersionHandler.getPrefixesByServiceVersionType(ServiceVersionType.SERVER) + ) + } + +} \ No newline at end of file diff --git a/simplecloud-base/build.gradle b/simplecloud-base/build.gradle new file mode 100644 index 000000000..56865875c --- /dev/null +++ b/simplecloud-base/build.gradle @@ -0,0 +1,67 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +plugins { + id 'java' + id 'org.jetbrains.kotlin.jvm' + id 'maven-publish' +} + +repositories { + mavenLocal() + mavenCentral() + maven { url("https://xbib.org/repository/") } +} + +dependencies { + testApi group: 'junit', name: 'junit', version: '4.12' + compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + compileOnly project(":simplecloud-api") + compileOnly project(":simplecloud-runner") + compileOnly project(":simplecloud-dependency-loader") + compileOnly project(":simplecloud-launcher") + api(project(":simplecloud-client")) { + transitive = false + } + compileOnly group: 'commons-io', name: 'commons-io', version: dependencyCommonsIOVersion + compileOnly group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: dependencyKotlinCouroutinesVersion + compileOnly group: 'org.reflections', name: 'reflections', version: '0.9.12' + compileOnly group: 'org.litote.kmongo', name: 'kmongo', version: dependencyKMongoVersion + compileOnly(group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion) + compileOnly group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' +} + +compileKotlin { + kotlinOptions.jvmTarget = 1.8 +} + +shadowJar { + archiveFileName.set("base.jar") +} + +jar { + manifest { + attributes( + 'Implementation-Version': project.version, + ) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgument.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgument.kt new file mode 100644 index 000000000..a3269f623 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgument.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.core.jvm + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 12.06.2020 + * Time: 18:47 + */ +data class JvmArgument( + val groups: List, + val arguments: List +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgumentsConfig.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgumentsConfig.kt new file mode 100644 index 000000000..5afd753e7 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/core/jvm/JvmArgumentsConfig.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.core.jvm + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 12.06.2020 + * Time: 18:36 + */ +data class JvmArgumentsConfig( + val jvmArguments: List +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ClearCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ClearCommand.kt new file mode 100644 index 000000000..767068b02 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ClearCommand.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.startup.Launcher + +@Command("clear", CommandType.CONSOLE, "cloud.command.clear") +class ClearCommand : ICommandHandler { + + @CommandSubPath("", "Clears the Console") + fun handleClear(commandSender: ICommandSender) { + Launcher.instance.clearConsole() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CopyCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CopyCommand.kt new file mode 100644 index 000000000..74dc82fcb --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CopyCommand.kt @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceCommandSuggestionProvider + +/** + * Created by IntelliJ IDEA. + * Date: 09.06.2020 + * Time: 16:54 + * @author Frederick Baier + */ +@Command("copy", CommandType.CONSOLE_AND_INGAME, "cloud.command.copy") +class CopyCommand : ICommandHandler { + + @CommandSubPath(" ", "Copies the specified directory to the template folder") + fun handle( + commandSender: ICommandSender, + @CommandArgument("service", ServiceCommandSuggestionProvider::class) service: ICloudService, + @CommandArgument("path") path: String + ) { + if (!service.isActive()) { + commandSender.sendProperty("manager.command.copy.service-inactive") + return + } + commandSender.sendProperty("manager.command.copy.start", service.getName()) + service.copy(path) + .addResultListener { + commandSender.sendProperty("manager.command.copy.success") + }.addFailureListener { + val messageCause = it.message ?: it::class.java.simpleName + commandSender.sendProperty("manager.command.copy.failed", messageCause) + } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CreateCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CreateCommand.kt new file mode 100644 index 000000000..45dbdacd8 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/CreateCommand.kt @@ -0,0 +1,91 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.template.impl.DefaultTemplate +import eu.thesimplecloud.base.manager.setup.ServiceVersionSetup +import eu.thesimplecloud.base.manager.setup.WrapperSetup +import eu.thesimplecloud.base.manager.setup.groups.* +import eu.thesimplecloud.launcher.config.java.JavaVersion +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.startup.Launcher + +@Command("create", CommandType.CONSOLE, "cloud.command.create") +class CreateCommand : ICommandHandler { + + val templateManager = CloudAPI.instance.getTemplateManager() + + + @CommandSubPath("lobbygroup", "Creates a lobby group") + fun createLobbyGroup() { + if (JavaVersion.paths.versions.isEmpty()) { + Launcher.instance.setupManager.queueSetup(LobbyGroupSetup()) + return + } + Launcher.instance.setupManager.queueSetup(LobbyGroupSetupWithJava()) + } + + @CommandSubPath("proxygroup", "Creates a proxy group") + fun createProxyGroup() { + Launcher.instance.setupManager.queueSetup(ProxyGroupSetup()) + } + + @CommandSubPath("servergroup", "Creates a server group") + fun createServerGroup() { + if (JavaVersion.paths.versions.isEmpty()) { + Launcher.instance.setupManager.queueSetup(ServerGroupSetup()) + return + } + Launcher.instance.setupManager.queueSetup(ServerGroupSetupWithJava()) + } + + @CommandSubPath("wrapper", "Creates a wrapper") + fun createWrapper() { + Launcher.instance.setupManager.queueSetup(WrapperSetup()) + } + + @CommandSubPath("serviceVersion", "Creates a Service Version") + fun createServiceVersion() { + Launcher.instance.setupManager.queueSetup(ServiceVersionSetup()) + } + + @CommandSubPath("template ", "Creates a template") + fun createTemplate(@CommandArgument("name") name: String) { + if (name.length > 16) { + Launcher.instance.consoleSender.sendProperty("manager.command.create.template.name-too-long") + } + if (templateManager.getTemplateByName(name) != null) { + Launcher.instance.consoleSender.sendProperty("manager.command.create.template.already-exist", name) + return + } + val template = DefaultTemplate(name) + templateManager.update(template) + Launcher.instance.consoleSender.sendProperty("manager.command.create.template.success", name) + + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/DeleteCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/DeleteCommand.kt new file mode 100644 index 000000000..72da12b2e --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/DeleteCommand.kt @@ -0,0 +1,115 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.base.manager.serviceversion.ManagerServiceVersionHandler +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.startup.Launcher + +@Command("delete", CommandType.CONSOLE, "cloud.command.delete") +class DeleteCommand : ICommandHandler { + + private val templateManager = CloudAPI.instance.getTemplateManager() + + @CommandSubPath("template ", "Deletes a template") + fun deleteTemplate(@CommandArgument("name") name: String) { + if (templateManager.getTemplateByName(name) == null) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.template.not-exist", name) + return + } + if (CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + .any { it.getTemplateName().equals(name, true) } + ) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.template.in-use.group", name) + return + } + if (CloudAPI.instance.getCloudServiceManager().getAllCachedObjects() + .any { it.getTemplateName().equals(name, true) } + ) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.template.in-use.service", name) + return + } + templateManager.deleteTemplate(name) + Launcher.instance.consoleSender.sendProperty("manager.command.delete.template.success", name) + } + + @CommandSubPath("group ", "Deletes a group") + fun deleteGroup(@CommandArgument("name") name: String) { + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name) + if (serviceGroup == null) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.group.not-exist", name) + return + } + val result = runCatching { CloudAPI.instance.getCloudServiceGroupManager().delete(serviceGroup) } + if (result.isFailure) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.group.services-running", name) + return + } + Launcher.instance.consoleSender.sendProperty("manager.command.delete.group.success", name) + } + + + @CommandSubPath("wrapper ", "Deletes a wrapper") + fun deleteWrapper(@CommandArgument("wrapper") name: String) { + val wrapper = CloudAPI.instance.getWrapperManager().getWrapperByName(name) + if (wrapper == null) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.wrapper.not-exist", name) + return + } + if (wrapper.getServicesRunningOnThisWrapper().isNotEmpty()) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.wrapper.services-running", name) + return + } + if (CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupsByWrapperName(wrapper.getName()) + .isNotEmpty() + ) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.wrapper.group-must-start", name) + return + } + + CloudAPI.instance.getWrapperManager().delete(wrapper) + Launcher.instance.consoleSender.sendProperty("manager.command.delete.wrapper.success", name) + } + + @CommandSubPath("serviceVersion ", "Delete a Service Version") + fun createServiceVersion(@CommandArgument("name") name: String) { + val serviceVersionHandler = CloudAPI.instance.getServiceVersionHandler() as ManagerServiceVersionHandler + if (!serviceVersionHandler.doesVersionExist(name)) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.service-version.not-exist") + return + } + if (serviceVersionHandler.isVersionInUse(name)) { + Launcher.instance.consoleSender.sendProperty("manager.command.delete.service-version.still-in-use") + return + } + serviceVersionHandler.deleteServiceVersion(name) + Launcher.instance.consoleSender.sendProperty("manager.command.delete.service-version.deleted", name) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/EditCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/EditCommand.kt new file mode 100644 index 000000000..146c1a038 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/EditCommand.kt @@ -0,0 +1,316 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.parser.string.StringParser +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.utils.getAllFieldsFromClassAndSubClasses +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.manager.commands.provider.EditGroupParameterCommandSuggestionProvider +import eu.thesimplecloud.base.manager.commands.provider.EditWrapperParameterCommandSuggestionProvider +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.* +import eu.thesimplecloud.launcher.startup.Launcher +import java.lang.reflect.Field + +@Command("edit", CommandType.CONSOLE_AND_INGAME, "cloud.command.edit") +class EditCommand : ICommandHandler { + + //group + + @CommandSubPath("group ", "Shows the parameters value") + fun editGroup( + commandSender: ICommandSender, + @CommandArgument("name", ServiceGroupCommandSuggestionProvider::class) name: String, + @CommandArgument("parameter", EditGroupParameterCommandSuggestionProvider::class) parameter: String + ) { + val fields = getFieldsOfGroup(name) ?: return + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name)!! + val lowerCaseFieldNames = fields.map { it.name.toLowerCase() } + if (lowerCaseFieldNames.contains(parameter.toLowerCase())) { + val field = fields[lowerCaseFieldNames.indexOf(parameter.toLowerCase())] + field.isAccessible = true + val fieldValue = field[serviceGroup] + commandSender.sendMessage("Value: $fieldValue") + } else { + sendAllParameters(commandSender, fields) + } + } + + @CommandSubPath("group ", "Edits a service group") + fun editGroup( + commandSender: ICommandSender, + @CommandArgument("name", ServiceGroupCommandSuggestionProvider::class) name: String, + @CommandArgument("parameter", EditGroupParameterCommandSuggestionProvider::class) parameter: String, + @CommandArgument("value") value: String + ) { + val fields = getFieldsOfGroup(name) ?: return + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name)!! + val lowerCaseFieldNames = fields.map { it.name.toLowerCase() } + if (lowerCaseFieldNames.contains(parameter.toLowerCase())) { + val field = fields[lowerCaseFieldNames.indexOf(parameter.toLowerCase())] + field.isAccessible = true + val type = StringParser().parseToObject(value, field.type) + if (type == null) { + commandSender.sendProperty("manager.command.edit.group.invalid-value", field.type.simpleName) + return + } + try { + field.set(serviceGroup, type) + commandSender.sendProperty("manager.command.edit.group.success") + CloudAPI.instance.getCloudServiceGroupManager().update(serviceGroup) + } catch (e: Exception) { + commandSender.sendProperty("manager.command.edit.group.invalid-value", field.type.simpleName) + return + } + } else { + sendAllParameters(commandSender, fields) + } + } + + fun getFieldsOfGroup(groupName: String): List? { + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(groupName) + if (serviceGroup == null) { + Launcher.instance.consoleSender.sendProperty("manager.command.edit.group.not-exist") + return null + } + val allFields = serviceGroup::class.java.getAllFieldsFromClassAndSubClasses() + .filter { !Collection::class.java.isAssignableFrom(it.type) } + return allFields.filterNot { it.name == "name" || it.name == "serviceVersion" } + } + //wrapper + + @CommandSubPath("wrapper ", "Shows the parameters value") + fun editWrapper( + commandSender: ICommandSender, + @CommandArgument("name", WrapperCommandSuggestionProvider::class) wrapper: IWrapperInfo, + @CommandArgument( + "parameter", + EditWrapperParameterCommandSuggestionProvider::class + ) parameter: String + ) { + val fields = getFieldsOfWrapper(wrapper) + val lowerCaseFieldNames = fields.map { it.name.toLowerCase() } + if (lowerCaseFieldNames.contains(parameter.toLowerCase())) { + val field = fields[lowerCaseFieldNames.indexOf(parameter.toLowerCase())] + field.isAccessible = true + val fieldValue = field[wrapper] + commandSender.sendMessage("Value: $fieldValue") + } else { + sendAllParameters(commandSender, fields) + } + } + + @CommandSubPath("wrapper ", "Edits a wrapper") + fun editWrapper( + commandSender: ICommandSender, + @CommandArgument("name", WrapperCommandSuggestionProvider::class) wrapper: IWrapperInfo, + @CommandArgument( + "parameter", + EditWrapperParameterCommandSuggestionProvider::class + ) parameter: String, + @CommandArgument("value") value: String + ) { + val fields = getFieldsOfWrapper(wrapper) + val lowerCaseFieldNames = fields.map { it.name.toLowerCase() } + if (lowerCaseFieldNames.contains(parameter.toLowerCase())) { + val field = fields[lowerCaseFieldNames.indexOf(parameter.toLowerCase())] + field.isAccessible = true + val type = StringParser().parseToObject(value, field.type) + if (type == null) { + commandSender.sendProperty("manager.command.edit.wrapper.invalid-value", field.type.simpleName) + return + } + try { + field.set(wrapper, type) + commandSender.sendProperty("manager.command.edit.wrapper.success") + CloudAPI.instance.getWrapperManager().update(wrapper) + } catch (e: Exception) { + commandSender.sendProperty("manager.command.edit.wrapper.invalid-value", field.type.simpleName) + return + } + } else { + sendAllParameters(commandSender, fields) + } + } + + private fun getFieldsOfWrapper(wrapper: IWrapperInfo): List { + val allFields = wrapper::class.java.getAllFieldsFromClassAndSubClasses() + .filter { !Collection::class.java.isAssignableFrom(it.type) } + return allFields.filterNot { + it.name == "name" || + it.name == "host" || + it.name == "wrapperName" || + it.name == "wrapperUpdater" || + it.name == "cpuUsage" + } + } + + private fun sendAllParameters(commandSender: ICommandSender, fields: List) { + commandSender.sendProperty("manager.command.edit.allowed-parameters") + commandSender.sendMessage(fields.joinToString { it.name }) + } + + @CommandSubPath("template inheritance add ", "Adds a inheritance to a template") + fun addInheritTemplate( + commandSender: ICommandSender, + @CommandArgument("name", TemplateCommandSuggestionProvider::class) template: ITemplate, + @CommandArgument( + "otherTemplate", + TemplateCommandSuggestionProvider::class + ) otherTemplate: ITemplate + ) { + if (template == otherTemplate) { + commandSender.sendProperty("manager.command.edit.template.inheritance.add.both-equal") + return + } + if (template.getInheritedTemplateNames().contains(otherTemplate.getName())) { + commandSender.sendProperty( + "manager.command.edit.template.inheritance.add.already-added", + template.getName(), + otherTemplate.getName() + ) + return + } + template.addInheritanceTemplate(otherTemplate) + CloudAPI.instance.getTemplateManager().update(template) + commandSender.sendProperty( + "manager.command.edit.template.inheritance.add.success", + template.getName(), + otherTemplate.getName() + ) + } + + @CommandSubPath("template inheritance remove ", "Removes a inheritance from a template") + fun removeInheritTemplate( + commandSender: ICommandSender, + @CommandArgument("name", TemplateCommandSuggestionProvider::class) template: ITemplate, + @CommandArgument( + "otherTemplate", + TemplateCommandSuggestionProvider::class + ) otherTemplate: ITemplate + ) { + if (!template.getInheritedTemplateNames().contains(otherTemplate.getName())) { + commandSender.sendProperty( + "manager.command.edit.template.inheritance.remove.not-added", + template.getName(), + otherTemplate.getName() + ) + return + } + template.removeInheritanceTemplate(otherTemplate) + CloudAPI.instance.getTemplateManager().update(template) + commandSender.sendProperty( + "manager.command.edit.template.inheritance.remove.success", + template.getName(), + otherTemplate.getName() + ) + } + + + @CommandSubPath("template module add ", "Adds a module to a template") + fun addModuleNameToCopy( + commandSender: ICommandSender, + @CommandArgument("name", TemplateCommandSuggestionProvider::class) template: ITemplate, + @CommandArgument("module") module: String + ) { + if (template.getModuleNamesToCopy().map { it.toLowerCase() }.contains(module)) { + commandSender.sendProperty( + "manager.command.edit.template.modules.add.already-added", + module, + template.getName() + ) + return + } + template.addModuleNameToCopy(module) + CloudAPI.instance.getTemplateManager().update(template) + commandSender.sendProperty("manager.command.edit.template.modules.add.success", module, template.getName()) + } + + @CommandSubPath("template module remove ", "Removes a module from a template") + fun removeModuleNameToCopy( + commandSender: ICommandSender, + @CommandArgument("name", TemplateCommandSuggestionProvider::class) template: ITemplate, + @CommandArgument("module") module: String + ) { + if (!template.getModuleNamesToCopy().map { it.toLowerCase() }.contains(module)) { + commandSender.sendProperty( + "manager.command.edit.template.modules.remove.not-added", + module, + template.getName() + ) + return + } + template.removeModuleNameToCopy(module) + CloudAPI.instance.getTemplateManager().update(template) + commandSender.sendProperty("manager.command.edit.template.modules.remove.success", module, template.getName()) + } + + @CommandSubPath("service state ", "Sets the state of a service") + fun setState( + sender: ICommandSender, + @CommandArgument("service", ServiceCommandSuggestionProvider::class) service: ICloudService, + @CommandArgument("state", ServiceStateCommandSuggestionProvider::class) state: ServiceState + ) { + if (state != ServiceState.VISIBLE && state != ServiceState.INVISIBLE) { + sender.sendProperty("manager.command.edit.service.state.fail") + return + } + service.setState(state) + service.update() + sender.sendProperty("manager.command.edit.service.state.success") + } + + @CommandSubPath("service displayname ", "Sets the displayname of a service") + fun setDisplayName( + sender: ICommandSender, + @CommandArgument("service", ServiceCommandSuggestionProvider::class) service: ICloudService, + @CommandArgument("displayname") displayname: String + ) { + service.setDisplayName(displayname) + service.update() + sender.sendProperty("manager.command.edit.service.displayname.success") + } + + @CommandSubPath("service maxplayers ", "Sets the setmaxplayers slots of a service") + fun setMaxPlayers( + sender: ICommandSender, + @CommandArgument("service", ServiceCommandSuggestionProvider::class) service: ICloudService, + @CommandArgument("maxplayers") maxplayers: Int + ) { + + service.setMaxPlayers(maxplayers) + service.update() + sender.sendProperty("manager.command.edit.service.maxplayers.success") + + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ExecuteCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ExecuteCommand.kt new file mode 100644 index 000000000..2c0306fdb --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ExecuteCommand.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath + +@Command("execute", CommandType.CONSOLE_AND_INGAME, "cloud.command.execute", ["exec"]) +class ExecuteCommand : ICommandHandler { + + @CommandSubPath("", "Execute a command on the specified service") + fun handle(commandSender: ICommandSender, args: Array) { + if (args.size < 2) { + commandSender.sendProperty("manager.command.execute.usage") + return + } + val serviceName = args[0] + val service = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) + if (service == null) { + commandSender.sendProperty("manager.command.execute.service-not-found") + return + } + service.executeCommand(args.drop(1).joinToString(" ")) + commandSender.sendProperty("manager.command.execute.success") + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/InfoCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/InfoCommand.kt new file mode 100644 index 000000000..6a69d0365 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/InfoCommand.kt @@ -0,0 +1,96 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceCommandSuggestionProvider +import eu.thesimplecloud.launcher.console.command.provider.ServiceGroupCommandSuggestionProvider +import eu.thesimplecloud.launcher.console.command.provider.WrapperCommandSuggestionProvider + +@Command("info", CommandType.CONSOLE_AND_INGAME, "cloud.command.info") +class InfoCommand : ICommandHandler { + + @CommandSubPath("wrapper ", "Prints some information about the specified wrapper") + fun wrapper( + commandSender: ICommandSender, + @CommandArgument("name", WrapperCommandSuggestionProvider::class) name: String + ) { + val wrapper = CloudAPI.instance.getWrapperManager().getWrapperByName(name) + if (wrapper == null) { + commandSender.sendProperty("manager.command.info.wrapper.not-exist") + return + } + commandSender.sendMessage(wrapper.toString()) + } + + + @CommandSubPath("service ", "Prints some information about the specified service") + fun service( + commandSender: ICommandSender, + @CommandArgument("name", ServiceCommandSuggestionProvider::class) name: String + ) { + val service = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) + if (service == null) { + commandSender.sendProperty("manager.command.info.service.not-exist") + return + } + commandSender.sendMessage(service.toString()) + } + + @CommandSubPath("group ", "Prints some information about the specified group") + fun group( + commandSender: ICommandSender, + @CommandArgument("name", ServiceGroupCommandSuggestionProvider::class) name: String + ) { + val group = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name) + if (group == null) { + commandSender.sendProperty("manager.command.info.group.not-exist") + return + } + commandSender.sendMessage(group.toString()) + } + + @CommandSubPath("player ", "Prints some information about the specified player") + fun player(commandSender: ICommandSender, @CommandArgument("name") name: String) { + val player = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(name) + if (player == null) { + commandSender.sendProperty("manager.command.info.player.not-exist") + return + } + commandSender.sendMessage(player.toString()) + } + + @CommandSubPath("onlinecount", "Prints the number of online players") + fun handlePlayers(commandSender: ICommandSender) { + val onlineCount = CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().size + commandSender.sendProperty("manager.command.info.onlinecount", onlineCount.toString()) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ListCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ListCommand.kt new file mode 100644 index 000000000..e0513140b --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ListCommand.kt @@ -0,0 +1,100 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath + +/** + * Created by MrManHD + * Class create at 13.06.2020 17:24 + */ + +@Command("list", CommandType.CONSOLE_AND_INGAME, "cloud.command.list") +class ListCommand : ICommandHandler { + + @CommandSubPath("", "Lists some information about the cloud") + fun handleList(commandSender: ICommandSender) { + val darkChatColor = if (commandSender is ICloudPlayer) "§8" else "§7" + + CloudAPI.instance.getWrapperManager().getAllCachedObjects().forEach { + val connectedMessage = if (it.isAuthenticated()) "§aConnected" else "§cNot Connected" + commandSender.sendMessage( + darkChatColor + ">> §3" + it.getName() + darkChatColor + " (§f" + it.getUsedMemory() + + darkChatColor + "/§f" + + it.getMaxMemory() + "MB" + darkChatColor + " | " + connectedMessage + darkChatColor + ")" + ) + } + + commandSender.sendMessage(" ") + + val cloudServices = CloudAPI.instance.getCloudServiceManager().getAllCachedObjects() + val cloudServiceGroups = CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + cloudServiceGroups.filter { it.getAllServices().isNotEmpty() }.forEach { groups -> + val serviceName = if (groups.getRegisteredServiceCount() == 1) "Service" else "Services" + + commandSender.sendMessage( + darkChatColor + ">> §7" + groups.getName() + darkChatColor + " (§f" + groups.getMaxMemory() + + "MB " + darkChatColor + "/§f " + + groups.getRegisteredServiceCount() + " " + serviceName + darkChatColor + ")" + ) + + groups.getAllServices().forEach { + val wrapperDesign = + if (it.getWrapperName() != null) " " + darkChatColor + "|§3 " + it.getWrapperName() else "" + commandSender.sendMessage( + darkChatColor + "- §b" + it.getName() + " " + darkChatColor + "(§f" + + it.getUsedMemory() + "MB" + " ${darkChatColor}| " + + "§f" + it.getOnlineCount() + + darkChatColor + "/§f" + + it.getMaxPlayers() + " " + darkChatColor + "|§3 " + it.getState() + wrapperDesign + darkChatColor + ")" + ) + } + + commandSender.sendMessage(" ") + } + + val unusedGroups = cloudServiceGroups.filter { it.getAllServices().isEmpty() } + .joinToString("$darkChatColor,§f ") { it.getName() } + + val maxMemory = CloudAPI.instance.getWrapperManager().getAllCachedObjects().sumBy { it.getMaxMemory() } + val usedMemory = CloudAPI.instance.getWrapperManager().getAllCachedObjects().sumBy { it.getUsedMemory() } + + if (unusedGroups.isNotEmpty()) commandSender.sendMessage( + darkChatColor + ">>§7 Unused Groups" + + darkChatColor + ":§f " + unusedGroups + ) + commandSender.sendMessage(darkChatColor + ">>§7 Online Services" + darkChatColor + ":§f " + cloudServices.size) + commandSender.sendMessage( + darkChatColor + ">>§7 Memory" + darkChatColor + ":§f " + usedMemory + + darkChatColor + "/§f" + maxMemory + "MB" + ) + + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ReloadCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ReloadCommand.kt new file mode 100644 index 000000000..f80e1c693 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ReloadCommand.kt @@ -0,0 +1,152 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.extension.sendPacketToAllAuthenticatedWrapperClients +import eu.thesimplecloud.base.manager.config.JvmArgumentsConfigLoader +import eu.thesimplecloud.base.manager.network.packets.PacketOutReloadExistingModules +import eu.thesimplecloud.base.manager.serviceversion.ManagerServiceVersionHandler +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.loader.dependency.DependencyLoader +import kotlin.concurrent.thread + +@Command("reload", CommandType.CONSOLE_AND_INGAME, "cloud.command.reload", ["rl"]) +class ReloadCommand : ICommandHandler { + + @CommandSubPath("all", "Reload everything (recommended)") + fun handleReloadAll(commandSender: ICommandSender) { + this.reloadModules() + this.reloadWrappers(commandSender) + this.reloadServiceVersion() + this.reloadJvmArguments() + this.reloadGroups(commandSender) + } + + @CommandSubPath("modules", "Reload all modules") + fun handleReloadModules(commandSender: ICommandSender) { + this.reloadModules() + } + + @CommandSubPath("wrappers", "Reload all wrappers") + fun handleReloadWrappers(commandSender: ICommandSender) { + this.reloadWrappers(commandSender) + } + + @CommandSubPath("serverVersion", "Reload all server versions") + fun handleReloadServerVersions(commandSender: ICommandSender) { + this.reloadServiceVersion() + commandSender.sendProperty("manager.command.reload.server.version") + } + + @CommandSubPath("jvm-arguments", "Reload jvm-arguments") + fun handleReloadJvmArguments(commandSender: ICommandSender) { + this.reloadJvmArguments() + commandSender.sendProperty("manager.command.reload.jvm.arguments") + } + + @CommandSubPath("groups", "Reload all groups") + fun handleReloadGroups(commandSender: ICommandSender) { + this.reloadGroups(commandSender) + } + + @CommandSubPath("module ", "Reloads a specific module") + fun handleReloadModule(commandSender: ICommandSender, @CommandArgument("name") moduleName: String) { + val module = Manager.instance.cloudModuleHandler.getLoadedModuleByName(moduleName) + + if (module == null) { + commandSender.sendProperty("manager.command.reload.module.not-exists") + return + } + + Manager.instance.cloudModuleHandler.unloadModule(module.cloudModule) + Manager.instance.cloudModuleHandler.loadSingleModuleFromFile(module.file) + } + + private fun reloadGroups(commandSender: ICommandSender) { + val loadedGroups = Manager.instance.cloudServiceGroupFileHandler.loadAll().toMutableList() + val unknownGroups = loadedGroups.filter { + CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(it.getName()) == null + } + if (unknownGroups.isNotEmpty()) { + unknownGroups.forEach { + commandSender.sendProperty("manager.command.reload.group-changed", it.getName()) + } + } + loadedGroups.toMutableList().removeAll(unknownGroups) + loadedGroups.forEach { CloudAPI.instance.getCloudServiceGroupManager().update(it) } + loadedGroups.forEach { commandSender.sendProperty("manager.command.reload.group-success", it.getName()) } + } + + private fun reloadModules() { + Manager.instance.cloudModuleHandler.unloadAllReloadableModules() + Manager.instance.appClassLoader.clearCachedClasses() + DependencyLoader.INSTANCE.reset() + + Manager.instance.communicationServer.getClientManager() + .sendPacketToAllAuthenticatedWrapperClients(PacketOutReloadExistingModules()) + + //enable + Manager.instance.appClassLoader.clearCachedClasses() + thread( + start = true, + isDaemon = false, + Manager.instance.appClassLoader + ) { Manager.instance.cloudModuleHandler.loadAllUnloadedModules() } + } + + private fun reloadWrappers(commandSender: ICommandSender) { + val loadedWrappers = Manager.instance.wrapperFileHandler.loadAll().toMutableList() + val unknownWrappers = + loadedWrappers.filter { CloudAPI.instance.getWrapperManager().getWrapperByHost(it.getHost()) == null } + if (unknownWrappers.isNotEmpty()) { + unknownWrappers.forEach { + commandSender.sendProperty("manager.command.reload.wrapper-changed", it.getName()) + } + } + loadedWrappers.toMutableList().removeAll(unknownWrappers) + loadedWrappers.forEach { + val cachedWrapper = CloudAPI.instance.getWrapperManager().getWrapperByHost(it.getHost())!! + val wrapperUpdater = cachedWrapper.getUpdater() + wrapperUpdater.setMaxSimultaneouslyStartingServices(it.getMaxSimultaneouslyStartingServices()) + wrapperUpdater.setMaxMemory(it.getMaxMemory()) + wrapperUpdater.update() + } + loadedWrappers.forEach { commandSender.sendProperty("manager.command.reload.wrapper-success", it.getName()) } + } + + private fun reloadServiceVersion() { + (CloudAPI.instance.getServiceVersionHandler() as ManagerServiceVersionHandler).reloadServiceVersions() + } + + private fun reloadJvmArguments() { + val jvmArgumentsConfigLoader = JvmArgumentsConfigLoader() + Manager.instance.jvmArgumentsConfig = jvmArgumentsConfigLoader.loadConfig() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ScreenCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ScreenCommand.kt new file mode 100644 index 000000000..49b836bbd --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ScreenCommand.kt @@ -0,0 +1,82 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceCommandSuggestionProvider +import eu.thesimplecloud.launcher.screens.IScreen +import eu.thesimplecloud.launcher.screens.session.ScreenSession +import eu.thesimplecloud.launcher.startup.Launcher + +@Command("screen", CommandType.CONSOLE, "cloud.command.screen") +class ScreenCommand : ICommandHandler { + + @CommandSubPath("join ", "Joins a screen") + fun screenCommand( + commandSender: ICommandSender, + @CommandArgument("name", ServiceCommandSuggestionProvider::class) name: String + ) { + val screen = handleScreenNotExist(commandSender, name) ?: return + Launcher.instance.screenManager.joinScreen(ScreenSession(screen, ScreenSession.ScreenCloseBehaviour.CLOSE)) + } + + @CommandSubPath("join -reopen", "Joins a screen and reopens the screen every time the service restarts") + fun screenCommandReopen( + commandSender: ICommandSender, + @CommandArgument("name", ServiceCommandSuggestionProvider::class) name: String + ) { + val screen = handleScreenNotExist(commandSender, name) ?: return + Launcher.instance.screenManager.joinScreen(ScreenSession(screen, ScreenSession.ScreenCloseBehaviour.REOPEN)) + } + + @CommandSubPath("join -keep", "Joins a screen and keeps it open after it closes") + fun screenCommandKeep( + commandSender: ICommandSender, + @CommandArgument("name", ServiceCommandSuggestionProvider::class) name: String + ) { + val screen = handleScreenNotExist(commandSender, name) ?: return + Launcher.instance.screenManager.joinScreen(ScreenSession(screen, ScreenSession.ScreenCloseBehaviour.KEEP_OPEN)) + } + + private fun handleScreenNotExist(commandSender: ICommandSender, name: String): IScreen? { + val screen = Launcher.instance.screenManager.getScreen(name) + if (screen == null) { + commandSender.sendProperty("manager.command.screen.not-exist") + return null + } + return screen + } + + @CommandSubPath("list", "Lists all screens") + fun listScreens(commandSender: ICommandSender) { + commandSender.sendProperty("manager.command.screen.list") + val screensString = Launcher.instance.screenManager.getAllScreens().joinToString { it.getName() } + commandSender.sendMessage(screensString) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownCommand.kt new file mode 100644 index 000000000..2e06cc5c4 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownCommand.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceCommandSuggestionProvider + +@Command("shutdown", CommandType.CONSOLE_AND_INGAME, "cloud.command.shutdown") +class ShutdownCommand : ICommandHandler { + + @CommandSubPath("", "Stops a service") + fun shutdown( + commandSender: ICommandSender, + @CommandArgument("name", ServiceCommandSuggestionProvider::class) service: ICloudService + ) { + service.shutdown() + commandSender.sendProperty("manager.command.shutdown.success") + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownGroupCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownGroupCommand.kt new file mode 100644 index 000000000..df8131816 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/ShutdownGroupCommand.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceGroupCommandSuggestionProvider + +@Command("shutdowngroup", CommandType.CONSOLE_AND_INGAME, "cloud.command.shutdowngroup") +class ShutdownGroupCommand : ICommandHandler { + + @CommandSubPath("", "Stops all services of a group") + fun startService( + commandSender: ICommandSender, + @CommandArgument( + "group", + ServiceGroupCommandSuggestionProvider::class + ) cloudServiceGroup: ICloudServiceGroup + ) { + if (cloudServiceGroup.getAllServices().isEmpty()) { + commandSender.sendProperty("manager.command.shutdowngroup.failure", cloudServiceGroup.getName()) + return + } + cloudServiceGroup.shutdownAllServices() + commandSender.sendProperty("manager.command.shutdowngroup.success", cloudServiceGroup.getName()) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartCommand.kt new file mode 100644 index 000000000..cd3ed2fd3 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartCommand.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceGroupCommandSuggestionProvider + +@Command("start", CommandType.CONSOLE_AND_INGAME, "cloud.command.start") +class StartCommand : ICommandHandler { + + @CommandSubPath("", "Starts a service") + fun startService( + commandSender: ICommandSender, + @CommandArgument( + "group", + ServiceGroupCommandSuggestionProvider::class + ) cloudServiceGroup: ICloudServiceGroup + ) { + startService(commandSender, cloudServiceGroup, 1) + } + + @CommandSubPath(" ", "Starts a service") + fun startService( + commandSender: ICommandSender, + @CommandArgument("group", ServiceGroupCommandSuggestionProvider::class) cloudServiceGroup: ICloudServiceGroup, + @CommandArgument("count") count: Int + ) { + for (i in 0 until count) { + cloudServiceGroup.startNewService() + } + commandSender.sendProperty("manager.command.start.success", count.toString(), cloudServiceGroup.getName()) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartStaticCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartStaticCommand.kt new file mode 100644 index 000000000..eb45a5a2d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/StartStaticCommand.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.start.configuration.ServiceStartConfiguration +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceGroupCommandSuggestionProvider + +@Command("startStatic", CommandType.CONSOLE_AND_INGAME, "cloud.command.startstatic") +class StartStaticCommand : ICommandHandler { + + @CommandSubPath("", "Starts a static service") + fun handleStartStatic( + commandSender: ICommandSender, + @CommandArgument("service", ServiceGroupCommandSuggestionProvider::class) serviceName: String + ) { + val runningService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) + if (runningService != null) { + commandSender.sendProperty("manager.command.startstatic.service-already-online") + return + } + val groupName = serviceName.split("-").dropLast(1).joinToString("-") + val numberString = serviceName.split("-").last() + val number = kotlin.runCatching { numberString.toInt() }.getOrNull() + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(groupName) + if (number == null || serviceGroup == null) { + commandSender.sendProperty("manager.command.startstatic.service-invalid") + return + } + + if (!serviceGroup.isStatic()) { + commandSender.sendProperty("manager.command.startstatic.group-not-static") + return + } + + Manager.instance.serviceHandler.startService(ServiceStartConfiguration(serviceGroup).setServiceNumber(number)) + commandSender.sendProperty("manager.command.startstatic.success") + } + +} + diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditGroupParameterCommandSuggestionProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditGroupParameterCommandSuggestionProvider.kt new file mode 100644 index 000000000..7bf57affa --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditGroupParameterCommandSuggestionProvider.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.utils.getAllFieldsFromClassAndSubClasses +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class EditGroupParameterCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + val fullCommandArray = fullCommand.split(" ") + val groupName = fullCommandArray[fullCommandArray.lastIndex - 1] + val group = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(groupName) + group ?: return emptyList() + val allFields = group::class.java.getAllFieldsFromClassAndSubClasses() + .filter { !Collection::class.java.isAssignableFrom(it.type) } + return allFields.filterNot { + it.name == "name" || + it.name == "serviceVersion" || + it.name == "wrapperName" + }.map { it.name } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditWrapperParameterCommandSuggestionProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditWrapperParameterCommandSuggestionProvider.kt new file mode 100644 index 000000000..a3fa3724d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/commands/provider/EditWrapperParameterCommandSuggestionProvider.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.commands.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.utils.getAllFieldsFromClassAndSubClasses +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperInfo +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class EditWrapperParameterCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + val allFields = DefaultWrapperInfo::class.java.getAllFieldsFromClassAndSubClasses() + .filter { !Collection::class.java.isAssignableFrom(it.type) } + return allFields.filterNot { + it.name == "name" || + it.name == "host" || + it.name == "authenticated" || + it.name == "usedMemory" || + it.name == "templatesReceived" || + it.name == "cpuUsage" || + it.name == "wrapperUpdater" || + it.name == "currentlyStartingServices" + }.map { it.name } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/JvmArgumentsConfigLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/JvmArgumentsConfigLoader.kt new file mode 100644 index 000000000..63b6dab8b --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/JvmArgumentsConfigLoader.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.base.core.jvm.JvmArgument +import eu.thesimplecloud.base.core.jvm.JvmArgumentsConfig +import java.io.File + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 12.06.2020 + * Time: 18:38 + */ +class JvmArgumentsConfigLoader : AbstractJsonLibConfigLoader( + JvmArgumentsConfig::class.java, + File(DirectoryPaths.paths.storagePath + "jvm-arguments.json"), + { JvmArgumentsConfig(listOf(JvmArgument(listOf("all"), listOf("-XX:-UseAdaptiveSizePolicy")))) }, + true +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/encryption/KeyConfigLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/encryption/KeyConfigLoader.kt new file mode 100644 index 000000000..39ef87a8f --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/encryption/KeyConfigLoader.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config.encryption + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import org.apache.commons.lang3.RandomStringUtils +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 12.09.2020 + * Time: 20:25 + * @author Frederick Baier + */ +class KeyConfigLoader : AbstractJsonLibConfigLoader( + String::class.java, + File(DirectoryPaths.paths.storagePath + ".hash-key"), + { RandomStringUtils.random(64) }, + true +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/mongo/DatabaseConfigLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/mongo/DatabaseConfigLoader.kt new file mode 100644 index 000000000..b7d5f0234 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/mongo/DatabaseConfigLoader.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config.mongo + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.base.manager.database.DatabaseConnectionInformation +import eu.thesimplecloud.base.manager.database.DatabaseType +import java.io.File + +class DatabaseConfigLoader : AbstractJsonLibConfigLoader( + DatabaseConnectionInformation::class.java, + File(DirectoryPaths.paths.storagePath + "database.json"), + { + DatabaseConnectionInformation( + "127.0.0.1", + 45678, + "cloud", + "simplecloud", + "cloudpassword", + "", + DatabaseType.MONGODB + ) + }, + false +) { +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfig.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfig.kt new file mode 100644 index 000000000..9c5c21330 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfig.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config.template + +import eu.thesimplecloud.api.template.impl.DefaultTemplate + + +class TemplatesConfig(val templates: HashSet) { +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfigLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfigLoader.kt new file mode 100644 index 000000000..8e16f1fd5 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/template/TemplatesConfigLoader.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config.template + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +class TemplatesConfigLoader : AbstractJsonLibConfigLoader( + TemplatesConfig::class.java, + File(DirectoryPaths.paths.storagePath + "templates.json"), + { TemplatesConfig(HashSet()) }, + false +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfig.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfig.kt new file mode 100644 index 000000000..ca43cdb89 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfig.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config.updater + +/** + * Created by IntelliJ IDEA. + * Date: 13.06.2020 + * Time: 07:45 + * @author Frederick Baier + */ +class ModuleUpdaterConfig( + val modules: List +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfigLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfigLoader.kt new file mode 100644 index 000000000..891393abf --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/config/updater/ModuleUpdaterConfigLoader.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.config.updater + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 13.06.2020 + * Time: 07:46 + * @author Frederick Baier + */ +class ModuleUpdaterConfigLoader : AbstractJsonLibConfigLoader( + ModuleUpdaterConfig::class.java, + File(DirectoryPaths.paths.storagePath, "updateable-modules.json"), + { + ModuleUpdaterConfig( + listOf( + "SimpleCloud-Chat+Tab", + "SimpleCloud-CloudFlare", + "SimpleCloud-HubCommand", + "SimpleCloud-InternalWrapper", + "SimpleCloud-Notify", + "SimpleCloud-Permission", + "SimpleCloud-Proxy", + "SimpleCloud-Rest", + "SimpleCloud-Sign", + "SimpleCloud-Statistics", + "SimpleCloud-NPC" + ) + ) + }, + true +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/AbstractOfflineCloudPlayerHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/AbstractOfflineCloudPlayerHandler.kt new file mode 100644 index 000000000..20396d5e5 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/AbstractOfflineCloudPlayerHandler.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database + +import eu.thesimplecloud.api.player.IOfflineCloudPlayer +import eu.thesimplecloud.api.utils.DatabaseExclude +import eu.thesimplecloud.jsonlib.GsonCreator + +/** + * Created by IntelliJ IDEA. + * Date: 12.09.2020 + * Time: 21:02 + * @author Frederick Baier + */ +abstract class AbstractOfflineCloudPlayerHandler : IOfflineCloudPlayerHandler { + + protected val databaseGson = GsonCreator().excludeAnnotations(DatabaseExclude::class.java).create() + + protected fun getPlayerWithLatestLogin(players: List): IOfflineCloudPlayer? { + return players.maxByOrNull { it.getLastLogin() } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseConnectionInformation.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseConnectionInformation.kt new file mode 100644 index 000000000..c226a4804 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseConnectionInformation.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database + + +open class DatabaseConnectionInformation( + val host: String, + val port: Int, + val databaseName: String, + val userName: String, + val password: String, + val collectionPrefix: String, + val databaseType: DatabaseType +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseType.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseType.kt new file mode 100644 index 000000000..92aa68c61 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/DatabaseType.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database + +/** + * Created by IntelliJ IDEA. + * Date: 17.06.2020 + * Time: 08:41 + * @author Frederick Baier + */ +enum class DatabaseType { + + MYSQL, + + MONGODB + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/IOfflineCloudPlayerHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/IOfflineCloudPlayerHandler.kt new file mode 100644 index 000000000..9112a1138 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/IOfflineCloudPlayerHandler.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database + +import eu.thesimplecloud.api.player.IOfflineCloudPlayer +import eu.thesimplecloud.api.player.OfflineCloudPlayer +import java.util.* + +interface IOfflineCloudPlayerHandler { + + /** + * Returns the [IOfflineCloudPlayer] found by the specified [playerUniqueId] + */ + fun getOfflinePlayer(playerUniqueId: UUID): IOfflineCloudPlayer? + + /** + * Returns the [IOfflineCloudPlayer] found by the specified [name] + */ + fun getOfflinePlayer(name: String): IOfflineCloudPlayer? + + /** + * Saves the specified [offlineCloudPlayer] to the database. + */ + fun saveCloudPlayer(offlineCloudPlayer: OfflineCloudPlayer) + + /** + * Returns the number of registered players + */ + fun getRegisteredPlayerCount(): Int + + /** + * Closes the connection to the database + */ + fun closeConnection() + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/MongoOfflineCloudPlayerHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/MongoOfflineCloudPlayerHandler.kt new file mode 100644 index 000000000..e112408d4 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/MongoOfflineCloudPlayerHandler.kt @@ -0,0 +1,133 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database + +import com.mongodb.ConnectionString +import com.mongodb.client.MongoClient +import com.mongodb.client.MongoDatabase +import com.mongodb.client.model.Filters +import com.mongodb.client.model.Indexes +import eu.thesimplecloud.api.player.IOfflineCloudPlayer +import eu.thesimplecloud.api.player.OfflineCloudPlayer +import eu.thesimplecloud.api.player.connection.DefaultPlayerAddress +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.jsonlib.JsonLib +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.bson.Document +import org.litote.kmongo.KMongo +import org.litote.kmongo.find +import org.litote.kmongo.findOne +import org.litote.kmongo.getCollection +import java.net.URLEncoder +import java.util.* + +class MongoOfflineCloudPlayerHandler(val databaseConnectionInformation: DatabaseConnectionInformation) : + AbstractOfflineCloudPlayerHandler() { + + private val mongoClient: MongoClient = createMongoClient() + val database: MongoDatabase = this.mongoClient.getDatabase(databaseConnectionInformation.databaseName) + private val collection = + database.getCollection(databaseConnectionInformation.collectionPrefix + "players") + + init { + //make a first request (the first request will take a very long time when using embed mongodb. Following requests will be way faster) + GlobalScope.launch { + collection.createIndex(Indexes.text("name")) + //loadCollection.createIndex(Indexes.text("uniqueId")) + + //dummy request + val playerUniqueId = UUID.randomUUID() + val dummyPlayer = getOfflinePlayer(playerUniqueId) + if (dummyPlayer == null) { + val playerConnection = + DefaultPlayerConnection(DefaultPlayerAddress("127.0.0.1", 0), "Test", playerUniqueId, true, 42) + saveCloudPlayer(OfflineCloudPlayer("Test", playerUniqueId, 1L, 1L, 1L, playerConnection)) + delay(100) + deletePlayer(playerUniqueId) + } + } + } + + private fun getConnectionString(): ConnectionString { + val host = databaseConnectionInformation.host + val port = databaseConnectionInformation.port + val databaseName = URLEncoder.encode(databaseConnectionInformation.databaseName,"utf-8") + val userName = URLEncoder.encode(databaseConnectionInformation.userName, "utf-8") + val password = URLEncoder.encode(databaseConnectionInformation.password,"utf-8") + if (password.isBlank() || userName.isBlank()) { + return ConnectionString("mongodb://$host:$port/?authSource=$databaseName") + } + + return ConnectionString("mongodb://$userName:$password@$host:$port/?authSource=$databaseName") + } + + private fun createMongoClient(): MongoClient { + return KMongo.createClient(getConnectionString()) + } + + private fun deletePlayer(playerUniqueId: UUID) { + this.collection.deleteOne(Filters.eq("uniqueId", playerUniqueId.toString())) + } + + override fun getOfflinePlayer(playerUniqueId: UUID): IOfflineCloudPlayer? { + val document = this.collection.findOne(Filters.eq("uniqueId", playerUniqueId.toString())) + ?: return null + return JsonLib.fromObject(document, databaseGson).getObject(OfflineCloudPlayer::class.java) + } + + override fun getOfflinePlayer(name: String): IOfflineCloudPlayer? { + val documents = this.collection.find("{ \$text: { \$search: \"$name\",\$caseSensitive :false } }") + val players = documents.map { + JsonLib.fromObject(it, databaseGson).getObject(OfflineCloudPlayer::class.java) + } + return getPlayerWithLatestLogin(players.toList()) + } + + @Synchronized + override fun saveCloudPlayer(offlineCloudPlayer: OfflineCloudPlayer) { + //load all properties so that the values are all set + val documentToSave = JsonLib.fromObject(offlineCloudPlayer, databaseGson).getObject(Document::class.java) + if (offlineCloudPlayer::class.java != OfflineCloudPlayer::class.java) throw IllegalStateException("Cannot save player of type " + offlineCloudPlayer::class.java.simpleName) + if (getOfflinePlayer(offlineCloudPlayer.getUniqueId()) != null) { + this.collection.replaceOne( + Filters.eq("uniqueId", offlineCloudPlayer.getUniqueId().toString()), + documentToSave + ) + } else { + this.collection.insertOne(documentToSave) + } + + } + + override fun getRegisteredPlayerCount(): Int { + return this.collection.countDocuments().toInt() + } + + override fun closeConnection() { + this.mongoClient.close() + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/SQLOfflineCloudPlayerHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/SQLOfflineCloudPlayerHandler.kt new file mode 100644 index 000000000..96a6e3a07 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/SQLOfflineCloudPlayerHandler.kt @@ -0,0 +1,166 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database + +import eu.thesimplecloud.api.player.IOfflineCloudPlayer +import eu.thesimplecloud.api.player.OfflineCloudPlayer +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.startup.Launcher +import java.sql.* +import java.util.* +import java.util.concurrent.TimeUnit + + +/** + * Created by IntelliJ IDEA. + * Date: 16.06.2020 + * Time: 14:18 + * @author Frederick Baier + */ +class SQLOfflineCloudPlayerHandler(private val databaseConnectionInformation: DatabaseConnectionInformation) : + AbstractOfflineCloudPlayerHandler() { + + var connection: Connection? = null + private set + + private val playerCollectionName = databaseConnectionInformation.collectionPrefix + "players" + + init { + runReconnectLoop() + createDatabaseAndIndicesIfNotExist() + } + + private fun createDatabaseAndIndicesIfNotExist() { + if (!doesTableExist()) { + val statement = + connection!!.prepareStatement("CREATE TABLE IF NOT EXISTS `$playerCollectionName` (`uniqueId` varchar(36), `name` varchar(16), `data` LONGBLOB)") + statement.executeUpdate() + createIndex("uniqueId") + createIndex("name") + } + } + + private fun runReconnectLoop() { + reconnect() + Launcher.instance.scheduler.scheduleAtFixedRate({ + reconnect() + }, 1, 1, TimeUnit.HOURS) + } + + private fun reconnect() = synchronized(this) { + closeConnection() + this.connection = + DriverManager.getConnection("jdbc:mysql://${databaseConnectionInformation.host}:${databaseConnectionInformation.port}/${databaseConnectionInformation.databaseName}?user=${databaseConnectionInformation.userName}&password=${databaseConnectionInformation.password}&serverTimezone=UTC&autoReconnect=true") + } + + private fun createIndex(columnName: String) { + val statement = connection!!.prepareStatement("ALTER TABLE $playerCollectionName ADD INDEX ($columnName)") + statement.executeUpdate() + } + + override fun getOfflinePlayer(playerUniqueId: UUID): IOfflineCloudPlayer? { + return loadPlayer(playerUniqueId.toString(), "uniqueId") + } + + override fun getOfflinePlayer(name: String): IOfflineCloudPlayer? { + return loadPlayer(name, "name") + } + + private fun loadPlayer(value: String, fieldName: String): IOfflineCloudPlayer? = synchronized(this) { + if (!exist(value, fieldName)) return null + val statement = + connection!!.prepareStatement("SELECT `data` FROM `$playerCollectionName` WHERE `$fieldName` = ?") + statement.setString(1, value) + val resultSet = statement.executeQuery() + val allDataStrings = getAllDataStringsFromResultSet(resultSet) + val players = allDataStrings.mapNotNull { loadPlayerFromJsonString(it) } + return getPlayerWithLatestLogin(players) + } + + private fun getAllDataStringsFromResultSet(resultSet: ResultSet): List { + val returnList = mutableListOf() + while (resultSet.next()) { + try { + val dataString = resultSet.getString("data") + returnList.add(dataString) + } catch (e: SQLException) { + //ignore exception + //it will be thrown 2 times before reaching "data" + } + } + return returnList + } + + private fun loadPlayerFromJsonString(jsonString: String): OfflineCloudPlayer? { + return JsonLib.fromJsonString(jsonString, databaseGson).getObject(OfflineCloudPlayer::class.java) + } + + override fun saveCloudPlayer(offlineCloudPlayer: OfflineCloudPlayer): Unit = synchronized(this) { + val newData = JsonLib.fromObject(offlineCloudPlayer, databaseGson).getAsJsonString() + if (!exist(offlineCloudPlayer.getUniqueId().toString(), "uniqueId")) { + val statement = + connection!!.prepareStatement("INSERT INTO `$playerCollectionName` (`uniqueId`, `name`, `data`) VALUES (?, ?, ?)") + statement.setString(1, offlineCloudPlayer.getUniqueId().toString()) + statement.setString(2, offlineCloudPlayer.getName()) + statement.setString(3, newData) + statement.executeUpdate() + } else { + val statement = + connection!!.prepareStatement("UPDATE `$playerCollectionName` SET `data` = ?, `name` = ? WHERE `uniqueId` = ?") + statement.setString(1, newData) + statement.setString(2, offlineCloudPlayer.getName()) + statement.setString(3, offlineCloudPlayer.getUniqueId().toString()) + statement.executeUpdate() + } + } + + override fun getRegisteredPlayerCount(): Int { + val statement = connection!!.prepareStatement("SELECT COUNT(*) FROM `$playerCollectionName`") + val resultSet = statement.executeQuery() + return if (!resultSet.next()) { + 0 + } else { + resultSet.getInt(1) + } + } + + override fun closeConnection() { + connection?.close() + } + + private fun exist(searchValue: String, fieldName: String): Boolean { + val prepareStatement = + connection!!.prepareStatement("SELECT `data` FROM `$playerCollectionName` WHERE `$fieldName` = ?") + prepareStatement.setString(1, searchValue) + val resultSet = prepareStatement.executeQuery() + return resultSet.next() + } + + private fun doesTableExist(): Boolean { + val meta: DatabaseMetaData = connection!!.metaData + val res = meta.getTables(null, null, this.playerCollectionName, arrayOf("TABLE")) + return res.next() + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/aes/AdvancedEncryption.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/aes/AdvancedEncryption.kt new file mode 100644 index 000000000..00de84c48 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/database/aes/AdvancedEncryption.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.database.aes + +import java.security.MessageDigest +import java.util.* +import javax.crypto.Cipher +import javax.crypto.spec.SecretKeySpec + +/** + * Created by IntelliJ IDEA. + * Date: 12.09.2020 + * Time: 20:12 + * @author Frederick Baier + */ + + +class AdvancedEncryption(keyString: String) { + private var secretKey: SecretKeySpec? = null + private var key: ByteArray = createKey(keyString) + + private fun createKey(myKey: String): ByteArray { + var sha: MessageDigest? = null + var key = myKey.toByteArray(charset("UTF-8")) + sha = MessageDigest.getInstance("SHA-1") + key = sha.digest(key) + key = key.copyOf(16) + secretKey = SecretKeySpec(key, "AES") + return key + } + + fun encrypt(strToEncrypt: String): String? { + val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") + cipher.init(Cipher.ENCRYPT_MODE, secretKey) + return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.toByteArray(charset("UTF-8")))) + } + + fun decrypt(strToDecrypt: String?): String? { + val cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING") + cipher.init(Cipher.DECRYPT_MODE, secretKey) + return String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))) + + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/events/CloudPlayerLoginRequestEvent.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/events/CloudPlayerLoginRequestEvent.kt new file mode 100644 index 000000000..b6251dd22 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/events/CloudPlayerLoginRequestEvent.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.events + +import eu.thesimplecloud.api.eventapi.ICancellable +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.player.ICloudPlayer + +class CloudPlayerLoginRequestEvent( + val cloudPlayer: ICloudPlayer +) : IEvent, ICancellable { + + private var cancelled: Boolean = false + var kickMessage: String = "§cLogin cancelled" + + + override fun isCancelled(): Boolean = this.cancelled + + override fun setCancelled(cancel: Boolean) { + this.cancelled = cancel + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/CloudServiceGroupFileHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/CloudServiceGroupFileHandler.kt new file mode 100644 index 000000000..82182e144 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/CloudServiceGroupFileHandler.kt @@ -0,0 +1,69 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.filehandler + +import eu.thesimplecloud.api.config.IFileHandler +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultLobbyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultProxyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultServerGroup +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +class CloudServiceGroupFileHandler : IFileHandler { + + + override fun save(value: ICloudServiceGroup) { + val file = getJsonFileForGroup(value) + JsonLib.fromObject(value).saveAsFile(file) + } + + override fun delete(value: ICloudServiceGroup) { + getJsonFileForGroup(value).delete() + } + + override fun loadAll(): Set { + val proxyGroups = + getAllFilesInDirectoryParsedAs(File(DirectoryPaths.paths.proxyGroupsPath), DefaultProxyGroup::class.java) + val lobbyGroups = + getAllFilesInDirectoryParsedAs(File(DirectoryPaths.paths.lobbyGroupsPath), DefaultLobbyGroup::class.java) + val serverGroups = + getAllFilesInDirectoryParsedAs(File(DirectoryPaths.paths.serverGroupsPath), DefaultServerGroup::class.java) + return proxyGroups.union(lobbyGroups).union(serverGroups) + } + + private fun getAllFilesInDirectoryParsedAs(directory: File, clazz: Class): List { + val list = directory.listFiles()?.map { JsonLib.fromJsonFile(it)?.getObjectOrNull(clazz) } ?: emptyList() + return list.filterNotNull() + } + + private fun getJsonFileForGroup(cloudServiceGroup: ICloudServiceGroup): File { + return when (cloudServiceGroup.getServiceType()) { + ServiceType.PROXY -> File(DirectoryPaths.paths.proxyGroupsPath, cloudServiceGroup.getName() + ".json") + ServiceType.LOBBY -> File(DirectoryPaths.paths.lobbyGroupsPath, cloudServiceGroup.getName() + ".json") + ServiceType.SERVER -> File(DirectoryPaths.paths.serverGroupsPath, cloudServiceGroup.getName() + ".json") + } + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/WrapperFileHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/WrapperFileHandler.kt new file mode 100644 index 000000000..a4465bd6b --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/filehandler/WrapperFileHandler.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.filehandler + +import eu.thesimplecloud.api.config.IFileHandler +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperInfo +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +class WrapperFileHandler : IFileHandler { + + private val directory = File(DirectoryPaths.paths.wrappersPath) + + override fun save(value: IWrapperInfo) { + JsonLib.fromObject(value).saveAsFile(getFile(value)) + } + + override fun delete(value: IWrapperInfo) { + getFile(value).delete() + } + + override fun loadAll(): Set = + directory.listFiles().mapNotNull { getWrapperInfoFromFile(it) }.toSet() + + + fun getFile(wrapperInfo: IWrapperInfo): File = File(directory, wrapperInfo.getName() + ".json") + + private fun getWrapperInfoFromFile(file: File): IWrapperInfo? { + return try { + JsonLib.fromJsonFile(file)?.getObject(DefaultWrapperInfo::class.java) + } catch (exception: IllegalArgumentException) { + file.delete() + null + } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudAPIImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudAPIImpl.kt new file mode 100644 index 000000000..e0cb93830 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudAPIImpl.kt @@ -0,0 +1,97 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.IEventManager +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.ILanguageManager +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.version.IServiceVersionHandler +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.sync.list.manager.ISynchronizedObjectListManager +import eu.thesimplecloud.api.sync.list.manager.SynchronizedObjectListManager +import eu.thesimplecloud.api.template.ITemplateManager +import eu.thesimplecloud.api.wrapper.IWrapperManager +import eu.thesimplecloud.base.manager.language.LanguageManagerImpl +import eu.thesimplecloud.base.manager.serviceversion.ManagerServiceVersionHandler +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.bootstrap.ICommunicationBootstrap + +class CloudAPIImpl : CloudAPI() { + + private val cloudPlayerManager = CloudPlayerManagerImpl() + private val cloudServiceGroupManager = CloudServiceGroupManagerImpl() + private val cloudServiceManager = CloudServiceManagerImpl() + private val commandExecuteManager = CommandExecuteManagerImpl() + private val templateManager = TemplateManagerImpl() + private val wrapperManager = WrapperManagerImpl() + private val eventManager = EventManagerImpl() + private val synchronizedObjectListManager = SynchronizedObjectListManager() + private val serviceVersionHandler = ManagerServiceVersionHandler() + private val languageManager = LanguageManagerImpl() + + init { + getCacheListManager().registerCacheList(getWrapperManager()) + getCacheListManager().registerCacheList(getCloudServiceManager()) + getCacheListManager().registerCacheList(getCloudServiceGroupManager()) + getCacheListManager().registerCacheList(getTemplateManager()) + getCacheListManager().registerCacheList(getCloudPlayerManager()) + } + + + override fun getCloudServiceGroupManager(): ICloudServiceGroupManager = this.cloudServiceGroupManager + + override fun getCloudServiceManager(): ICloudServiceManager = this.cloudServiceManager + + override fun getCloudPlayerManager(): ICloudPlayerManager = this.cloudPlayerManager + + override fun getEventManager(): IEventManager = this.eventManager + + override fun getCommandExecuteManager(): ICommandExecuteManager = this.commandExecuteManager + + override fun getThisSidesCommunicationBootstrap(): ICommunicationBootstrap = Manager.instance.communicationServer + + override fun getSynchronizedObjectListManager(): ISynchronizedObjectListManager = this.synchronizedObjectListManager + + override fun getServiceVersionHandler(): IServiceVersionHandler = this.serviceVersionHandler + + override fun getLanguageManager(): ILanguageManager = this.languageManager + + override fun getTemplateManager(): ITemplateManager = this.templateManager + + override fun getWrapperManager(): IWrapperManager = this.wrapperManager + + override fun getThisSidesName(): String = "Manager" + + override fun getThisSidesNetworkComponent(): INetworkComponent { + return INetworkComponent.MANAGER_COMPONENT + } + + override fun getThisSidesCloudModule(): ICloudModule = Manager.instance + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceGroupManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceGroupManagerImpl.kt new file mode 100644 index 000000000..b96c6f766 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceGroupManagerImpl.kt @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.service.start.future.IServiceStartPromise +import eu.thesimplecloud.api.service.start.future.ServiceStartPromise +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.impl.AbstractCloudServiceGroupManager +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class CloudServiceGroupManagerImpl : AbstractCloudServiceGroupManager() { + + + override fun createServiceGroup(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise { + val promise = CommunicationPromise() + if (getServiceGroupByName(cloudServiceGroup.getName()) == null) { + update(cloudServiceGroup) + promise.trySuccess(cloudServiceGroup) + } else { + promise.setFailure(IllegalArgumentException("The name of the specified group is already in use")) + } + return promise + } + + override fun update( + value: ICloudServiceGroup, + fromPacket: Boolean, + isCalledFromDelete: Boolean + ): ICommunicationPromise { + Manager.instance.cloudServiceGroupFileHandler.save(value) + return super.update(value, fromPacket, isCalledFromDelete) + } + + override fun startNewService(serviceStartConfiguration: IServiceStartConfiguration): IServiceStartPromise { + val service = try { + Manager.instance.serviceHandler.startService(serviceStartConfiguration) + } catch (ex: IllegalArgumentException) { + //catch IllegalArgumentException. It will be thrown when the service to start is already registered. + return ServiceStartPromise(CommunicationPromise.failed(ex)) + } + return ServiceStartPromise(CommunicationPromise.of(service)) + } + + override fun delete(value: ICloudServiceGroup, fromPacket: Boolean): ICommunicationPromise { + Manager.instance.cloudServiceGroupFileHandler.delete(value) + return super.delete(value, fromPacket) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceManagerImpl.kt new file mode 100644 index 000000000..78bad202d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CloudServiceManagerImpl.kt @@ -0,0 +1,104 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.service.CloudServiceConnectedEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.exception.UnreachableComponentException +import eu.thesimplecloud.api.listenerextension.cloudListener +import eu.thesimplecloud.api.network.packets.service.PacketIOCopyService +import eu.thesimplecloud.api.network.packets.service.PacketIOStopCloudService +import eu.thesimplecloud.api.network.packets.service.PacketIOWrapperStartService +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.service.impl.AbstractCloudServiceManager +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher +import java.io.File +import java.text.SimpleDateFormat +import java.util.stream.Collectors + +class CloudServiceManagerImpl : AbstractCloudServiceManager() { + + override fun stopService(cloudService: ICloudService): ICommunicationPromise { + Launcher.instance.screenManager.getScreen(cloudService.getName()).let { + if (it != null) { + it.getAllSavedMessages().parallelStream().collect(Collectors.joining("\n"))?.let { screenMessage -> + val groupName = cloudService.getServiceGroup().getName() + val file = File("logs/$groupName/") + if (!file.exists()) file.mkdirs() + val date = SimpleDateFormat("yyyy.MM.dd-HH:mm:ss").format(System.currentTimeMillis()) + File("${file.absolutePath}/${cloudService.getName()}-$date.txt").writeText(screenMessage) + } + } + } + + when (cloudService.getState()) { + ServiceState.CLOSED -> { + return CommunicationPromise.failed(IllegalStateException("Service is already closed")) + } + ServiceState.PREPARED -> { + Manager.instance.serviceHandler.removeServiceFromQueue(cloudService) + cloudService.setState(ServiceState.CLOSED) + CloudAPI.instance.getCloudServiceManager().delete(cloudService) + return CommunicationPromise.UNIT_PROMISE + } + ServiceState.STARTING, ServiceState.VISIBLE, ServiceState.INVISIBLE -> { + val wrapper = cloudService.getWrapper() + val wrapperClient = Manager.instance.communicationServer.getClientManager() + .getClientByClientValue(wrapper) + wrapperClient?.sendUnitQuery(PacketIOStopCloudService(cloudService.getName())) + } + } + + return cloudListener() + .addCondition { it.cloudService == cloudService } + .unregisterAfterCall() + .toUnitPromise() + } + + override fun startService(cloudService: ICloudService): ICommunicationPromise { + if (cloudService.isActive() || cloudService.getState() == ServiceState.CLOSED) throw IllegalStateException("Can not start started service.") + val wrapper = cloudService.getWrapper() + val wrapperClient = Manager.instance.communicationServer.getClientManager().getClientByClientValue(wrapper) + check(wrapperClient != null) { "Can not find client of wrapper to start service ${cloudService.getName()} on." } + wrapperClient.sendUnitQuery(PacketIOWrapperStartService(cloudService.getName())) + return cloudListener() + .addCondition { it.cloudService == cloudService } + .unregisterAfterCall() + .toUnitPromise() + } + + override fun copyService(cloudService: ICloudService, path: String): ICommunicationPromise { + if (!cloudService.isActive()) + return CommunicationPromise.failed(IllegalStateException("Cannot copy inactive service")) + val wrapper = cloudService.getWrapper() + val wrapperClient = Manager.instance.communicationServer.getClientManager() + .getClientByClientValue(wrapper) + wrapperClient ?: return CommunicationPromise.failed(UnreachableComponentException("Wrapper is not reachable")) + return wrapperClient.sendUnitQuery(PacketIOCopyService(cloudService, path), 20 * 1000) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CommandExecuteManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CommandExecuteManagerImpl.kt new file mode 100644 index 000000000..690c998a4 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/CommandExecuteManagerImpl.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.network.component.ManagerComponent +import eu.thesimplecloud.api.network.packets.screen.PacketIOExecuteCommand +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.startup.Launcher + +class CommandExecuteManagerImpl : ICommandExecuteManager { + + override fun executeCommand(commandExecutable: ICommandExecutable, command: String) { + if (commandExecutable is ManagerComponent) { + executeCommandOnManager("cloud $command") + } + if (commandExecutable !is INetworkComponent) return + + val networkComponentType = commandExecutable.getNetworkComponentType() + val wrapperClient = if (commandExecutable is ICloudService) { + Manager.instance.communicationServer.getClientManager() + .getClientByClientValue(commandExecutable.getWrapper()) + } else { + Manager.instance.communicationServer.getClientManager().getClientByClientValue(commandExecutable) + } + wrapperClient?.sendUnitQuery(PacketIOExecuteCommand(networkComponentType, commandExecutable.getName(), command)) + } + + private fun executeCommandOnManager(command: String) { + val consoleSender = Launcher.instance.consoleSender + Launcher.instance.commandManager.handleCommand(command, consoleSender) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/EventManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/EventManagerImpl.kt new file mode 100644 index 000000000..dbb7404f0 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/EventManagerImpl.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.eventapi.BasicEventManager +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.api.extension.sendPacketToAllAuthenticatedNonWrapperClients +import eu.thesimplecloud.api.network.packets.event.PacketIOCallEvent +import eu.thesimplecloud.base.manager.startup.Manager + +class EventManagerImpl : BasicEventManager() { + + override fun call(event: IEvent, fromPacket: Boolean) { + super.call(event, fromPacket) + if (event is ISynchronizedEvent) + Manager.instance.communicationServer.getClientManager() + .sendPacketToAllAuthenticatedNonWrapperClients(PacketIOCallEvent(event)) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/TemplateManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/TemplateManagerImpl.kt new file mode 100644 index 000000000..505d3bcfe --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/TemplateManagerImpl.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.template.impl.DefaultTemplate +import eu.thesimplecloud.api.template.impl.DefaultTemplateManager +import eu.thesimplecloud.base.manager.config.template.TemplatesConfigLoader +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class TemplateManagerImpl : DefaultTemplateManager() { + + private val templatesConfigLoader = TemplatesConfigLoader() + + override fun update( + value: ITemplate, + fromPacket: Boolean, + isCalledFromDelete: Boolean + ): ICommunicationPromise { + val result = super.update(value, fromPacket, isCalledFromDelete) + val templateConfig = this.templatesConfigLoader.loadConfig() + templateConfig.templates.removeIf { it.getName().equals(value.getName(), true) } + templateConfig.templates.add(value as DefaultTemplate) + templatesConfigLoader.saveConfig(templateConfig) + + if (!value.getDirectory().exists()) { + value.getDirectory().mkdirs() + } + return result + } + + override fun delete(value: ITemplate, fromPacket: Boolean): ICommunicationPromise { + val result = super.delete(value, fromPacket) + + val templateConfig = this.templatesConfigLoader.loadConfig() + templateConfig.templates.removeIf { it.getName().equals(value.getName(), true) } + templatesConfigLoader.saveConfig(templateConfig) + return result + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/WrapperManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/WrapperManagerImpl.kt new file mode 100644 index 000000000..5e25fff32 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/impl/WrapperManagerImpl.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.impl + +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperManager +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class WrapperManagerImpl : DefaultWrapperManager() { + + override fun update( + value: IWrapperInfo, + fromPacket: Boolean, + isCalledFromDelete: Boolean + ): ICommunicationPromise { + Manager.instance.wrapperFileHandler.save(value) + return super.update(value, fromPacket, isCalledFromDelete) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/ingamecommands/IngameCommandUpdater.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/ingamecommands/IngameCommandUpdater.kt new file mode 100644 index 000000000..f8d19e598 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/ingamecommands/IngameCommandUpdater.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.ingamecommands + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.event.command.CommandRegisteredEvent +import eu.thesimplecloud.launcher.startup.Launcher + +class IngameCommandUpdater : IListener { + + private var ingameCommandList: Collection = emptyList() + + init { + CloudAPI.instance.getGlobalPropertyHolder() + .setProperty("simplecloud-ingamecommands", this.ingameCommandList.toTypedArray()) + CloudAPI.instance.getEventManager().registerListener(Manager.instance, this) + } + + + @CloudEventHandler + fun on(event: CommandRegisteredEvent) { + this.ingameCommandList = Launcher.instance.commandManager.getAllIngameCommandPrefixes() + CloudAPI.instance.getGlobalPropertyHolder() + .setProperty("simplecloud-ingamecommands", this.ingameCommandList.toTypedArray()) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/language/LanguageManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/language/LanguageManagerImpl.kt new file mode 100644 index 000000000..7437caf1c --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/language/LanguageManagerImpl.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.language + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.LanguageManager +import eu.thesimplecloud.api.language.LoadedLanguageFile +import eu.thesimplecloud.api.network.packets.language.PacketIOLanguage +import eu.thesimplecloud.base.manager.startup.Manager + +/** + * Created by IntelliJ IDEA. + * Date: 31.10.2020 + * Time: 23:06 + * @author Frederick Baier + */ +class LanguageManagerImpl : LanguageManager() { + + override fun registerLanguageFile(cloudModule: ICloudModule, languageFile: LoadedLanguageFile) { + super.registerLanguageFile(cloudModule, languageFile) + + val allServices = CloudAPI.instance.getCloudServiceManager().getAllCachedObjects() + val allServiceClients = allServices.map { + Manager.instance.communicationServer.getClientManager().getClientByClientValue(it) + } + val packet = PacketIOLanguage(this.getAllProperties()) + allServiceClients.filterNotNull().forEach { it.sendUnitQuery(packet) } + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/CloudListener.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/CloudListener.kt new file mode 100644 index 000000000..3842b6ba9 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/CloudListener.kt @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.listener + +import eu.thesimplecloud.api.event.player.CloudPlayerLoginEvent +import eu.thesimplecloud.api.event.player.CloudPlayerUnregisteredEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.event.module.ModuleUnloadedEvent +import eu.thesimplecloud.launcher.screens.session.ScreenSession +import eu.thesimplecloud.launcher.startup.Launcher + +class CloudListener : IListener { + + @CloudEventHandler + fun on(event: CloudServiceUnregisteredEvent) { + Launcher.instance.consoleSender.sendProperty("manager.service.stopped", event.cloudService.getName()) + + val activeSession = Launcher.instance.screenManager.getActiveScreenSession() + activeSession?.let { + if (activeSession.screen.getName().equals(event.cloudService.getName(), true)) { + if (activeSession.screenCloseBehaviour == ScreenSession.ScreenCloseBehaviour.CLOSE) + Launcher.instance.screenManager.leaveActiveScreen() + } + } + Launcher.instance.screenManager.unregisterScreen(event.cloudService.getName()) + } + + @CloudEventHandler + fun on(event: ModuleUnloadedEvent) { + Manager.instance.packetRegistry.unregisterAllPackets(event.module.cloudModule) + } + + @CloudEventHandler + fun on(event: CloudPlayerLoginEvent) { + event.getCloudPlayer().then { + Launcher.instance.consoleSender + .sendProperty( + "manager.player.connected", + it.getName(), + it.getUniqueId().toString(), + it.getPlayerConnection().getAddress().getHostname(), + it.getConnectedProxyName() + ) + } + + } + + @CloudEventHandler + fun on(event: CloudPlayerUnregisteredEvent) { + val player = event.cloudPlayer + + Launcher.instance.consoleSender + .sendProperty( + "manager.player.disconnected", player.getName(), player.getUniqueId().toString(), + player.getPlayerConnection().getAddress().getHostname() + ) + + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/ModuleEventListener.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/ModuleEventListener.kt new file mode 100644 index 000000000..6b8d014db --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/listener/ModuleEventListener.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.listener + +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.launcher.event.module.ModuleLoadedEvent +import eu.thesimplecloud.launcher.event.module.ModuleUnloadedEvent +import eu.thesimplecloud.launcher.startup.Launcher + +class ModuleEventListener : IListener { + + @CloudEventHandler + fun handleLoad(event: ModuleLoadedEvent) { + val module = event.module + Launcher.instance.consoleSender.sendProperty( + "manager.module.loaded", + module.fileContent.name, + module.fileContent.author + ) + } + + @CloudEventHandler + fun handleUnload(event: ModuleUnloadedEvent) { + val module = event.module + Launcher.instance.commandManager.unregisterCommands(module.cloudModule) + Launcher.instance.consoleSender.sendProperty( + "manager.module.unload", + module.fileContent.name, + module.fileContent.author + ) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInCloudClientLogin.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInCloudClientLogin.kt new file mode 100644 index 000000000..1f9a41325 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInCloudClientLogin.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.network.packets.language.PacketIOLanguage +import eu.thesimplecloud.api.network.packets.serviceversion.PacketIOServiceVersions +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClient +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClientValue +import eu.thesimplecloud.launcher.startup.Launcher + +@Suppress("UNCHECKED_CAST") +class PacketInCloudClientLogin() : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val host = connection.getHost()!! + val cloudClientType = this.jsonLib.getObject("cloudClientType", NetworkComponentType::class.java) + ?: return contentException("cloudClientType") + connection as IConnectedClient + CloudAPI.instance.getWrapperManager().sendAllCachedObjectsToConnection(connection).awaitCoroutine() + CloudAPI.instance.getCloudServiceManager().sendAllCachedObjectsToConnection(connection).awaitCoroutine() + CloudAPI.instance.getTemplateManager().sendAllCachedObjectsToConnection(connection).awaitCoroutine() + CloudAPI.instance.getCloudServiceGroupManager().sendAllCachedObjectsToConnection(connection).awaitCoroutine() + connection.sendUnitQuery(PacketIOServiceVersions(CloudAPI.instance.getServiceVersionHandler().getAllVersions())) + .awaitCoroutine() + when (cloudClientType) { + NetworkComponentType.SERVICE -> { + val name = this.jsonLib.getString("name") ?: return contentException("name") + val cloudService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) + ?: return failure(NoSuchElementException("Service not found")) + connection.setClientValue(cloudService) + connection.sendUnitQuery(PacketIOLanguage(CloudAPI.instance.getLanguageManager().getAllProperties())) + cloudService.setAuthenticated(true) + CloudAPI.instance.getCloudServiceManager().update(cloudService) + CloudAPI.instance.getCloudServiceManager().sendUpdateToConnection(cloudService, connection) + .awaitCoroutine() + Launcher.instance.consoleSender.sendProperty("manager.login.service", cloudService.getName()) + } + NetworkComponentType.WRAPPER -> { + val wrapperInfo = CloudAPI.instance.getWrapperManager().getWrapperByHost(host) + ?: return failure(NoSuchElementException("Wrapper not found")) + connection.setClientValue(wrapperInfo) + wrapperInfo.setAuthenticated(true) + CloudAPI.instance.getWrapperManager().update(wrapperInfo) + CloudAPI.instance.getWrapperManager().sendUpdateToConnection(wrapperInfo, connection).awaitCoroutine() + connection.sendUnitQuery(PacketOutJvmArguments(Manager.instance.jvmArgumentsConfig)).awaitCoroutine() + connection.sendUnitQuery(PacketOutSetWrapperName(wrapperInfo.getName())).awaitCoroutine() + Launcher.instance.consoleSender.sendProperty("manager.login.wrapper", wrapperInfo.getName()) + } + + else -> {} + } + + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInGetTabSuggestions.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInGetTabSuggestions.kt new file mode 100644 index 000000000..91b303532 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInGetTabSuggestions.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 19:05 + */ +class PacketInGetTabSuggestions() : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val command = this.jsonLib.getString("command") ?: return contentException("command") + val uuid = this.jsonLib.getObject("uuid", UUID::class.java) ?: return contentException("uuid") + + val player = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uuid) ?: return CommunicationPromise.failed( + NoSuchPlayerException(uuid.toString()) + ) + + return CommunicationPromise.of( + Launcher.instance.commandManager.getAvailableTabCompleteArgs(command, player).toTypedArray() + ) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInScreenMessage.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInScreenMessage.kt new file mode 100644 index 000000000..2394dc230 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketInScreenMessage.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher + +class PacketInScreenMessage : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val cloudClientType = this.jsonLib.getObject("cloudClientType", NetworkComponentType::class.java) + ?: return contentException("cloudClientType") + val name = this.jsonLib.getString("name") ?: return contentException("name") + val message = this.jsonLib.getString("message") ?: return contentException("message") + + val commandExecutable: ICommandExecutable? = when (cloudClientType) { + NetworkComponentType.SERVICE -> CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) + NetworkComponentType.WRAPPER -> CloudAPI.instance.getWrapperManager().getWrapperByName(name) + else -> throw IllegalArgumentException("NetworkComponentType") + } + commandExecutable ?: return failure(NoSuchElementException("Cannot find service / wrapper by name: $name")) + + val screenManager = Launcher.instance.screenManager + screenManager.addScreenMessage(commandExecutable, "[$name]$message") + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutJvmArguments.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutJvmArguments.kt new file mode 100644 index 000000000..fcab8e85d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutJvmArguments.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets + +import eu.thesimplecloud.base.core.jvm.JvmArgumentsConfig +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 12.06.2020 + * Time: 18:55 + */ +class PacketOutJvmArguments() : ObjectPacket() { + + constructor(jvmArgumentsConfig: JvmArgumentsConfig) : this() { + value = jvmArgumentsConfig + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutReloadExistingModules.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutReloadExistingModules.kt new file mode 100644 index 000000000..e2d4f03d4 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutReloadExistingModules.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketOutReloadExistingModules : JsonPacket() { + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutSetWrapperName.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutSetWrapperName.kt new file mode 100644 index 000000000..a831d4bcc --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/PacketOutSetWrapperName.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket + +class PacketOutSetWrapperName() : ObjectPacket() { + + constructor(name: String) : this() { + this.value = name + } + + override suspend fun handle(connection: IConnection) = unit() +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInCreateCloudPlayer.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInCreateCloudPlayer.kt new file mode 100644 index 000000000..0c207af78 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInCreateCloudPlayer.kt @@ -0,0 +1,73 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.player + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.OfflineCloudPlayer +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.api.player.impl.CloudPlayer +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.concurrent.ConcurrentHashMap + +class PacketInCreateCloudPlayer() : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerConnection = this.jsonLib.getObject("playerConnection", DefaultPlayerConnection::class.java) + ?: return contentException("playerConnection") + val proxyName = this.jsonLib.getString("proxyName") ?: return contentException("proxyName") + val offlinePlayer = Manager.instance.offlineCloudPlayerHandler.getOfflinePlayer(playerConnection.getUniqueId()) + val cloudPlayer = if (offlinePlayer == null) { + CloudPlayer( + playerConnection.getName(), + playerConnection.getUniqueId(), + System.currentTimeMillis(), + System.currentTimeMillis(), + 0L, + proxyName, + null, + playerConnection, + Maps.newConcurrentMap() + ) + } else { + CloudPlayer( + playerConnection.getName(), + playerConnection.getUniqueId(), + offlinePlayer.getFirstLogin(), + System.currentTimeMillis(), + offlinePlayer.getOnlineTime(), + proxyName, + null, + playerConnection, + ConcurrentHashMap(offlinePlayer.getProperties() as Map>) + ) + } + CloudAPI.instance.getCloudPlayerManager().update(cloudPlayer) + Manager.instance.offlineCloudPlayerHandler.saveCloudPlayer(cloudPlayer.toOfflinePlayer() as OfflineCloudPlayer) + return success(cloudPlayer) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerConnectToServer.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerConnectToServer.kt new file mode 100644 index 000000000..0e46cbeb9 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerConnectToServer.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.api.exception.NoSuchServiceException +import eu.thesimplecloud.api.player.impl.CloudPlayer +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketInPlayerConnectToServer() : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val uniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val serviceName = this.jsonLib.getString("serviceName") ?: return contentException("serviceName") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) ?: return failure( + NoSuchPlayerException("Player cannot be found") + ) + cloudPlayer as CloudPlayer + /* + val oldConnectedServer = cloudPlayer.getConnectedServer() + oldConnectedServer?.let { + val oldClient = Manager.instance.communicationServer.getClientManager().getClientByClientValue(it) + oldClient?.sendUnitQuery(PacketIORemoveCloudPlayer(cloudPlayer.getUniqueId())) + } + */ + val newService = + CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) ?: return failure( + NoSuchServiceException("New service cannot be found") + ) + val newServiceClient = + Manager.instance.communicationServer.getClientManager().getClientByClientValue(newService) + ?: return failure(NoSuchServiceException("New service is not connected to the manager")) + return CloudAPI.instance.getCloudPlayerManager().sendUpdateToConnection(cloudPlayer, newServiceClient) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerExecuteCommand.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerExecuteCommand.kt new file mode 100644 index 000000000..868d2acf6 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerExecuteCommand.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.* + +class PacketInPlayerExecuteCommand() : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val cloudPlayer = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) ?: return failure( + NoSuchPlayerException("Cannot find player by UUID: $playerUniqueId") + ) + val command = this.jsonLib.getString("command") ?: return contentException("command") + try { + Launcher.instance.commandManager.handleCommand(command, cloudPlayer) + } catch (ex: Exception) { + cloudPlayer.sendMessage("§cAn error occurred while executing the command.") + throw ex + } + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerLoginRequest.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerLoginRequest.kt new file mode 100644 index 000000000..78f9a2eb3 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInPlayerLoginRequest.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.dto.PlayerLoginRequestResult +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.base.manager.events.CloudPlayerLoginRequestEvent +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketInPlayerLoginRequest() : ObjectPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(value) ?: return failure( + NoSuchPlayerException("Player cannot be found") + ) + val loginEvent = CloudPlayerLoginRequestEvent(cloudPlayer) + CloudAPI.instance.getEventManager().call(loginEvent) + return success(PlayerLoginRequestResult(loginEvent.isCancelled(), loginEvent.kickMessage)) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInTeleportOtherService.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInTeleportOtherService.kt new file mode 100644 index 000000000..d48f95a26 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketInTeleportOtherService.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.api.exception.NoSuchServiceException +import eu.thesimplecloud.api.location.SimpleLocation +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketInTeleportOtherService : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val playerUniqueId = + this.jsonLib.getObject("playerUniqueId", UUID::class.java) ?: return contentException("playerUniqueId") + val serviceName = this.jsonLib.getString("serviceName") ?: return contentException("serviceName") + val simpleLocation = this.jsonLib.getObject("simpleLocation", SimpleLocation::class.java) + ?: return contentException("simpleLocation") + val cloudPlayer = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(playerUniqueId) ?: return failure( + NoSuchPlayerException("Player cannot be found") + ) + val service = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) ?: return failure( + NoSuchServiceException("Service cannot be found") + ) + if (service.isProxy()) + return failure(IllegalArgumentException("Cannot connect a player to a proxy service.")) + return cloudPlayer.teleport(simpleLocation.toServiceLocation(serviceName)) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketOutGetPlayerOnlineStatus.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketOutGetPlayerOnlineStatus.kt new file mode 100644 index 000000000..54e5da27f --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/player/PacketOutGetPlayerOnlineStatus.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.player + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 10.04.2020 + * Time: 21:28 + */ +class PacketOutGetPlayerOnlineStatus() : ObjectPacket() { + + constructor(uuid: UUID) : this() { + this.value = uuid + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return unit() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/template/PacketInGetTemplates.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/template/PacketInGetTemplates.kt new file mode 100644 index 000000000..d9363fdb0 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/network/packets/template/PacketInGetTemplates.kt @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.network.packets.template + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.filetransfer.directory.IDirectorySync +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher +import java.io.File + +class PacketInGetTemplates() : JsonPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val wrapperByHost = CloudAPI.instance.getWrapperManager().getWrapperByHost(connection.getHost()!!) + ?: throw IllegalStateException("No Wrapper object found for Wrapper by host " + connection.getHost()) + Launcher.instance.consoleSender.sendProperty("manager.templates.synchronization", wrapperByHost.getName()) + val templatesDirectorySync = connection.getCommunicationBootstrap().getDirectorySyncManager() + .getDirectorySync(File(DirectoryPaths.paths.templatesPath)) + val modulesDirectorySync = connection.getCommunicationBootstrap().getDirectorySyncManager() + .getDirectorySync(File(DirectoryPaths.paths.modulesPath)) + syncDirectory(templatesDirectorySync, connection) + syncDirectory(modulesDirectorySync, connection) + Launcher.instance.consoleSender.sendProperty( + "manager.templates.synchronization.complete", + wrapperByHost.getName() + ) + return unit() + } + + private fun syncDirectory(directorySync: IDirectorySync?, connection: IConnection) { + checkNotNull(directorySync) { "Failed to send modules and templates to a connected wrapper." } + val promise = directorySync.syncDirectory(connection) + promise.awaitUninterruptibly() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/IPacketRegistry.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/IPacketRegistry.kt new file mode 100644 index 000000000..24415721f --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/IPacketRegistry.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.packet + +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.BytePacket +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import org.reflections.Reflections + +interface IPacketRegistry { + + /** + * Registers a packet + */ + fun registerPacket(cloudModule: ICloudModule, packetClass: Class) + + /** + * Registers all Packets in the specified [packages] + */ + fun registerPacketsByPackage(cloudModule: ICloudModule, vararg packages: String) { + for (packageName in packages) { + val reflections = Reflections(packageName) + val allClasses = reflections.getSubTypesOf(IPacket::class.java) + .union(reflections.getSubTypesOf(JsonPacket::class.java)) + .union(reflections.getSubTypesOf(ObjectPacket::class.java)) + .union(reflections.getSubTypesOf(BytePacket::class.java)) + .filter { it != JsonPacket::class.java && it != BytePacket::class.java && it != ObjectPacket::class.java } + + allClasses.forEach { packetClass -> registerPacket(cloudModule, packetClass) } + } + } + + /** + * Unregisters a packet + */ + fun unregisterAllPackets(cloudModule: ICloudModule) + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/PacketRegistry.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/PacketRegistry.kt new file mode 100644 index 000000000..816ff6c74 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/packet/PacketRegistry.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.packet + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket + +class PacketRegistry : IPacketRegistry { + + private val registeredPackets = Maps.newConcurrentMap>>() + + override fun registerPacket(cloudModule: ICloudModule, packetClass: Class) { + val list = this.registeredPackets.getOrPut(cloudModule) { ArrayList() } + list.add(packetClass) + val packetManager = Manager.instance.communicationServer.getPacketManager() + packetManager.registerPacket(packetClass) + } + + override fun unregisterAllPackets(cloudModule: ICloudModule) { + val list = this.registeredPackets[cloudModule] ?: emptyList>() + list.forEach { Manager.instance.communicationServer.getPacketManager().unregisterPacket(it) } + this.registeredPackets.remove(cloudModule) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/LoadOfflineCloudPlayer.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/LoadOfflineCloudPlayer.kt new file mode 100644 index 000000000..15a3db056 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/LoadOfflineCloudPlayer.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.player + +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.api.property.Property +import java.util.* + +open class LoadOfflineCloudPlayer( + val name: String, + val uniqueId: UUID, + val firstLogin: Long, + val lastLogin: Long, + val onlineTime: Long, + val lastPlayerConnection: DefaultPlayerConnection, + var propertyMap: Map> +) \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/PlayerUnregisterScheduler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/PlayerUnregisterScheduler.kt new file mode 100644 index 000000000..85c94a9f0 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/PlayerUnregisterScheduler.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.base.manager.network.packets.player.PacketOutGetPlayerOnlineStatus +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 10.04.2020 + * Time: 21:35 + */ +class PlayerUnregisterScheduler { + + fun startScheduler() { + Launcher.instance.scheduler.scheduleAtFixedRate({ + CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().forEach { player -> + + checkPlayerOnlineStatus(player).then { + if (!it) { + CloudAPI.instance.getCloudPlayerManager().delete(player) + } + } + + } + }, 30L, 30, TimeUnit.SECONDS) + } + + private fun checkPlayerOnlineStatus(cloudPlayer: ICloudPlayer): ICommunicationPromise { + val connectedProxy = cloudPlayer.getConnectedProxy() ?: return CommunicationPromise.of(false) + + val client = Manager.instance.communicationServer.getClientManager().getClientByClientValue(connectedProxy) + ?: return CommunicationPromise.of(false) + + return client.sendQuery(PacketOutGetPlayerOnlineStatus(cloudPlayer.getUniqueId())) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/exception/OfflinePlayerLoadException.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/exception/OfflinePlayerLoadException.kt new file mode 100644 index 000000000..a70055b43 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/player/exception/OfflinePlayerLoadException.kt @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.player.exception + +class OfflinePlayerLoadException(message: String, exception: java.lang.Exception) : Exception(message, exception) { +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/IServiceHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/IServiceHandler.kt new file mode 100644 index 000000000..f844f6a95 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/IServiceHandler.kt @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.service + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +interface IServiceHandler { + + /** + * Starts the specified [count] of services and returns them in a list + * @return all new services. + */ + fun startServicesByGroup(cloudServiceGroup: ICloudServiceGroup, count: Int = 1): List + + /** + * Starts the specified service. + * @param startConfiguration the configuration with the information to start the new service. + * @return the new service + */ + fun startService(startConfiguration: IServiceStartConfiguration): ICloudService + + /** + * Removes the specified service from the queue + * @param cloudService the service to be removed + */ + fun removeServiceFromQueue(cloudService: ICloudService) +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/ServiceHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/ServiceHandler.kt new file mode 100644 index 000000000..6d87c901c --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/service/ServiceHandler.kt @@ -0,0 +1,219 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.network.packets.service.PacketIOWrapperStartService +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.service.impl.DefaultCloudService +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.service.start.configuration.ServiceStartConfiguration +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.utils.time.Timestamp +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.* +import java.util.concurrent.CopyOnWriteArrayList +import java.util.concurrent.TimeUnit +import kotlin.concurrent.thread +import kotlin.math.min + +class ServiceHandler : IServiceHandler { + + private val messageSentForServices = arrayListOf() + + @Volatile + private var serviceQueue: MutableList = CopyOnWriteArrayList() + + override fun startServicesByGroup(cloudServiceGroup: ICloudServiceGroup, count: Int): List { + require(count >= 1) { "Count must be positive" } + val list = ArrayList() + for (i in 0 until count) { + list.add(startService(ServiceStartConfiguration(cloudServiceGroup))) + } + return list + } + + override fun startService(startConfiguration: IServiceStartConfiguration): ICloudService { + startConfiguration as ServiceStartConfiguration + val cloudServiceGroup = startConfiguration.getServiceGroup() + val serviceNumber = startConfiguration.serviceNumber ?: getNumberForNewService(cloudServiceGroup) + val serviceName = cloudServiceGroup.getName() + "-" + serviceNumber + val runningService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serviceName) + if (runningService != null) throw IllegalArgumentException("Service to start ($serviceName) is already registered") + val service = DefaultCloudService( + cloudServiceGroup.getName(), + serviceNumber, + cloudServiceGroup.getName() + "-" + serviceNumber, + UUID.randomUUID(), + startConfiguration.template, + cloudServiceGroup.getWrapperName(), + -1, + startConfiguration.maxMemory, + startConfiguration.maxPlayers, + "Cloud-Service", + cloudServiceGroup.getServiceVersion() + ) + CloudAPI.instance.getCloudServiceManager().update(service).awaitUninterruptibly() + addServiceToQueue(service) + return service + } + + override fun removeServiceFromQueue(cloudService: ICloudService) { + this.serviceQueue.remove(cloudService) + } + + private fun addServiceToQueue(service: ICloudService) { + if (serviceQueue.contains(service)) + return + serviceQueue.add(service) + Launcher.instance.consoleSender.sendProperty("manager.service.queued", service.getName()) + } + + + private fun getNumberForNewService(cloudServiceGroup: ICloudServiceGroup): Int { + var number = 1 + while (CloudAPI.instance.getCloudServiceManager() + .getCloudServiceByName(cloudServiceGroup.getName() + "-" + number) != null + ) + number++ + return number + } + + private fun queueMinServices() { + for (serviceGroup in CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects()) { + val allServices = serviceGroup.getAllServices() + //don't exclude closed services because they will be deleted in a moment. + val inLobbyServices = allServices.filter { it.getState() != ServiceState.INVISIBLE } //1 + val inLobbyServicesWithFewPlayers = inLobbyServices.filter { + it.getOnlinePercentage() < serviceGroup.getPercentToStartNewService().toDouble() / 100 + } + val minimumServiceCount = serviceGroup.getMinimumOnlineServiceCount() + var newServicesAmount = minimumServiceCount - inLobbyServicesWithFewPlayers.size + if (serviceGroup.getMaximumOnlineServiceCount() != -1 && newServicesAmount + inLobbyServices.size > serviceGroup.getMaximumOnlineServiceCount()) + newServicesAmount = serviceGroup.getMaximumOnlineServiceCount() - inLobbyServices.size + if (newServicesAmount > 0) { + startServicesByGroup(serviceGroup, newServicesAmount) + } + } + } + + private fun stopRedundantServices() { + for (serviceGroup in CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects()) { + val allServices = serviceGroup.getAllServices() + val redundantServices = allServices.filter { it.getState() == ServiceState.VISIBLE } + .filter { (it.getOnlinePercentage() * 100) < serviceGroup.getPercentToStartNewService() } + .filter { it.getLastPlayerUpdate().hasTimePassed(TimeUnit.MINUTES.toMillis(3)) } + //exclude services with percentage higher than percentage to start new service because they are not redundant + val stoppableServices = redundantServices.filter { it.getOnlineCount() <= 0 } + val minimumServiceCount = serviceGroup.getMinimumOnlineServiceCount() + if (redundantServices.size > minimumServiceCount) { + val amountToStop = redundantServices.size - minimumServiceCount + for (i in 0 until min(amountToStop, stoppableServices.size)) { + val service = stoppableServices[i] + //set to invisible, so that services are not shutdown again + service.setState(ServiceState.INVISIBLE) + service.update().awaitUninterruptibly() + service.shutdown() + } + } + } + } + + fun startThread() { + thread(start = true, isDaemon = true) { + while (true) { + this.serviceQueue = + CopyOnWriteArrayList(this.serviceQueue.sortedByDescending { + it.getServiceGroup().getStartPriority() + }) + queueMinServices() + stopRedundantServices() + + val priorityToServices = this.serviceQueue.groupBy { it.getServiceGroup().getStartPriority() } + val maxPriority = priorityToServices.keys.maxOrNull() + + if (maxPriority != null) { + for (priority in maxPriority downTo 0) { + val services = priorityToServices[priority] ?: emptyList() + //false will be listed first -> services with wrapper will be listed first + val sortedServices = services.sortedBy { it.getWrapperName() == null } + for (service in sortedServices) { + executeStart(service) + } + } + } + Thread.sleep(300) + } + } + } + + private fun executeStart(service: ICloudService) { + val wrapper = getWrapperForService(service) ?: return + val wrapperClient = Manager.instance.communicationServer.getClientManager().getClientByClientValue(wrapper) + wrapperClient ?: return + service as DefaultCloudService + service.setWrapperName(wrapper.getName()) + service.setLastPlayerUpdate(Timestamp()) + service.update().awaitUninterruptibly() + wrapperClient.sendUnitQuery(PacketIOWrapperStartService(service.getName())).awaitUninterruptibly() + Launcher.instance.consoleSender.sendProperty("manager.service.start", wrapper.getName(), service.getName()) + this.serviceQueue.remove(service) + } + + private fun getWrapperForService(service: ICloudService): IWrapperInfo? { + if (service.getWrapperName() == null) { + val wrapper = CloudAPI.instance.getWrapperManager().getWrapperByUnusedMemory(service.getMaxMemory()) + if (wrapper == null) + handleNotEnoughMemoryForService(service.getName()) + return wrapper + } else { + val requiredWrapper = CloudAPI.instance.getWrapperManager().getWrapperByName(service.getWrapperName()!!) + ?: return null + val hasEnoughMemory = requiredWrapper.hasEnoughMemory(service.getMaxMemory()) + if (!hasEnoughMemory) { + handleNotEnoughMemoryForService(service.getName()) + } + if (hasEnoughMemory && requiredWrapper.isAuthenticated() + && requiredWrapper.hasTemplatesReceived() + && requiredWrapper.getCurrentlyStartingServices() != requiredWrapper.getMaxSimultaneouslyStartingServices() + ) { + return requiredWrapper + } + return null + } + } + + private fun handleNotEnoughMemoryForService(serviceName: String) { + if (this.messageSentForServices.contains(serviceName)) + return + this.messageSentForServices.add(serviceName) + Launcher.instance.logger.warning("The cloud does not have enough ram to start the service $serviceName") + Launcher.instance.scheduler.schedule({ + this.messageSentForServices.remove(serviceName) + }, 60, TimeUnit.SECONDS) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/serviceversion/ManagerServiceVersionHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/serviceversion/ManagerServiceVersionHandler.kt new file mode 100644 index 000000000..6d42da7f9 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/serviceversion/ManagerServiceVersionHandler.kt @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.serviceversion + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.extension.sendPacketToAllAuthenticatedClients +import eu.thesimplecloud.api.network.packets.serviceversion.PacketIOServiceVersions +import eu.thesimplecloud.api.service.version.ServiceVersionHandler +import eu.thesimplecloud.api.service.version.loader.CombinedServiceVersionLoader +import eu.thesimplecloud.api.service.version.loader.LocalServiceVersionHandler +import eu.thesimplecloud.base.manager.startup.Manager + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 22:11 + * @author Frederick Baier + */ +class ManagerServiceVersionHandler : ServiceVersionHandler(CombinedServiceVersionLoader.loadVersions()) { + + fun reloadServiceVersions() { + val allVersions = CombinedServiceVersionLoader.loadVersions() + this.versions = allVersions + + val packet = PacketIOServiceVersions(allVersions) + Manager.instance.communicationServer.getClientManager().sendPacketToAllAuthenticatedClients(packet) + } + + fun deleteServiceVersion(name: String) { + if (!doesVersionExist(name)) + throw NoSuchElementException("Service-Version does not exist") + if (isVersionInUse(name)) + throw IllegalStateException("Service-Version is still in use") + + val list = this.versions.toMutableList() + list.removeIf { it.name == name } + LocalServiceVersionHandler().deleteServiceVersion(name) + reloadServiceVersions() + } + + fun isVersionInUse(name: String): Boolean { + return CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + .any { it.getServiceVersion().name == name } + } + + fun doesVersionExist(name: String): Boolean { + return this.versions.any { it.name == name } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultLobbyGroup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultLobbyGroup.kt new file mode 100644 index 000000000..827e63537 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultLobbyGroup.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup + +import eu.thesimplecloud.base.manager.setup.groups.LobbyGroupSetup +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.console.setup.provider.BooleanSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher + +class CreateDefaultLobbyGroup : ISetup { + + @SetupQuestion(0, "Do you want to create a default Lobby-Group?", BooleanSetupAnswerProvider::class) + fun setupLobby(answer: Boolean): Boolean { + if (!answer) { + return true + } + Launcher.instance.setupManager.queueSetup(LobbyGroupSetup()) + return true + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultProxyGroup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultProxyGroup.kt new file mode 100644 index 000000000..9bc2dccb5 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/CreateDefaultProxyGroup.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup + +import eu.thesimplecloud.base.manager.setup.groups.ProxyGroupSetup +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.console.setup.provider.BooleanSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher + +class CreateDefaultProxyGroup : ISetup { + + @SetupQuestion(0, "Do you want to create a default Proxy-Group?", BooleanSetupAnswerProvider::class) + fun setupProxy(answer: Boolean): Boolean { + if (!answer) { + return true + } + Launcher.instance.setupManager.queueSetup(ProxyGroupSetup()) + return true + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/ServiceVersionSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/ServiceVersionSetup.kt new file mode 100644 index 000000000..fdd11a06b --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/ServiceVersionSetup.kt @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.service.version.loader.LocalServiceVersionHandler +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.base.manager.serviceversion.ManagerServiceVersionHandler +import eu.thesimplecloud.base.manager.setup.provider.ServiceAPITypeAnswerProvider +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher +import java.net.MalformedURLException +import java.net.URL + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:38 + * @author Frederick Baier + */ +class ServiceVersionSetup : ISetup { + + private lateinit var name: String + private lateinit var serviceAPIType: ServiceAPIType + private lateinit var downloadURL: String + private var isPaperclip: Boolean = false + + @SetupQuestion(0, "manager.setup.service-versions.question.name") + fun nameSetup(name: String): Boolean { + this.name = name + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.name.success") + return true + } + + @SetupQuestion(1, "manager.setup.service-versions.question.apitype", ServiceAPITypeAnswerProvider::class) + fun typeSetup(type: ServiceAPIType): Boolean { + this.serviceAPIType = type + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.apitype.success") + return true + } + + @SetupQuestion(2, "manager.setup.service-versions.question.url") + fun downloadUrlSetup(url: String): Boolean { + try { + URL(url) + } catch (ex: MalformedURLException) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.url.invalid") + return false + } + this.downloadURL = url + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.url.success") + return true + } + + @SetupQuestion(3, "manager.setup.service-versions.question.paperclip") + fun isPaperclipSetup(isPaperclip: Boolean): Boolean { + this.isPaperclip = isPaperclip + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.paperclip.success") + return true + } + + @SetupFinished + fun setupFinished() { + val serviceVersion = ServiceVersion(name, serviceAPIType, downloadURL, isPaperclip) + LocalServiceVersionHandler().saveServiceVersion(serviceVersion) + val serviceVersionHandler = CloudAPI.instance.getServiceVersionHandler() as ManagerServiceVersionHandler + serviceVersionHandler.reloadServiceVersions() + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.finished", name) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/WrapperSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/WrapperSetup.kt new file mode 100644 index 000000000..a4185c8dc --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/WrapperSetup.kt @@ -0,0 +1,97 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperInfo +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.launcher.utils.IpValidator + +class WrapperSetup : ISetup { + + private var maxSimultaneouslyStartingServices: Int = 0 + private var memory: Int = 0 + private lateinit var host: String + private lateinit var name: String + + @SetupQuestion(0, "manager.setup.wrapper.question.name") + fun nameSetup(name: String): Boolean { + if (name.length > 16) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.name.too-long") + return false + } + this.name = name + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.name.success") + return true + } + + @SetupQuestion(1, "manager.setup.wrapper.question.host") + fun hostSetup(host: String): Boolean { + if (host.equals("this", true)) { + this.host = Launcher.instance.launcherConfig.host + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.host.success") + return true + } + if (!IpValidator().validate(host)) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.host.invalid") + return false + } + this.host = host + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.host.success") + return true + } + + @SetupQuestion(2, "manager.setup.wrapper.question.memory") + fun memorySetup(memory: Int): Boolean { + if (memory < 1024) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.memory.too-low") + return false + } + this.memory = memory + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.memory.success") + return true + } + + @SetupQuestion(3, "manager.setup.wrapper.question.start-services") + fun simultaneouslySetup(maxSimultaneouslyStartingServices: Int): Boolean { + if (maxSimultaneouslyStartingServices < 1) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.start-services.too-low") + return false + } + this.maxSimultaneouslyStartingServices = maxSimultaneouslyStartingServices + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.question.start-services.success") + return true + } + + @SetupFinished + fun finished() { + val wrapperInfo = DefaultWrapperInfo(name, host, maxSimultaneouslyStartingServices, memory) + CloudAPI.instance.getWrapperManager().update(wrapperInfo) + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.wrapper.finished", name) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseConnectionSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseConnectionSetup.kt new file mode 100644 index 000000000..87971018c --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseConnectionSetup.kt @@ -0,0 +1,107 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.database + +import eu.thesimplecloud.base.manager.config.mongo.DatabaseConfigLoader +import eu.thesimplecloud.base.manager.database.DatabaseConnectionInformation +import eu.thesimplecloud.base.manager.database.DatabaseType +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher + +class DatabaseConnectionSetup : ISetup { + + var host: String? = null + var port: Int? = null + var databaseName: String? = null + var username: String? = null + var password: String? = null + var databaseType: DatabaseType? = null + + @SetupQuestion(0, "manager.setup.database-connection.question.type", DatabaseTypeSetupAnswerProvider::class) + fun type(type: DatabaseType): Boolean { + this.databaseType = type + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.question.type.success") + return true + } + + @SetupQuestion(0, "manager.setup.database-connection.question.host") + fun host(host: String): Boolean { + if (host.isEmpty()) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.host-invalid") + return false + } + this.host = host + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.question.host.success") + return true + } + + @SetupQuestion(1, "manager.setup.database-connection.question.port") + fun port(port: Int): Boolean { + if (port <= 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.port-invalid") + return false + } + this.port = port + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.question.port.success") + return true + } + + @SetupQuestion(2, "manager.setup.database-connection.question.database") + fun database(database: String): Boolean { + this.databaseName = database + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.question.database.success") + return true + } + + @SetupQuestion(3, "manager.setup.database-connection.question.username") + fun username(username: String): Boolean { + this.username = username + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.question.username.success") + return true + } + + @SetupQuestion(4, "manager.setup.database-connection.question.password") + fun password(password: String): Boolean { + this.password = password + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.database-connection.question.password.success") + return true + } + + @SetupFinished + fun finished() { + val databaseConnectionInformation = DatabaseConnectionInformation( + this.host!!, + this.port!!, + this.databaseName!!, + this.username!!, + this.password!!, + "cloud_", + databaseType!! + ) + DatabaseConfigLoader().saveConfig(databaseConnectionInformation) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseTypeSetupAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseTypeSetupAnswerProvider.kt new file mode 100644 index 000000000..ecf6cc017 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/database/DatabaseTypeSetupAnswerProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.database + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.base.manager.database.DatabaseType +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * Date: 17.06.2020 + * Time: 08:48 + * @author Frederick Baier + */ +class DatabaseTypeSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): Collection { + return DatabaseType.values().map { it.name } + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/DefaultGroupSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/DefaultGroupSetup.kt new file mode 100644 index 000000000..e1c457492 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/DefaultGroupSetup.kt @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.template.impl.DefaultTemplate +import eu.thesimplecloud.launcher.startup.Launcher + +open class DefaultGroupSetup { + + protected var permission: String? = null + + /** + * Creates a template and returns its name + */ + fun createTemplate(templateName: String, groupName: String): String? { + if (templateName.equals("create", true)) { + if (CloudAPI.instance.getTemplateManager().getTemplateByName(groupName) == null) { + val template = DefaultTemplate(groupName) + CloudAPI.instance.getTemplateManager().update(template) + template.getDirectory().mkdirs() + } + Launcher.instance.consoleSender.sendPropertyInSetup( + "manager.setup.service-group.question.template.created", + groupName + ) + return groupName + } + if (CloudAPI.instance.getTemplateManager().getTemplateByName(templateName) == null) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.template.not-exist") + return null + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.template.success") + return templateName + } + + protected fun handlePermission(permission: String) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.permission.success") + if (permission.isNotBlank()) + this.permission = permission + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetup.kt new file mode 100644 index 000000000..cf635a7e7 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetup.kt @@ -0,0 +1,192 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.manager.setup.groups.provider.GroupTemplateSetupAnswerProvider +import eu.thesimplecloud.base.manager.setup.groups.provider.GroupWrapperSetupAnswerProvider +import eu.thesimplecloud.base.manager.setup.groups.provider.ServerVersionTypeSetupAnswerProvider +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.console.setup.provider.BooleanSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher +import kotlin.properties.Delegates + +open class LobbyGroupSetup : DefaultGroupSetup(), ISetup { + + private lateinit var serviceVersion: ServiceVersion + private var wrapper: IWrapperInfo? = null + private var priority by Delegates.notNull() + private var percent by Delegates.notNull() + private var static by Delegates.notNull() + private var maximumOnlineServices by Delegates.notNull() + private var minimumOnlineServices by Delegates.notNull() + private var maxPlayers by Delegates.notNull() + private var memory by Delegates.notNull() + private lateinit var name: String + private lateinit var templateName: String + var javaCommand: String = "java" + + @SetupQuestion(0, "manager.setup.service-group.question.name") + fun nameQuestion(name: String): Boolean { + this.name = name + if (name.length > 32) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.too-long") + return false + } + if (name.isEmpty()) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.is-empty") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.success") + return true + } + + @SetupQuestion(1, "manager.setup.service-group.question.template", GroupTemplateSetupAnswerProvider::class) + fun templateQuestion(templateName: String): Boolean { + val template = createTemplate(templateName, this.name) + if (template != null) { + this.templateName = template + } + return template != null + } + + @SetupQuestion(2, "manager.setup.service-group.question.type", ServerVersionTypeSetupAnswerProvider::class) + fun typeQuestion(string: String) { + this.serviceVersion = CloudAPI.instance.getServiceVersionHandler().getServiceVersionByName(string)!! + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.server-group.question.type.success") + } + + @SetupQuestion(4, "manager.setup.service-group.question.memory") + fun memoryQuestion(memory: Int): Boolean { + if (memory < 128) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.memory.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.memory.success") + this.memory = memory + return true + } + + @SetupQuestion(5, "manager.setup.service-group.question.max-players") + fun maxPlayersQuestion(maxPlayers: Int): Boolean { + if (maxPlayers < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.max-players.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.max-players.success") + this.maxPlayers = maxPlayers + return true + } + + + @SetupQuestion(6, "manager.setup.service-group.question.minimum-online") + fun minimumOnlineQuestion(minimumOnlineServices: Int): Boolean { + if (minimumOnlineServices < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.minimum-online.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.minimum-online.success") + this.minimumOnlineServices = minimumOnlineServices + return true + } + + @SetupQuestion(7, "manager.setup.service-group.question.maximum-online") + fun maximumOnlineQuestion(maximumOnlineServices: Int): Boolean { + if (maximumOnlineServices < -1) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.maximum-online.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.maximum-online.success") + this.maximumOnlineServices = maximumOnlineServices + return true + } + + @SetupQuestion(8, "manager.setup.service-group.question.static", BooleanSetupAnswerProvider::class) + fun staticQuestion(static: Boolean) { + this.static = static + } + + @SetupQuestion(9, "manager.setup.server-group.question.wrapper", GroupWrapperSetupAnswerProvider::class) + fun wrapperQuestion(string: String): Boolean { + if (string.isBlank() && static) + return false + if (string.isBlank() && !static) + return true + val wrapper = CloudAPI.instance.getWrapperManager().getWrapperByName(string)!! + this.wrapper = wrapper + return true + } + + @SetupQuestion(10, "manager.setup.service-group.question.percent") + fun percentQuestion(percent: Int): Boolean { + if (percent < 1 || percent > 100) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.percent.out-of-range") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.percent.success") + this.percent = percent + return true + } + + @SetupQuestion(11, "manager.setup.service-group.question.priority") + fun priorityQuestion(priority: Int): Boolean { + if (priority < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.priority.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.priority.success") + this.priority = priority + return true + } + + @SetupQuestion(12, "manager.setup.service-group.question.permission") + fun permissionQuestion(permission: String) { + handlePermission(permission) + } + + @SetupFinished + fun finished() { + CloudAPI.instance.getCloudServiceGroupManager().createLobbyGroup( + name, + templateName, + memory, + maxPlayers, + minimumOnlineServices, + maximumOnlineServices, + false, + static, + percent, + wrapper?.getName(), + priority, + permission, + serviceVersion, + 9, + javaCommand + ) + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.finished", name) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetupWithJava.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetupWithJava.kt new file mode 100644 index 000000000..75bd46208 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/LobbyGroupSetupWithJava.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups + +import eu.thesimplecloud.base.manager.setup.provider.ServiceJavaCommandAnswerProvider +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher + +class LobbyGroupSetupWithJava : LobbyGroupSetup() { + + @SetupQuestion(13, "manager.setup.service-versions.question.java", ServiceJavaCommandAnswerProvider::class) + fun useJavaCommand(javaName: String): Boolean { + if (javaName == "default") { + this.javaCommand = "java" + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.java.success") + return true + } + this.javaCommand = javaName + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.java.success") + return true + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ProxyGroupSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ProxyGroupSetup.kt new file mode 100644 index 000000000..1bb232ef9 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ProxyGroupSetup.kt @@ -0,0 +1,195 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.manager.setup.groups.provider.GroupTemplateSetupAnswerProvider +import eu.thesimplecloud.base.manager.setup.groups.provider.GroupWrapperSetupAnswerProvider +import eu.thesimplecloud.base.manager.setup.groups.provider.ProxyVersionTypeSetupAnswerProvider +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.console.setup.provider.BooleanSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher +import kotlin.properties.Delegates + +class ProxyGroupSetup : DefaultGroupSetup(), ISetup { + + private lateinit var serviceVersion: ServiceVersion + private var startPort by Delegates.notNull() + private var wrapper: IWrapperInfo? = null + private var percent by Delegates.notNull() + private var static by Delegates.notNull() + private var maximumOnlineServices by Delegates.notNull() + private var minimumOnlineServices by Delegates.notNull() + private var maxPlayers by Delegates.notNull() + private var memory by Delegates.notNull() + private lateinit var name: String + private lateinit var templateName: String + + @SetupQuestion(0, "manager.setup.service-group.question.name") + fun nameQuestion(name: String): Boolean { + this.name = name + if (name.length > 32) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.too-long") + return false + } + if (name.isEmpty()) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.is-empty") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.success") + return true + } + + @SetupQuestion(1, "manager.setup.service-group.question.template", GroupTemplateSetupAnswerProvider::class) + fun templateQuestion(templateName: String): Boolean { + val template = createTemplate(templateName, this.name) + if (template != null) { + this.templateName = template + } + return template != null + } + + @SetupQuestion(2, "manager.setup.proxy-group.question.type", ProxyVersionTypeSetupAnswerProvider::class) + fun typeQuestion(answer: String): Boolean { + val serviceVersion = CloudAPI.instance.getServiceVersionHandler() + .getServiceVersionByName(answer)!! + this.serviceVersion = serviceVersion + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.proxy-group.question.type.success") + return true + } + + @SetupQuestion(4, "manager.setup.service-group.question.memory") + fun memoryQuestion(memory: Int): Boolean { + if (memory < 128) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.memory.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.memory.success") + this.memory = memory + return true + } + + @SetupQuestion(5, "manager.setup.service-group.question.max-players") + fun maxPlayersQuestion(maxPlayers: Int): Boolean { + if (maxPlayers < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.max-players.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.max-players.success") + this.maxPlayers = maxPlayers + return true + } + + + @SetupQuestion(6, "manager.setup.service-group.question.minimum-online") + fun minimumOnlineQuestion(minimumOnlineServices: Int): Boolean { + if (minimumOnlineServices < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.minimum-online.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.minimum-online.success") + this.minimumOnlineServices = minimumOnlineServices + return true + } + + @SetupQuestion(7, "manager.setup.service-group.question.maximum-online") + fun maximumOnlineQuestion(maximumOnlineServices: Int): Boolean { + if (maximumOnlineServices < -1) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.maximum-online.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.maximum-online.success") + this.maximumOnlineServices = maximumOnlineServices + return true + } + + @SetupQuestion(8, "manager.setup.service-group.question.static", BooleanSetupAnswerProvider::class) + fun staticQuestion(static: Boolean) { + this.static = static + } + + @SetupQuestion(9, "manager.setup.proxy-group.question.wrapper", GroupWrapperSetupAnswerProvider::class) + fun wrapperQuestion(string: String): Boolean { + if (string.isBlank() && static) + return false + if (string.isBlank() && !static) + return true + val wrapper = CloudAPI.instance.getWrapperManager().getWrapperByName(string)!! + this.wrapper = wrapper + return true + } + + @SetupQuestion(10, "manager.setup.service-group.question.percent") + fun percentQuestion(percent: Int): Boolean { + if (percent < 1 || percent > 100) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.percent.out-of-range") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.percent.success") + this.percent = percent + return true + } + + @SetupQuestion(11, "manager.setup.proxy-group.question.start-port") + fun startPortQuestion(startPort: Int): Boolean { + if (startPort < 100 || startPort > 65535) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.port.out-of-range") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.port.success") + this.startPort = startPort + return true + } + + @SetupQuestion(12, "manager.setup.service-group.question.permission") + fun permissionQuestion(permission: String) { + handlePermission(permission) + } + + @SetupFinished + fun finished() { + CloudAPI.instance.getCloudServiceGroupManager().createProxyGroup( + name, + templateName, + memory, + maxPlayers, + minimumOnlineServices, + maximumOnlineServices, + true, + static, + percent, + wrapper?.getName(), + startPort, + serviceVersion, + 10, + this.permission + ) + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.finished", name) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetup.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetup.kt new file mode 100644 index 000000000..8bae58ca3 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetup.kt @@ -0,0 +1,181 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.manager.setup.groups.provider.GroupTemplateSetupAnswerProvider +import eu.thesimplecloud.base.manager.setup.groups.provider.GroupWrapperSetupAnswerProvider +import eu.thesimplecloud.base.manager.setup.groups.provider.ServerVersionTypeSetupAnswerProvider +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.console.setup.provider.BooleanSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher +import kotlin.properties.Delegates + +open class ServerGroupSetup : DefaultGroupSetup(), ISetup { + + private lateinit var serviceVersion: ServiceVersion + private var wrapper: IWrapperInfo? = null + private var percent by Delegates.notNull() + private var static by Delegates.notNull() + private var maximumOnlineServices by Delegates.notNull() + private var minimumOnlineServices by Delegates.notNull() + private var maxPlayers by Delegates.notNull() + private var memory by Delegates.notNull() + private lateinit var name: String + private lateinit var templateName: String + var javaCommand: String = "java" + + @SetupQuestion(0, "manager.setup.service-group.question.name") + fun nameQuestion(name: String): Boolean { + this.name = name + if (name.length > 32) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.too-long") + return false + } + if (name.isEmpty()) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.is-empty") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.name.success") + return true + } + + @SetupQuestion(1, "manager.setup.service-group.question.template", GroupTemplateSetupAnswerProvider::class) + fun templateQuestion(templateName: String): Boolean { + val template = createTemplate(templateName, this.name) + if (template != null) { + this.templateName = template + } + return template != null + } + + @SetupQuestion(2, "manager.setup.service-group.question.type", ServerVersionTypeSetupAnswerProvider::class) + fun typeQuestion(string: String) { + this.serviceVersion = CloudAPI.instance.getServiceVersionHandler().getServiceVersionByName(string)!! + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.server-group.question.type.success") + } + + @SetupQuestion(4, "manager.setup.service-group.question.memory") + fun memoryQuestion(memory: Int): Boolean { + if (memory < 128) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.memory.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.memory.success") + this.memory = memory + return true + } + + @SetupQuestion(5, "manager.setup.service-group.question.max-players") + fun maxPlayersQuestion(maxPlayers: Int): Boolean { + if (maxPlayers < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.max-players.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.max-players.success") + this.maxPlayers = maxPlayers + return true + } + + + @SetupQuestion(6, "manager.setup.service-group.question.minimum-online") + fun minimumOnlineQuestion(minimumOnlineServices: Int): Boolean { + if (minimumOnlineServices < 0) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.minimum-online.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.minimum-online.success") + this.minimumOnlineServices = minimumOnlineServices + return true + } + + @SetupQuestion(7, "manager.setup.service-group.question.maximum-online") + fun maximumOnlineQuestion(maximumOnlineServices: Int): Boolean { + if (maximumOnlineServices < -1) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.maximum-online.too-low") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.maximum-online.success") + this.maximumOnlineServices = maximumOnlineServices + return true + } + + @SetupQuestion(8, "manager.setup.service-group.question.static", BooleanSetupAnswerProvider::class) + fun staticQuestion(static: Boolean) { + this.static = static + } + + @SetupQuestion(9, "manager.setup.server-group.question.wrapper", GroupWrapperSetupAnswerProvider::class) + fun wrapperQuestion(string: String): Boolean { + if (string.isBlank() && static) + return false + if (string.isBlank() && !static) + return true + val wrapper = CloudAPI.instance.getWrapperManager().getWrapperByName(string)!! + this.wrapper = wrapper + return true + } + + @SetupQuestion(10, "manager.setup.service-group.question.percent") + fun percentQuestion(percent: Int): Boolean { + if (percent < 1 || percent > 100) { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.percent.out-of-range") + return false + } + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.question.percent.success") + this.percent = percent + return true + } + + @SetupQuestion(11, "manager.setup.service-group.question.permission") + fun permissionQuestion(permission: String) { + handlePermission(permission) + } + + @SetupFinished + fun finished() { + CloudAPI.instance.getCloudServiceGroupManager().createServerGroup( + name, + templateName, + memory, + maxPlayers, + minimumOnlineServices, + maximumOnlineServices, + false, + static, + percent, + wrapper?.getName(), + serviceVersion, + 0, + permission, + javaCommand + ) + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-group.finished", name) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetupWithJava.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetupWithJava.kt new file mode 100644 index 000000000..7d2064607 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/ServerGroupSetupWithJava.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups + +import eu.thesimplecloud.base.manager.setup.provider.ServiceJavaCommandAnswerProvider +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher + +class ServerGroupSetupWithJava : ServerGroupSetup() { + + @SetupQuestion(12, "manager.setup.service-versions.question.java", ServiceJavaCommandAnswerProvider::class) + fun useJavaCommand(javaCommandType: String): Boolean { + this.javaCommand = javaCommandType + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.java.success") + return true + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupTemplateSetupAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupTemplateSetupAnswerProvider.kt new file mode 100644 index 000000000..b5ddaec0a --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupTemplateSetupAnswerProvider.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class GroupTemplateSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return CloudAPI.instance.getTemplateManager().getAllCachedObjects().map { it.getName() } + .union(listOf("create")).toList() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupWrapperSetupAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupWrapperSetupAnswerProvider.kt new file mode 100644 index 000000000..b2d34887d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/GroupWrapperSetupAnswerProvider.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class GroupWrapperSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): Collection { + return CloudAPI.instance.getWrapperManager().getAllCachedObjects() + .map { it.getName() } + .union(listOf("")) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ProxyVersionTypeSetupAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ProxyVersionTypeSetupAnswerProvider.kt new file mode 100644 index 000000000..57878c1c7 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ProxyVersionTypeSetupAnswerProvider.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.version.type.ServiceVersionType +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 16:55 + * @author Frederick Baier + */ +class ProxyVersionTypeSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return CloudAPI.instance.getServiceVersionHandler().getVersionsByServiceVersionType(ServiceVersionType.PROXY) + .map { it.name } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ServerVersionTypeSetupAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ServerVersionTypeSetupAnswerProvider.kt new file mode 100644 index 000000000..483be58e6 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/groups/provider/ServerVersionTypeSetupAnswerProvider.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.groups.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.version.type.ServiceVersionType +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 16:55 + * @author Frederick Baier + */ +class ServerVersionTypeSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return CloudAPI.instance.getServiceVersionHandler().getVersionsByServiceVersionType(ServiceVersionType.SERVER) + .map { it.name }.toList() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceAPITypeAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceAPITypeAnswerProvider.kt new file mode 100644 index 000000000..eb4ecbe62 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceAPITypeAnswerProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * Date: 30/01/2021 + * Time: 09:23 + * @author Frederick Baier + */ +class ServiceAPITypeAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): Collection { + return ServiceAPIType.values().map { it.name } + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceJavaCommandAnswerProvider.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceJavaCommandAnswerProvider.kt new file mode 100644 index 000000000..16823ba15 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/setup/provider/ServiceJavaCommandAnswerProvider.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.setup.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.config.java.JavaVersion +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +class ServiceJavaCommandAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): Collection { + return JavaVersion.paths.versions.keys.union(listOf("default")) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/Manager.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/Manager.kt new file mode 100644 index 000000000..2d077fca5 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/Manager.kt @@ -0,0 +1,263 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.base.core.jvm.JvmArgumentsConfig +import eu.thesimplecloud.base.manager.config.JvmArgumentsConfigLoader +import eu.thesimplecloud.base.manager.config.encryption.KeyConfigLoader +import eu.thesimplecloud.base.manager.config.mongo.DatabaseConfigLoader +import eu.thesimplecloud.base.manager.config.template.TemplatesConfigLoader +import eu.thesimplecloud.base.manager.config.updater.ModuleUpdaterConfigLoader +import eu.thesimplecloud.base.manager.database.DatabaseType +import eu.thesimplecloud.base.manager.database.IOfflineCloudPlayerHandler +import eu.thesimplecloud.base.manager.database.MongoOfflineCloudPlayerHandler +import eu.thesimplecloud.base.manager.database.SQLOfflineCloudPlayerHandler +import eu.thesimplecloud.base.manager.database.aes.AdvancedEncryption +import eu.thesimplecloud.base.manager.filehandler.CloudServiceGroupFileHandler +import eu.thesimplecloud.base.manager.filehandler.WrapperFileHandler +import eu.thesimplecloud.base.manager.impl.CloudAPIImpl +import eu.thesimplecloud.base.manager.ingamecommands.IngameCommandUpdater +import eu.thesimplecloud.base.manager.listener.CloudListener +import eu.thesimplecloud.base.manager.listener.ModuleEventListener +import eu.thesimplecloud.base.manager.packet.IPacketRegistry +import eu.thesimplecloud.base.manager.packet.PacketRegistry +import eu.thesimplecloud.base.manager.player.PlayerUnregisterScheduler +import eu.thesimplecloud.base.manager.service.ServiceHandler +import eu.thesimplecloud.base.manager.setup.CreateDefaultLobbyGroup +import eu.thesimplecloud.base.manager.setup.CreateDefaultProxyGroup +import eu.thesimplecloud.base.manager.setup.database.DatabaseConnectionSetup +import eu.thesimplecloud.base.manager.startup.server.CommunicationConnectionHandlerImpl +import eu.thesimplecloud.base.manager.startup.server.ManagerAccessHandler +import eu.thesimplecloud.base.manager.startup.server.ServerHandlerImpl +import eu.thesimplecloud.base.manager.startup.server.TemplateConnectionHandlerImpl +import eu.thesimplecloud.base.manager.update.converter.VersionConversionManager +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket +import eu.thesimplecloud.clientserverapi.server.INettyServer +import eu.thesimplecloud.clientserverapi.server.NettyServer +import eu.thesimplecloud.launcher.application.ApplicationClassLoader +import eu.thesimplecloud.launcher.application.ICloudApplication +import eu.thesimplecloud.launcher.external.module.ModuleClassLoader +import eu.thesimplecloud.launcher.external.module.handler.IModuleHandler +import eu.thesimplecloud.launcher.external.module.handler.ModuleHandler +import eu.thesimplecloud.launcher.language.LanguageFileLoader +import eu.thesimplecloud.launcher.startup.Launcher +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import java.io.File +import java.util.logging.Level +import java.util.logging.Logger +import kotlin.concurrent.thread + +class Manager : ICloudApplication { + + val ingameCommandUpdater: IngameCommandUpdater + val cloudServiceGroupFileHandler = CloudServiceGroupFileHandler() + val wrapperFileHandler = WrapperFileHandler() + val templatesConfigLoader = TemplatesConfigLoader() + val serviceHandler: ServiceHandler + + val offlineCloudPlayerHandler: IOfflineCloudPlayerHandler + + val communicationServer: INettyServer + val templateServer: INettyServer + val packetRegistry: IPacketRegistry = PacketRegistry() + val playerUnregisterScheduler = PlayerUnregisterScheduler() + val cloudModuleHandler: IModuleHandler + val appClassLoader: ApplicationClassLoader + val encryption: AdvancedEncryption + + private val profileFile = ProfileFile() + + lateinit var jvmArgumentsConfig: JvmArgumentsConfig + + companion object { + @JvmStatic + lateinit var instance: Manager + private set + } + + init { + Logger.getLogger("org.mongodb.driver").level = Level.SEVERE + instance = this + VersionConversionManager().convertIfNecessary() + CloudAPIImpl() + LanguageFileLoader().loadFile(Launcher.instance.launcherConfig) + this.serviceHandler = ServiceHandler() + CloudAPI.instance.getEventManager().registerListener(this, CloudListener()) + CloudAPI.instance.getEventManager().registerListener(this, ModuleEventListener()) + this.appClassLoader = this::class.java.classLoader as ApplicationClassLoader + + this.cloudModuleHandler = ModuleHandler( + appClassLoader, + Launcher.instance.launcherConfig.language, + ModuleUpdaterConfigLoader().loadConfig().modules, + true + ) { Launcher.instance.logger.exception(it) } + this.appClassLoader.moduleHandler = this.cloudModuleHandler + + this.cloudModuleHandler.setCreateModuleClassLoader { urls, name -> + ModuleClassLoader( + urls, + this.appClassLoader, + name, + this.cloudModuleHandler + ) + } + Property.propertyClassFindFunction = { this.cloudModuleHandler.findModuleOrSystemClass(it) } + this.ingameCommandUpdater = IngameCommandUpdater() + if (!DatabaseConfigLoader().doesConfigFileExist()) { + Launcher.instance.setupManager.queueSetup(DatabaseConnectionSetup()) + Launcher.instance.setupManager.waitForAllSetups() + } + val mongoConnectionInformation = DatabaseConfigLoader().loadConfig() + this.encryption = AdvancedEncryption(KeyConfigLoader().loadConfig()) + + val launcherConfig = Launcher.instance.launcherConfig + val baseAndLauncherLoader = Launcher.instance.getNewClassLoaderWithLauncherAndBase() + this.communicationServer = NettyServer( + launcherConfig.host, + launcherConfig.port, + CommunicationConnectionHandlerImpl(), + ServerHandlerImpl() + ) + this.communicationServer.setAccessHandler(ManagerAccessHandler()) + this.communicationServer.setPacketSearchClassLoader(baseAndLauncherLoader) + this.communicationServer.setClassLoaderToSearchObjectPacketClasses(appClassLoader) + this.communicationServer.setPacketClassConverter { moveToApplicationClassLoader(it) } + this.templateServer = NettyServer( + launcherConfig.host, + launcherConfig.port + 1, + TemplateConnectionHandlerImpl(), + ServerHandlerImpl() + ) + this.templateServer.setAccessHandler(ManagerAccessHandler()) + this.templateServer.setPacketSearchClassLoader(baseAndLauncherLoader) + this.templateServer.setClassLoaderToSearchObjectPacketClasses(appClassLoader) + this.templateServer.setPacketClassConverter { moveToApplicationClassLoader(it) } + this.communicationServer.addPacketsByPackage("eu.thesimplecloud.api.network.packets") + this.communicationServer.addPacketsByPackage("eu.thesimplecloud.base.manager.network.packets") + this.templateServer.addPacketsByPackage("eu.thesimplecloud.base.manager.network.packets.template") + thread(start = true, isDaemon = false) { communicationServer.start() } + createDirectories() + Logger.getLogger("org.mongodb.driver").level = Level.SEVERE + Launcher.instance.logger.console("Waiting for the database...") + + this.offlineCloudPlayerHandler = when (mongoConnectionInformation.databaseType) { + DatabaseType.MONGODB -> MongoOfflineCloudPlayerHandler(mongoConnectionInformation) + DatabaseType.MYSQL -> SQLOfflineCloudPlayerHandler(mongoConnectionInformation) + } + Launcher.instance.logger.console("Connected to the database") + + this.templateServer.getDirectorySyncManager().setTmpZipDirectory(File(DirectoryPaths.paths.zippedTemplatesPath)) + this.templateServer.getDirectorySyncManager() + .createDirectorySync(File(DirectoryPaths.paths.templatesPath), DirectoryPaths.paths.templatesPath) + this.templateServer.getDirectorySyncManager() + .createDirectorySync(File(DirectoryPaths.paths.modulesPath), DirectoryPaths.paths.modulesPath) + this.serviceHandler.startThread() + thread(start = true, isDaemon = false) { templateServer.start() } + VersionConversionManager().writeLastStartedVersionIfFileDoesNotExist() + //this.playerUnregisterScheduler.startScheduler() + } + + private fun moveToApplicationClassLoader(clazz: Class): Class { + if (appClassLoader.isThisClassLoader(clazz)) return clazz + val loadedClass = appClassLoader.loadClass(clazz.name) + appClassLoader.setCachedClass(loadedClass) + return loadedClass as Class + } + + override fun onEnable() { + GlobalScope.launch { + Launcher.instance.commandManager.registerAllCommands( + instance, + appClassLoader, + "eu.thesimplecloud.base.manager.commands" + ) + } + Launcher.instance.setupManager.waitForAllSetups() + this.wrapperFileHandler.loadAll().forEach { CloudAPI.instance.getWrapperManager().update(it) } + this.cloudServiceGroupFileHandler.loadAll() + .forEach { CloudAPI.instance.getCloudServiceGroupManager().update(it) } + val templates = this.templatesConfigLoader.loadConfig().templates + templates.forEach { CloudAPI.instance.getTemplateManager().update(it) } + this.jvmArgumentsConfig = JvmArgumentsConfigLoader().loadConfig() + + if (CloudAPI.instance.getWrapperManager().getAllCachedObjects().isNotEmpty()) { + Launcher.instance.consoleSender.sendProperty("manager.startup.loaded.wrappers") + CloudAPI.instance.getWrapperManager().getAllCachedObjects() + .forEach { Launcher.instance.consoleSender.sendMessage("- ${it.getName()}") } + } + + if (CloudAPI.instance.getTemplateManager().getAllCachedObjects().isNotEmpty()) { + Launcher.instance.consoleSender.sendProperty("manager.startup.loaded.templates") + CloudAPI.instance.getTemplateManager().getAllCachedObjects() + .forEach { Launcher.instance.consoleSender.sendMessage("- ${it.getName()}") } + } + + if (CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects().isNotEmpty()) { + Launcher.instance.consoleSender.sendProperty("manager.startup.loaded.groups") + CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + .forEach { Launcher.instance.consoleSender.sendMessage("- ${it.getName()}") } + } + thread(start = true, isDaemon = false, appClassLoader) { + this.cloudModuleHandler.loadAllUnloadedModules() + } + + if (CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects().isEmpty()) { + Launcher.instance.setupManager.queueSetup(CreateDefaultProxyGroup()) + Launcher.instance.setupManager.waitForAllSetups() + Launcher.instance.setupManager.queueSetup(CreateDefaultLobbyGroup()) + } + + this.profileFile.create() + } + + private fun createDirectories() { + for (file in listOf( + File(DirectoryPaths.paths.storagePath), + File(DirectoryPaths.paths.wrappersPath), + File(DirectoryPaths.paths.minecraftJarsPath), + File(DirectoryPaths.paths.serverGroupsPath), + File(DirectoryPaths.paths.lobbyGroupsPath), + File(DirectoryPaths.paths.proxyGroupsPath), + File(DirectoryPaths.paths.languagesPath), + File(DirectoryPaths.paths.modulesPath), + File(DirectoryPaths.paths.templatesPath), + File(DirectoryPaths.paths.templatesPath + "EVERY"), + File(DirectoryPaths.paths.templatesPath + "EVERY_SERVER"), + File(DirectoryPaths.paths.templatesPath + "EVERY_PROXY") + )) { + file.mkdirs() + } + } + + override fun onDisable() { + this.cloudModuleHandler.unloadAllModules() + this.profileFile.create() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/ProfileFile.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/ProfileFile.kt new file mode 100644 index 000000000..ccc0f8cf5 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/ProfileFile.kt @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths +import kotlin.io.path.name +import kotlin.io.path.pathString + +class ProfileFile { + + private val file = File("profile.sc") + + fun create() { + val pathStream = Files.walk(Paths.get("")) + val jsonLib = JsonLib.empty() + pathStream + .filter(Files::isRegularFile) + .filter { + it.name.endsWith(".json") + && !it.name.contains("database") + && !it.pathString.contains(DirectoryPaths.paths.languagesPath) + } + .forEach { + val pathName = it.pathString.replace(".json", "") + val file = File(it.toUri()) + val jsonFile = JsonLib.fromJsonFile(file) ?: return@forEach + jsonLib.append(pathName, jsonFile.jsonElement) + } + + pathStream.close() + jsonLib.saveAsFile(file) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/AbstractCloudConnectionHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/AbstractCloudConnectionHandler.kt new file mode 100644 index 000000000..ccf2c4e4d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/AbstractCloudConnectionHandler.kt @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup.server + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.utils.time.TimeAmountMeasurer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.handler.DefaultConnectionHandler +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:56 + * @author Frederick Baier + */ +abstract class AbstractCloudConnectionHandler : DefaultConnectionHandler() { + + private val unknownHostMessageShownTimeStamps = TimeAmountMeasurer(TimeUnit.SECONDS.toMillis(10)) + + override fun onConnectionActive(connection: IConnection) { + super.onConnectionActive(connection) + val host = connection.getHost() ?: return + val wrapperByHost = CloudAPI.instance.getWrapperManager().getWrapperByHost(host) + if (wrapperByHost == null) { + if (this.unknownHostMessageShownTimeStamps.getMeasuredAmount() < 3) { + Launcher.instance.consoleSender.sendProperty("manager.connection.unknown-host", host) + } + this.unknownHostMessageShownTimeStamps.addEntry() + return + } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/CommunicationConnectionHandlerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/CommunicationConnectionHandlerImpl.kt new file mode 100644 index 000000000..68403d809 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/CommunicationConnectionHandlerImpl.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup.server + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.network.component.IAuthenticatable +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.sync.`object`.GlobalPropertyHolder +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.manager.impl.CloudPlayerManagerImpl +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.server.client.connectedclient.IConnectedClient +import eu.thesimplecloud.launcher.startup.Launcher + +class CommunicationConnectionHandlerImpl : AbstractCloudConnectionHandler() { + + override fun onConnectionInactive(connection: IConnection) { + super.onConnectionInactive(connection) + connection as IConnectedClient + val clientValue = connection.getClientValue() + clientValue ?: return + clientValue as IAuthenticatable + clientValue.setAuthenticated(false) + + if (clientValue is IWrapperInfo) { + unregisterServicesRunningOnWrapper(clientValue) + val wrapperUpdater = clientValue.getUpdater() + wrapperUpdater.setTemplatesReceived(false) + wrapperUpdater.setCurrentlyStartingServices(0) + wrapperUpdater.setUsedMemory(0) + wrapperUpdater.update() + Launcher.instance.consoleSender.sendProperty("manager.disconnect.wrapper", clientValue.getName()) + } + + if (clientValue is ICloudService) { + val playerManager = CloudAPI.instance.getCloudPlayerManager() as CloudPlayerManagerImpl + playerManager.resetPlayerUpdates(clientValue.getName()) + CloudAPI.instance.getCloudServiceManager().update(clientValue) + Launcher.instance.consoleSender.sendProperty("manager.disconnect.service", clientValue.getName()) + } + val globalPropertyHolder = CloudAPI.instance.getGlobalPropertyHolder() as GlobalPropertyHolder + globalPropertyHolder.removeConnectionFromUpdates(connection) + } + + private fun unregisterServicesRunningOnWrapper(clientValue: IWrapperInfo) { + val services = CloudAPI.instance.getCloudServiceManager().getServicesRunningOnWrapper(clientValue.getName()) + services.forEach { + it.setState(ServiceState.CLOSED) + it.setOnlineCount(0) + it.setAuthenticated(false) + it.update() + } + services.forEach { CloudAPI.instance.getCloudServiceManager().delete(it) } + } + + override fun onFailure(connection: IConnection, ex: Throwable) { + Launcher.instance.logger.exception(ex) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ManagerAccessHandler.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ManagerAccessHandler.kt new file mode 100644 index 000000000..02c5a4bc6 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ManagerAccessHandler.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup.server + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.access.IAccessHandler +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection + +/** + * Created by IntelliJ IDEA. + * Date: 04.12.2020 + * Time: 17:56 + * @author Frederick Baier + */ +class ManagerAccessHandler : IAccessHandler { + + override fun isAccessAllowed(connection: IConnection): Boolean { + val host = connection.getHost() ?: return false + val wrapperByHost = CloudAPI.instance.getWrapperManager().getWrapperByHost(host) + return wrapperByHost != null + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ServerHandlerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ServerHandlerImpl.kt new file mode 100644 index 000000000..d9f7870bc --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/ServerHandlerImpl.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup.server + +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.clientserverapi.lib.handler.IServerHandler +import eu.thesimplecloud.clientserverapi.server.INettyServer +import eu.thesimplecloud.launcher.startup.Launcher + +class ServerHandlerImpl : IServerHandler { + override fun onServerShutdown(nettyServer: INettyServer) { + Launcher.instance.consoleSender.sendProperty("manager.server.stopped") + } + + override fun onServerStartException(nettyServer: INettyServer, ex: Throwable) { + Launcher.instance.logger.severe("Server start failed.") + Launcher.instance.logger.exception(ex) + } + + override fun onServerStarted(nettyServer: INettyServer) { + Launcher.instance.consoleSender.sendProperty("manager.server.listening", nettyServer.getPort().toString()) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/TemplateConnectionHandlerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/TemplateConnectionHandlerImpl.kt new file mode 100644 index 000000000..d6bc84107 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/startup/server/TemplateConnectionHandlerImpl.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.startup.server + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.launcher.startup.Launcher + +class TemplateConnectionHandlerImpl : AbstractCloudConnectionHandler() { + + override fun onFailure(connection: IConnection, ex: Throwable) { + Launcher.instance.logger.exception(ex) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/ConversionException.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/ConversionException.kt new file mode 100644 index 000000000..023c40268 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/ConversionException.kt @@ -0,0 +1,27 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +class ConversionException(minorVersion: Int, cause: Throwable) : + Exception("Conversion to version 2.${minorVersion} failed", cause) { +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_0_To_2_1.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_0_To_2_1.kt new file mode 100644 index 000000000..8bea34c5b --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_0_To_2_1.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:15 + * @author Frederick Baier + */ +class Converter_2_0_To_2_1 : IVersionConverter { + + override fun getTargetMinorVersion(): Int { + return 1 + } + + override fun convert() { + File(DirectoryPaths.paths.storagePath + "mc-versions.json").delete() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_2_To_2_3.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_2_To_2_3.kt new file mode 100644 index 000000000..eccee8b1d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_2_To_2_3.kt @@ -0,0 +1,69 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.utils.ZipUtils +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 29/01/2021 + * Time: 21:15 + * @author Frederick Baier + */ +class Converter_2_2_To_2_3 : IVersionConverter { + + override fun getTargetMinorVersion(): Int { + return 3 + } + + override fun convert() { + deleteJarsWithoutGson() + } + + //Deletes the jar files without gson inside. + //Because in SimpleCloud 2.2 gson was deleted from downloaded jar files to ensure compatibility with 1.8 + //Since 1.8 is no longer supported gson is no longer linked into the classpath. + //Therefore, the jars have to contain gson. Otherwise, they won't start. + //To ensure that gson is inside the jars all jars without gson get deleted and re-downloaded automatically, when they are needed. + private fun deleteJarsWithoutGson() { + for (jarFile in getMinecraftJarFiles()) { + deleteIfFileHasNoGson(jarFile) + } + } + + + private fun deleteIfFileHasNoGson(file: File) { + if (!ZipUtils().hasPath(file, "com/google/gson/")) { + file.delete() + } + } + + private fun getMinecraftJarFiles(): List { + val minecraftJarsPath = DirectoryPaths.paths.minecraftJarsPath + val minecraftJarsDir = File(minecraftJarsPath) + if (!minecraftJarsDir.exists()) return emptyList() + return minecraftJarsDir.listFiles()!!.filter { it.name.endsWith(".jar") } + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_3_To_2_4.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_3_To_2_4.kt new file mode 100644 index 000000000..30d4ad5ac --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_3_To_2_4.kt @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +/** + * Date: 18.06.22 + * Time: 16:44 + * @author Frederick Baier + * + */ +class Converter_2_3_To_2_4 : IVersionConverter { + + override fun getTargetMinorVersion(): Int { + return 4 + } + + override fun convert() { + convertGroupConfigs() + convertLanguageFile() + } + + private fun convertLanguageFile() { + val languagesDir = File(DirectoryPaths.paths.languagesPath) + if (!languagesDir.exists()) + return + languagesDir.listFiles()?.forEach { + replaceAndToParagraph(it) + } + } + + private fun replaceAndToParagraph(file: File) { + val lines = file.readLines() + val newLines = lines.map { it.replace("&", "§") } + file.writeText(newLines.joinToString("\n")) + } + + private fun convertGroupConfigs() { + convertGroupsInDirectory(File(DirectoryPaths.paths.proxyGroupsPath)) + convertGroupsInDirectory(File(DirectoryPaths.paths.lobbyGroupsPath)) + convertGroupsInDirectory(File(DirectoryPaths.paths.serverGroupsPath)) + + } + + private fun convertGroupsInDirectory(dir: File) { + dir.listFiles()?.forEach { + convertSingleGroupByFile(it) + } + } + + private fun convertSingleGroupByFile(file: File) { + val groupJsonLib = JsonLib.fromJsonFile(file) ?: return + if (groupJsonLib.jsonElement.asJsonObject.has("javaCommandName")) { + return + } + groupJsonLib.append("javaCommandName", "java") + groupJsonLib.saveAsFile(file) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_4_To_2_5.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_4_To_2_5.kt new file mode 100644 index 000000000..89ef88efe --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/Converter_2_4_To_2_5.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +/** + * Date: 18.06.22 + * Time: 16:44 + * @author Frederick Baier + * + */ +class Converter_2_4_To_2_5 : IVersionConverter { + + override fun getTargetMinorVersion(): Int { + return 5 + } + + override fun convert() { + File(DirectoryPaths.paths.storagePath, "updateable-modules.json").delete() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/IVersionConverter.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/IVersionConverter.kt new file mode 100644 index 000000000..3b3862563 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/IVersionConverter.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +interface IVersionConverter { + + /** + * Returns the version this converter converts to + * + */ + fun getTargetMinorVersion(): Int + + /** + * Coverts from the previous version to [getTargetMinorVersion] + */ + fun convert() + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/VersionConversionManager.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/VersionConversionManager.kt new file mode 100644 index 000000000..f3df165dc --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/manager/update/converter/VersionConversionManager.kt @@ -0,0 +1,101 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.manager.update.converter + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.startup.Launcher +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 18.06.2020 + * Time: 12:38 + * @author Frederick Baier + */ +class VersionConversionManager { + + private val converters = listOf( + Converter_2_0_To_2_1(), + Converter_2_2_To_2_3(), + Converter_2_3_To_2_4(), + Converter_2_4_To_2_5() + ) + + private val lastStartedVersionFile = File(DirectoryPaths.paths.storagePath + "versions/lastStartedVersion.json") + + fun convertIfNecessary() { + getConvertersToExecute().forEach { converter -> + executeConverter(converter) + } + writeLastStartedVersion() + } + + private fun executeConverter(converter: IVersionConverter) { + Launcher.instance.logger.info("Running converter to version 2.${converter.getTargetMinorVersion()}...") + try { + converter.convert() + } catch (e: Exception) { + throw ConversionException(converter.getTargetMinorVersion(), e) + } + Launcher.instance.logger.info("Converted") + } + + private fun getConvertersToExecute(): ArrayList { + val lastStartedVersion = getLastStartedVersion() + val currentVersion = Launcher.instance.getCurrentVersion() + val lastMinorVersion = getMinorVersionFromVersionString(lastStartedVersion) + val currentMinorVersion = getMinorVersionFromVersionString(currentVersion) + val list = ArrayList() + for (i in lastMinorVersion until currentMinorVersion) { + val version = getConverterByToVersion(i + 1) + version?.let { list.add(version) } + } + return list + } + + private fun getConverterByToVersion(version: Int): IVersionConverter? { + return this.converters.firstOrNull { it.getTargetMinorVersion() == version } + } + + private fun getMinorVersionFromVersionString(versionString: String): Int { + return versionString.split(".")[1].toInt() + } + + private fun getLastStartedVersion(): String { + this.lastStartedVersionFile.parentFile.mkdirs() + val config = JsonLib.fromJsonFile(this.lastStartedVersionFile) ?: return "1.2.0-BETA" + return config.getObject(String::class.java) + } + + private fun writeLastStartedVersion() { + JsonLib.fromObject(Launcher.instance.getCurrentVersion()).saveAsFile(lastStartedVersionFile) + } + + fun writeLastStartedVersionIfFileDoesNotExist() { + if (!this.lastStartedVersionFile.exists()) { + writeLastStartedVersion() + } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudAPIImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudAPIImpl.kt new file mode 100644 index 000000000..6431d13b1 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudAPIImpl.kt @@ -0,0 +1,86 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.IEventManager +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.ILanguageManager +import eu.thesimplecloud.api.language.LanguageManager +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.version.IServiceVersionHandler +import eu.thesimplecloud.api.service.version.ServiceVersionHandler +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.sync.list.manager.ISynchronizedObjectListManager +import eu.thesimplecloud.api.sync.list.manager.SynchronizedObjectListManager +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.bootstrap.ICommunicationBootstrap + +class CloudAPIImpl : CloudAPI() { + + private val cloudServiceGroupManager = CloudServiceGroupManagerImpl() + private val cloudServiceManager = CloudServiceManagerImpl() + private val commandExecuteManager = CommandExecuteManagerImpl() + private val cloudPlayerManager = CloudPlayerManagerImpl() + private val eventManager = EventManagerImpl() + private val synchronizedObjectListManager = SynchronizedObjectListManager() + private val serviceVersionHandler = ServiceVersionHandler() + private val languageManager = LanguageManager() + + init { + getCacheListManager().registerCacheList(getWrapperManager()) + getCacheListManager().registerCacheList(getCloudServiceManager()) + getCacheListManager().registerCacheList(getCloudServiceGroupManager()) + getCacheListManager().registerCacheList(getTemplateManager()) + getCacheListManager().registerCacheList(getCloudPlayerManager()) + } + + override fun getCloudServiceGroupManager(): ICloudServiceGroupManager = this.cloudServiceGroupManager + + override fun getCloudServiceManager(): ICloudServiceManager = this.cloudServiceManager + + override fun getCloudPlayerManager(): ICloudPlayerManager = this.cloudPlayerManager + + override fun getEventManager(): IEventManager = this.eventManager + + override fun getCommandExecuteManager(): ICommandExecuteManager = this.commandExecuteManager + + override fun getThisSidesCommunicationBootstrap(): ICommunicationBootstrap = Wrapper.instance.communicationClient + + override fun getSynchronizedObjectListManager(): ISynchronizedObjectListManager = this.synchronizedObjectListManager + + override fun getServiceVersionHandler(): IServiceVersionHandler = this.serviceVersionHandler + + override fun getLanguageManager(): ILanguageManager = this.languageManager + + override fun getThisSidesName(): String = Wrapper.instance.thisWrapperName ?: "Wrapper" + + override fun getThisSidesNetworkComponent(): INetworkComponent { + return Wrapper.instance.getThisWrapper() + } + + override fun getThisSidesCloudModule(): ICloudModule = Wrapper.instance +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceGroupManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceGroupManagerImpl.kt new file mode 100644 index 000000000..08d3b340c --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceGroupManagerImpl.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.network.packets.service.PacketIOStartCloudService +import eu.thesimplecloud.api.network.packets.servicegroup.PacketIOCreateServiceGroup +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.service.start.future.IServiceStartPromise +import eu.thesimplecloud.api.service.start.future.ServiceStartPromise +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.impl.AbstractCloudServiceGroupManager +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class CloudServiceGroupManagerImpl : AbstractCloudServiceGroupManager() { + + override fun createServiceGroup(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise { + return Wrapper.instance.connectionToManager.sendQuery(PacketIOCreateServiceGroup(cloudServiceGroup)) + } + + override fun startNewService(serviceStartConfiguration: IServiceStartConfiguration): IServiceStartPromise { + val namePromise = + Wrapper.instance.connectionToManager.sendQuery(PacketIOStartCloudService(serviceStartConfiguration)) + val servicePromise = namePromise.then { CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(it)!! } + return ServiceStartPromise(servicePromise) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceManagerImpl.kt new file mode 100644 index 000000000..efba8cbad --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CloudServiceManagerImpl.kt @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.impl + +import eu.thesimplecloud.api.event.service.CloudServiceConnectedEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.listenerextension.cloudListener +import eu.thesimplecloud.api.network.packets.service.PacketIOCopyService +import eu.thesimplecloud.api.network.packets.service.PacketIOStopCloudService +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.service.impl.AbstractCloudServiceManager +import eu.thesimplecloud.base.wrapper.process.ProcessCopier +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class CloudServiceManagerImpl : AbstractCloudServiceManager() { + + override fun stopService(cloudService: ICloudService): ICommunicationPromise { + if (cloudService.getWrapperName() == Wrapper.instance.thisWrapperName) { + if (cloudService.getState() == ServiceState.PREPARED) { + Wrapper.instance.processQueue?.removeFromQueue(cloudService) + } else { + val cloudServiceProcess = + Wrapper.instance.cloudServiceProcessManager.getCloudServiceProcessByServiceName(cloudService.getName()) + cloudServiceProcess?.shutdown() + } + } else { + Wrapper.instance.connectionToManager.sendUnitQuery(PacketIOStopCloudService(cloudService.getName())) + } + return cloudListener() + .addCondition { it.cloudService == cloudService } + .toUnitPromise() + } + + override fun copyService(cloudService: ICloudService, path: String): ICommunicationPromise { + val selfWrapper = Wrapper.instance.getThisWrapper() + if (selfWrapper != cloudService.getWrapper()) + return Wrapper.instance.connectionToManager.sendUnitQuery( + PacketIOCopyService(cloudService, path), + 20 * 1000 + ) + + val serviceProcess = Wrapper.instance.cloudServiceProcessManager + .getCloudServiceProcessByServiceName(cloudService.getName()) + serviceProcess ?: return CommunicationPromise.failed(IllegalStateException("Cannot copy inactive service")) + return ProcessCopier(cloudService).copy(path) + } + + override fun startService(cloudService: ICloudService): ICommunicationPromise { + val processQueue = Wrapper.instance.processQueue + checkNotNull(processQueue) { "Process-Queue was null while trying to add a service to the queue." } + processQueue.addToQueue(cloudService) + return cloudListener() + .addCondition { it.cloudService == cloudService } + .toUnitPromise() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CommandExecuteManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CommandExecuteManagerImpl.kt new file mode 100644 index 000000000..4bcae5df2 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/CommandExecuteManagerImpl.kt @@ -0,0 +1,57 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.impl + +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.network.packets.screen.PacketIOExecuteCommand +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.launcher.startup.Launcher + +class CommandExecuteManagerImpl : ICommandExecuteManager { + + override fun executeCommand(commandExecutable: ICommandExecutable, command: String) { + if (commandExecutable is ICloudService && commandExecutable.getWrapper() == Wrapper.instance.getThisWrapper()) { + val serviceProcess = + Wrapper.instance.cloudServiceProcessManager.getCloudServiceProcessByServiceName(commandExecutable.getName()) + serviceProcess?.executeCommand(command) + return + } + if (commandExecutable is IWrapperInfo && commandExecutable == Wrapper.instance.getThisWrapper()) { + Launcher.instance.executeCommand(command) + return + } + val cloudClientType = + if (commandExecutable is ICloudService) NetworkComponentType.SERVICE else NetworkComponentType.WRAPPER + Wrapper.instance.connectionToManager.sendUnitQuery( + PacketIOExecuteCommand( + cloudClientType, + commandExecutable.getName(), + command + ) + ) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/EventManagerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/EventManagerImpl.kt new file mode 100644 index 000000000..cc194de40 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/impl/EventManagerImpl.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.impl + +import eu.thesimplecloud.api.eventapi.BasicEventManager +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.api.network.packets.event.PacketIOCallEvent +import eu.thesimplecloud.base.wrapper.startup.Wrapper + +class EventManagerImpl : BasicEventManager() { + + override fun call(event: IEvent, fromPacket: Boolean) { + //don't call event if fromPacket is true because the event will be called via the received packet. + if (!fromPacket && event is ISynchronizedEvent) { + Wrapper.instance.connectionToManager.sendUnitQuery(PacketIOCallEvent(event)) + } else { + super.call(event, fromPacket) + } + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/logger/LoggerMessageListenerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/logger/LoggerMessageListenerImpl.kt new file mode 100644 index 000000000..c9f5c6fc9 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/logger/LoggerMessageListenerImpl.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.logger + +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.client.packets.PacketOutScreenMessage +import eu.thesimplecloud.launcher.logging.ILoggerMessageListener +import eu.thesimplecloud.launcher.logging.LogType + +class LoggerMessageListenerImpl : ILoggerMessageListener { + + override fun message(msg: String, logType: LogType) { + if (Wrapper.instance.connectionToManager.isOpen() && Wrapper.instance.isWrapperNameSet()) + Wrapper.instance.connectionToManager + .sendUnitQuery( + PacketOutScreenMessage( + NetworkComponentType.WRAPPER, + Wrapper.instance.getThisWrapper(), + msg + ) + ) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInJvmArguments.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInJvmArguments.kt new file mode 100644 index 000000000..629fa3ff6 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInJvmArguments.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.network.packets + +import eu.thesimplecloud.base.core.jvm.JvmArgumentsConfig +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 12.06.2020 + * Time: 18:57 + */ +class PacketInJvmArguments() : ObjectPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val value = this.value ?: return contentException("value") + Wrapper.instance.jvmArgumentsConfig = value + + return unit() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInReloadExistingModules.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInReloadExistingModules.kt new file mode 100644 index 000000000..59fcebb46 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInReloadExistingModules.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.network.packets + +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketInReloadExistingModules : JsonPacket() { + override suspend fun handle(connection: IConnection): ICommunicationPromise { + Wrapper.instance.reloadExistingModules() + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInSetWrapperName.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInSetWrapperName.kt new file mode 100644 index 000000000..074cd9d59 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/PacketInSetWrapperName.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.network.packets + + +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketInSetWrapperName : ObjectPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val name = this.value ?: return contentException("value") + Wrapper.instance.thisWrapperName = name + Wrapper.instance.startProcessQueue() + if (Wrapper.instance.isStartedInManagerDirectory()) { + val thisWrapper = Wrapper.instance.getThisWrapper() + val wrapperUpdater = thisWrapper.getUpdater() + wrapperUpdater.setTemplatesReceived(true) + wrapperUpdater.update() + } + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/template/PacketOutGetTemplates.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/template/PacketOutGetTemplates.kt new file mode 100644 index 000000000..5a6a2ef8e --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/network/packets/template/PacketOutGetTemplates.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.network.packets.template + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket + +class PacketOutGetTemplates : JsonPacket() { + override suspend fun handle(connection: IConnection) = unit() +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcess.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcess.kt new file mode 100644 index 000000000..349802184 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcess.kt @@ -0,0 +1,238 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.listenerextension.cloudListener +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.service.impl.DefaultCloudService +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudProxyGroup +import eu.thesimplecloud.base.wrapper.process.filehandler.ServiceDirectory +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.client.packets.PacketOutScreenMessage +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.config.java.JavaVersion +import eu.thesimplecloud.launcher.startup.Launcher +import java.io.BufferedReader +import java.io.File +import java.io.IOException +import java.io.InputStreamReader +import java.util.concurrent.TimeUnit + + +class CloudServiceProcess(private val cloudService: ICloudService) : ICloudServiceProcess { + + private var process: Process? = null + private val serviceDirectory = ServiceDirectory(cloudService) + + override fun start(): ICommunicationPromise { + Launcher.instance.consoleSender.sendProperty("wrapper.service.starting", cloudService.getName()) + this.cloudService as DefaultCloudService + if (cloudService.getServiceType().isProxy()) { + val proxyGroup = cloudService.getServiceGroup() + proxyGroup as ICloudProxyGroup + this.cloudService.setPort(Wrapper.instance.portManager.getUnusedPort(proxyGroup.getStartPort())) + } else { + this.cloudService.setPort(Wrapper.instance.portManager.getUnusedPort(Launcher.instance.launcherConfig.startServicePort)) + } + this.cloudService.setState(ServiceState.STARTING) + this.cloudService.update().awaitUninterruptibly() + + + val serviceConfigurator = Wrapper.instance.serviceConfigurationManager + .getServiceConfigurator(cloudService.getServiceVersion().serviceAPIType) + serviceConfigurator + ?: throw IllegalStateException("No ServiceConfiguration found by api type: ${cloudService.getServiceVersion().serviceAPIType}") + + serviceDirectory.copyTemplateFilesAndModules() + serviceConfigurator.configureService(cloudService, this.serviceDirectory.serviceTmpDirectory) + + val executableJar = File(this.serviceDirectory.serviceTmpDirectory, "server.jar") + val processBuilder = createProcessBuilder(executableJar) + .directory(this.serviceDirectory.serviceTmpDirectory) + + + val process = processBuilder.start() + this.process = process + + val bufferedReader = BufferedReader(InputStreamReader(process.inputStream)) + + while (process.isAlive) { + try { + val s = bufferedReader.readLine() ?: continue + if (!s.equals("", ignoreCase = true) && !s.equals(" ", ignoreCase = true) && !s.equals( + ">", + ignoreCase = true + ) + && !s.equals(" >", ignoreCase = true) && !s.contains("InitialHandler has pinged") + ) { + Wrapper.instance.connectionToManager.sendUnitQuery( + PacketOutScreenMessage( + NetworkComponentType.SERVICE, + getCloudService(), + s + ) + ) + .awaitUninterruptibly() + //Launcher.instance.logger.console("[${cloudService.getName()}]$s") + } + } catch (e: IOException) { + e.printStackTrace() + } + } + + bufferedReader.close() + printErrorStream() + processStopped() + //this method will not return before the process stops + return CommunicationPromise.of(Unit) + } + + private fun printErrorStream() { + val errorStream = this.process!!.errorStream + val reader = BufferedReader(InputStreamReader(errorStream)) + while (reader.ready()) { + val line = reader.readLine() ?: continue + Launcher.instance.logger.warning("[${cloudService.getName()}]$line") + } + reader.close() + } + + private fun processStopped() { + Launcher.instance.consoleSender.sendProperty("wrapper.service.stopped", cloudService.getName()) + Wrapper.instance.cloudServiceProcessManager.unregisterServiceProcess(this) + deleteTemporaryFiles() + if (Wrapper.instance.connectionToManager.isOpen()) { + var tries = 0 + while (this.cloudService.isAuthenticated()) { + Thread.sleep(100) + tries++ + if (tries == 30) break + } + this.cloudService.setOnlineCount(0) + this.cloudService.setState(ServiceState.CLOSED) + CloudAPI.instance.getCloudServiceManager().delete(this.cloudService).awaitUninterruptibly() + Wrapper.instance.updateWrapperData() + } + + Wrapper.instance.portManager.setPortUnused(this.cloudService.getPort()) + } + + private fun deleteTemporaryFiles() { + while (true) { + try { + if (this.cloudService.isStatic()) { + this.serviceDirectory.deleteTemporaryModuleFiles() + } else { + this.serviceDirectory.deleteServiceDirectoryUnsafe() + } + break + } catch (_: Exception) { + + } + } + } + + private fun createProcessBuilder(jarFile: File): ProcessBuilder { + return ProcessBuilder(*getStartCommandArgs(jarFile)) + } + + private fun getStartCommandArgs(jarFile: File): Array { + val jvmArguments = Wrapper.instance.jvmArgumentsConfig.jvmArguments.filter { + it.groups.contains("all") || it.groups.contains(this.cloudService.getGroupName()) || it.groups.contains(this.cloudService.getServiceType().name) + } + + val commandName = cloudService.getServiceGroup().getJavaCommandName() + var commandNameExist = JavaVersion.paths.versions.keys.contains(commandName) + if (commandName == "java") commandNameExist = true + if (!commandNameExist) throw IllegalArgumentException("The java command for this name wasn't configured yet.") + + val commands = mutableListOf(JavaVersion.paths.versions[commandName] ?: "java") + + jvmArguments.forEach { commands.addAll(it.arguments) } + + val startArguments = arrayListOf( + "-Dcom.mojang.eula.agree=true", + "-Djline.terminal=jline.UnsupportedTerminal", + "-Xms" + cloudService.getMaxMemory() + "M", + "-Xmx" + cloudService.getMaxMemory() + "M", + "-jar", + jarFile.absolutePath + ) + commands.addAll(startArguments) + + if (cloudService.getServiceVersion().serviceAPIType == ServiceAPIType.SPIGOT) { + commands.add("nogui") + } + return commands.toTypedArray() + } + + override fun forceStop() { + process?.destroyForcibly() + } + + override fun getTempDirectory(): File { + return this.serviceDirectory.serviceTmpDirectory + } + + override fun isActive(): Boolean = this.process?.isAlive ?: false + + override fun shutdown(): ICommunicationPromise { + if (isActive()) { + if (this.cloudService.getServiceType().isProxy()) { + executeCommand("end") + } else { + executeCommand("stop") + } + Launcher.instance.scheduler.schedule({ + if (isActive()) + forceStop() + }, 7, TimeUnit.SECONDS) + } + return cloudListener() + .addCondition { it.cloudService == this.cloudService } + .toUnitPromise() + } + + override fun executeCommand(command: String) { + val command = command + "\n" + try { + if (process != null && process?.outputStream != null) { + process?.outputStream?.write(command.toByteArray()) + process?.outputStream?.flush() + } + } catch (e: IOException) { + Launcher.instance.logger.warning("[" + this.cloudService.getName() + "]" + " Outputstream is closed.") + } + + } + + + override fun getCloudService(): ICloudService = cloudService + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcessManager.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcessManager.kt new file mode 100644 index 000000000..774b07456 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/CloudServiceProcessManager.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process + +import java.util.concurrent.ConcurrentHashMap + +class CloudServiceProcessManager : ICloudServiceProcessManager { + + private val registeredProcesses = ConcurrentHashMap.newKeySet() + + override fun registerServiceProcess(cloudServiceProcess: ICloudServiceProcess) { + this.registeredProcesses.add(cloudServiceProcess) + } + + override fun unregisterServiceProcess(cloudServiceProcess: ICloudServiceProcess) { + this.registeredProcesses.remove(cloudServiceProcess) + } + + override fun getAllProcesses(): Set = this.registeredProcesses + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcess.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcess.kt new file mode 100644 index 000000000..3e6d1b01d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcess.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.bootstrap.IBootstrap +import java.io.File + +interface ICloudServiceProcess : IBootstrap { + + /** + * Returns the [ICloudService] this process executes + */ + fun getCloudService(): ICloudService + + /** + * Terminates this process immediately (not recommended to use) + */ + fun forceStop() + + /** + * Returns the directory the service is executed in + */ + fun getTempDirectory(): File + + /** + * Executes a command on this service + */ + fun executeCommand(command: String) + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcessManager.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcessManager.kt new file mode 100644 index 000000000..f4cb70012 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ICloudServiceProcessManager.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process + +import eu.thesimplecloud.api.service.ICloudService + +interface ICloudServiceProcessManager { + + /** + * Registers a service process on this wrapper. + */ + fun registerServiceProcess(cloudServiceProcess: ICloudServiceProcess) + + /** + * Registers a service process on this wrapper. + */ + fun unregisterServiceProcess(cloudServiceProcess: ICloudServiceProcess) + + /** + * Returns a list of all registered cloud processes + */ + fun getAllProcesses(): Set + + /** + * Returns the [ICloudServiceProcess] found by the specified service [name] + */ + fun getCloudServiceProcessByServiceName(name: String): ICloudServiceProcess? = + getAllProcesses().firstOrNull { it.getCloudService().getName().equals(name, true) } + + /** + * Returns the [ICloudServiceProcess] found by the specified service [service] + */ + fun getCloudServiceProcessByService(service: ICloudService): ICloudServiceProcess? = + getCloudServiceProcessByServiceName(service.getName()) + + /** + * Stops all registered services. + */ + fun stopAllServices() = getAllProcesses().forEach { it.shutdown() } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ProcessCopier.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ProcessCopier.kt new file mode 100644 index 000000000..5ca0b9bb2 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/ProcessCopier.kt @@ -0,0 +1,109 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.utils.FileFinder +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.lib.defaultpackets.PacketIODeleteFile +import eu.thesimplecloud.clientserverapi.lib.defaultpackets.PacketIOUnzipZipFile +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.flatten +import eu.thesimplecloud.clientserverapi.lib.util.ZipUtils +import org.apache.commons.io.FileUtils +import java.io.File +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 09.06.2020 + * Time: 14:32 + * @author Frederick Baier + */ +class ProcessCopier(val cloudService: ICloudService) { + + private val blockedCopyFileNames = arrayListOf( + "SIMPLE-CLOUD.json", + "SimpleCloud-Plugin.jar" + ) + + fun copy(path: String): ICommunicationPromise { + val serviceProcess = Wrapper.instance.cloudServiceProcessManager + .getCloudServiceProcessByServiceName(cloudService.getName()) + serviceProcess ?: return CommunicationPromise.failed(IllegalStateException("Cannot copy inactive service")) + + val tempDirectory = serviceProcess.getTempDirectory() + val dirToCopy = if (path == ".") tempDirectory else File(tempDirectory, path) + if (!dirToCopy.exists()) + return CommunicationPromise.failed(IllegalArgumentException("Directory does not exist")) + if (!dirToCopy.isDirectory) + return CommunicationPromise.failed(IllegalArgumentException("The specified file must be a directory")) + return if (Wrapper.instance.isStartedInManagerDirectory()) { + copyUsingFiles(dirToCopy, tempDirectory) + } else { + copyUsingNetty(dirToCopy, tempDirectory) + } + } + + private fun copyUsingNetty(dirToCopy: File, tempDirectory: File): ICommunicationPromise { + val zippedTemplatesDir = File(DirectoryPaths.paths.zippedTemplatesPath) + val zipFile = File(zippedTemplatesDir, cloudService.getName() + ".zip") + zipFile.parentFile.mkdirs() + ZipUtils.zipFiles(zipFile, FileFinder.getAllFiles(dirToCopy) + .filter { !isBlockedCopyFile(it.name) }, tempDirectory.path + "/") + + //send file + val savePath = DirectoryPaths.paths.zippedTemplatesPath + "T-" + cloudService.getName() + ".zip" + val dirToUnzip = cloudService.getTemplate().getDirectory().path + return Wrapper.instance.connectionToManager.sendFile(zipFile, savePath, 20 * 1000) + .thenDelayed(1200, TimeUnit.MILLISECONDS) { + val relativePathInTemplate = dirToCopy.path.replace(tempDirectory.path, "") + val dirToReplace = dirToUnzip + if (relativePathInTemplate == "/.") "" else relativePathInTemplate + //delete folder to replace + Wrapper.instance.connectionToManager.sendUnitQuery(PacketIODeleteFile(dirToReplace)) + }.flatten(10 * 1000).thenDelayed(1000, TimeUnit.MILLISECONDS) { + //unzip file + Wrapper.instance.connectionToManager.sendUnitQuery( + PacketIOUnzipZipFile(savePath, dirToUnzip), + 10 * 1000 + ) + }.flatten().throwFailure() + + } + + private fun copyUsingFiles(dirToCopy: File, tempDirectory: File): ICommunicationPromise { + val templateDir = cloudService.getTemplate().getDirectory() + val relativePathInTemplate = dirToCopy.path.replace(tempDirectory.path, "") + val dirToCopyTo = File(templateDir, relativePathInTemplate) + FileUtils.copyDirectory(dirToCopy, dirToCopyTo) { !isBlockedCopyFile(it.name) } + return CommunicationPromise.of(Unit) + } + + private fun isBlockedCopyFile(fileName: String): Boolean { + return this.blockedCopyFileNames.contains(fileName) + || Wrapper.instance.existingModules.map { it.file.name }.contains(fileName) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/LoadedServiceVersion.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/LoadedServiceVersion.kt new file mode 100644 index 000000000..833155511 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/LoadedServiceVersion.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.filehandler + +import org.apache.commons.io.FileUtils +import java.io.File + +class LoadedServiceVersion( + private val srcFile: File, + val fileNameToExecute: String +) { + + fun copyToDirectory(destDirectory: File) { + if (this.srcFile.isDirectory) { + copyDirectoryToDirectory(destDirectory) + return + } + copyFilToDirectory(destDirectory) + } + + private fun copyDirectoryToDirectory(destDirectory: File) { + FileUtils.copyDirectory(srcFile, destDirectory) + } + + private fun copyFilToDirectory(destDirectory: File) { + val destFile = File(destDirectory, this.srcFile.name) + FileUtils.copyFile(this.srcFile, destFile) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceDirectory.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceDirectory.kt new file mode 100644 index 000000000..0b43c7e18 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceDirectory.kt @@ -0,0 +1,171 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.filehandler + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.clientserverapi.client.NettyClient +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.ModuleCopyType +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.launcher.utils.FileCopier +import org.apache.commons.io.FileUtils +import java.io.File +import java.io.IOException + +class ServiceDirectory(private val cloudService: ICloudService) { + + private var copiedModulesAsPlugins: List = emptyList() + val serviceTmpDirectory = getServiceTmpDirectory(cloudService) + + fun copyTemplateFilesAndModules() { + copyServiceVersion() + copyTemplateFiles() + copyModules() + } + + fun deleteTemporaryModuleFiles() { + this.copiedModulesAsPlugins.forEach { it.delete() } + } + + @Throws(IOException::class) + fun deleteServiceDirectoryUnsafe() { + FileUtils.deleteDirectory(this.serviceTmpDirectory) + } + + private fun copyServiceVersion() { + val loadedServiceVersion = + Wrapper.instance.serviceVersionLoader.loadVersionFile(this.cloudService.getServiceVersion()) + loadedServiceVersion.copyToDirectory(this.serviceTmpDirectory) + renameExecutableJar(loadedServiceVersion) + } + + private fun renameExecutableJar(loadedServiceVersion: LoadedServiceVersion) { + val executableJar = File(this.serviceTmpDirectory, loadedServiceVersion.fileNameToExecute) + val renamedExecutableJar = File(this.serviceTmpDirectory, "server.jar") + executableJar.renameTo(renamedExecutableJar) + } + + private fun copyTemplateFiles() { + val template = cloudService.getTemplate() + val everyDir = File(DirectoryPaths.paths.templatesPath + "EVERY") + val everyTypeDir = if (cloudService.getServiceType() == ServiceType.PROXY) + File(DirectoryPaths.paths.templatesPath + "EVERY_PROXY") + else + File(DirectoryPaths.paths.templatesPath + "EVERY_SERVER") + val templateDirectories = getDirectoriesOfTemplateAndSubTemplates(template) + + val dontCopyTemplates = cloudService.isStatic() && this.serviceTmpDirectory.exists() + if (!dontCopyTemplates) { + if (everyDir.exists()) + FileUtils.copyDirectory(everyDir, this.serviceTmpDirectory) + if (everyTypeDir.exists()) + FileUtils.copyDirectory(everyTypeDir, this.serviceTmpDirectory) + templateDirectories.filter { it.exists() }.forEach { FileUtils.copyDirectory(it, this.serviceTmpDirectory) } + } + + if (cloudService.getServiceType() == ServiceType.PROXY) { + val destServerIconFile = File(this.serviceTmpDirectory, "/server-icon.png") + if (!destServerIconFile.exists()) + FileCopier.copyFileOutOfJar(destServerIconFile, "/files/server-icon.png") + } + + val cloudPluginFile = File(this.serviceTmpDirectory, "/plugins/SimpleCloud-Plugin.jar") + val version = Launcher.instance.getCurrentVersion().replace("-SNAPSHOT", "") + File(DirectoryPaths.paths.storagePath + "pluginJars/SimpleCloud-Plugin-$version.jar").copyTo(cloudPluginFile, true) + + generateServiceFile() + } + + private fun copyModules() { + val modulesForService = getModulesForService() + modulesForService.forEach { + FileUtils.copyFile( + it.file, + File(this.serviceTmpDirectory, "/plugins/" + it.file.name) + ) + } + this.copiedModulesAsPlugins = getModuleFilesInService() + } + + private fun getServiceTmpDirectory(cloudService: ICloudService): File { + return if (cloudService.isStatic()) + File(DirectoryPaths.paths.staticPath + cloudService.getName()) + else + File(DirectoryPaths.paths.tempPath + cloudService.getName()) + } + + private fun getModulesForService(): List { + val modulesByCopyType = Wrapper.instance.existingModules + .filter { it.content.moduleCopyType != ModuleCopyType.NONE }.toMutableList() + if (!cloudService.isLobby()) + modulesByCopyType.removeIf { it.content.moduleCopyType == ModuleCopyType.LOBBY } + if (!cloudService.isProxy()) + modulesByCopyType.removeIf { it.content.moduleCopyType == ModuleCopyType.PROXY } + if (cloudService.isProxy()) + modulesByCopyType.removeIf { it.content.moduleCopyType == ModuleCopyType.SERVER } + + val moduleNamesToCopy = getModulesToCopyOfTemplateAndSubTemplates(this.cloudService.getTemplate()) + val modulesByName = Wrapper.instance.existingModules.filter { moduleNamesToCopy.contains(it.content.name) } + return modulesByCopyType.union(modulesByName).distinctBy { it.content.name } + } + + fun getModuleFilesInService(): List { + val modulesForService = getModulesForService() + return modulesForService.map { File(this.serviceTmpDirectory, "/plugins/" + it.file.name) } + } + + private fun generateServiceFile() { + val communicationClient = Wrapper.instance.communicationClient + communicationClient as NettyClient + JsonLib.empty().append("managerHost", communicationClient.getHost()) + .append("managerPort", communicationClient.getPort()) + .append("serviceName", cloudService.getName()) + .saveAsFile(File(this.serviceTmpDirectory, "SIMPLE-CLOUD.json")) + } + + private fun getDirectoriesOfTemplateAndSubTemplates(template: ITemplate): Set { + val set = HashSet() + for (templateName in template.getInheritedTemplateNames()) { + val subTemplate = CloudAPI.instance.getTemplateManager().getTemplateByName(templateName) + subTemplate?.let { set.addAll(getDirectoriesOfTemplateAndSubTemplates(it)) } + } + set.add(template.getDirectory()) + return set + } + + private fun getModulesToCopyOfTemplateAndSubTemplates(template: ITemplate): Set { + val set = HashSet() + for (templateName in template.getInheritedTemplateNames()) { + val subTemplate = CloudAPI.instance.getTemplateManager().getTemplateByName(templateName) + subTemplate?.let { set.addAll(getModulesToCopyOfTemplateAndSubTemplates(it)) } + } + set.addAll(template.getModuleNamesToCopy()) + return set + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceVersionJarLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceVersionJarLoader.kt new file mode 100644 index 000000000..3edd86ece --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/ServiceVersionJarLoader.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.filehandler + +import eu.thesimplecloud.api.service.version.ServiceVersion +import java.util.concurrent.ConcurrentHashMap + +class ServiceVersionJarLoader { + + private val serviceVersionToLoadedServiceVersion = ConcurrentHashMap() + + @Synchronized + fun loadVersionFile(serviceVersion: ServiceVersion): LoadedServiceVersion { + if (this.serviceVersionToLoadedServiceVersion.contains(serviceVersion)) + return this.serviceVersionToLoadedServiceVersion[serviceVersion]!! + + val singleServiceVersionLoader = SingleServiceVersionLoader(serviceVersion) + val loadedServiceVersion = singleServiceVersionLoader.load() + this.serviceVersionToLoadedServiceVersion[serviceVersion] = loadedServiceVersion + return loadedServiceVersion + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/SingleServiceVersionLoader.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/SingleServiceVersionLoader.kt new file mode 100644 index 000000000..9c1e75dbb --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/filehandler/SingleServiceVersionLoader.kt @@ -0,0 +1,97 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.filehandler + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.runner.utils.Downloader +import org.apache.commons.io.FileUtils +import java.io.File + +class SingleServiceVersionLoader( + private val serviceVersion: ServiceVersion +) { + + fun load(): LoadedServiceVersion { + if (this.serviceVersion.isPaperClip) { + return loadPaperClipVersion() + } + return loadNormalVersion() + } + + private fun loadNormalVersion(): LoadedServiceVersion { + val expectedFile = File(DirectoryPaths.paths.minecraftJarsPath + serviceVersion.name + ".jar") + if (!expectedFile.exists()) { + downloadNormalVersion(expectedFile) + } + return LoadedServiceVersion(expectedFile, expectedFile.name) + } + + private fun downloadNormalVersion(expectedFile: File) { + Downloader().userAgentDownload(this.serviceVersion.downloadURL, expectedFile) + //delete json to prevent bugs in spigot version 1.8 + //ZipUtils().deletePath(expectedFile, "com/google/gson/") + //Thread.sleep(200) + } + + private fun loadPaperClipVersion(): LoadedServiceVersion { + val expectedDir = File(DirectoryPaths.paths.minecraftJarsPath + serviceVersion.name + "/") + if (!expectedDir.exists()) { + downloadAndExecutePaperclip(expectedDir) + } + return LoadedServiceVersion(expectedDir, "paperclip.jar") + } + + private fun downloadAndExecutePaperclip(expectedDir: File) { + val paperClipFile = File(expectedDir, "paperclip.jar") + downloadPaperclip(paperClipFile) + executePaperClip(paperClipFile, expectedDir) + deleteUnnecessaryFiles(expectedDir) + } + + private fun deleteUnnecessaryFiles(expectedDir: File) { + val unnecessaryFileNames = listOf("eula.txt", "server.properties", "logs") + for (fileName in unnecessaryFileNames) { + val file = File(expectedDir, fileName) + if (file.isDirectory) { + FileUtils.deleteDirectory(file) + } else { + file.delete() + } + } + } + + private fun downloadPaperclip(paperClipFile: File) { + Downloader().userAgentDownload(this.serviceVersion.downloadURL, paperClipFile) + } + + private fun executePaperClip(file: File, workingDir: File) { + Launcher.instance.logger.info("Executing paperclip....") + val processBuilder = ProcessBuilder("java", "-jar", file.absolutePath) + processBuilder.directory(workingDir) + processBuilder.start().waitFor() + Launcher.instance.logger.info("Executed paperclip") + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/queue/CloudServiceProcessQueue.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/queue/CloudServiceProcessQueue.kt new file mode 100644 index 000000000..64b658df8 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/queue/CloudServiceProcessQueue.kt @@ -0,0 +1,91 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.queue + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.base.wrapper.process.CloudServiceProcess +import eu.thesimplecloud.base.wrapper.process.ICloudServiceProcess +import eu.thesimplecloud.base.wrapper.startup.Wrapper +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.concurrent.CopyOnWriteArrayList +import kotlin.concurrent.thread + +class CloudServiceProcessQueue { + + private val cloudServiceProcessManager = Wrapper.instance.cloudServiceProcessManager + + private val queue = ConcurrentLinkedQueue() + private val startingServices = CopyOnWriteArrayList() + + private fun getMaxSimultaneouslyStartingServices() = + Wrapper.instance.getThisWrapper().getMaxSimultaneouslyStartingServices() + + fun addToQueue(cloudService: ICloudService) { + Launcher.instance.consoleSender.sendProperty("wrapper.service.queued", cloudService.getName()) + val cloudServiceProcess = CloudServiceProcess(cloudService) + this.queue.add(cloudServiceProcess) + Wrapper.instance.cloudServiceProcessManager.registerServiceProcess(cloudServiceProcess) + Wrapper.instance.updateWrapperData() + } + + fun getStartingOrQueuedServiceAmount() = this.startingServices.size + this.queue.size + + fun startThread() { + thread(start = true, isDaemon = true) { + while (true) { + val startingServicesRemoved = startingServices.removeIf { cloudServiceProcess -> + cloudServiceProcess.getCloudService().getState() == ServiceState.VISIBLE || + cloudServiceProcess.getCloudService().getState() == ServiceState.INVISIBLE || + cloudServiceProcess.getCloudService().getState() == ServiceState.CLOSED + } + val canStartService = + queue.isNotEmpty() && startingServices.size < getMaxSimultaneouslyStartingServices() + if (canStartService) { + val cloudServiceProcess = queue.poll() + thread { cloudServiceProcess.start() } + startingServices.add(cloudServiceProcess) + } + if (startingServicesRemoved || canStartService) + Wrapper.instance.updateWrapperData() + Thread.sleep(200) + } + } + } + + fun removeFromQueue(cloudService: ICloudService) { + val cloudServiceProcess = this.cloudServiceProcessManager.getCloudServiceProcessByService(cloudService) + cloudServiceProcess?.let { + this.queue.remove(cloudServiceProcess) + this.cloudServiceProcessManager.unregisterServiceProcess(cloudServiceProcess) + } + Wrapper.instance.updateWrapperData() + } + + fun clearQueue() { + queue.forEach { Wrapper.instance.cloudServiceProcessManager.unregisterServiceProcess(it) } + queue.clear() + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/IServiceConfigurator.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/IServiceConfigurator.kt new file mode 100644 index 000000000..313358928 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/IServiceConfigurator.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.serviceconfigurator + +import eu.thesimplecloud.api.service.ICloudService +import java.io.File + +interface IServiceConfigurator { + + /** + * Edits all necessary files to start a service + */ + fun configureService(cloudService: ICloudService, serviceTmpDirectory: File) + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/ServiceConfiguratorManager.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/ServiceConfiguratorManager.kt new file mode 100644 index 000000000..448085f88 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/ServiceConfiguratorManager.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.serviceconfigurator + +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.configurators.DefaultBungeeConfigurator +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.configurators.DefaultServerConfigurator +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.configurators.DefaultVelocityConfigurator + +class ServiceConfiguratorManager { + + private val configurationMap = mapOf( + ServiceAPIType.VELOCITY to DefaultVelocityConfigurator(), + ServiceAPIType.BUNGEECORD to DefaultBungeeConfigurator(), + ServiceAPIType.SPIGOT to DefaultServerConfigurator() + ) + + /** + * Returns the [IServiceConfigurator] found by the specified [ServiceAPIType] + */ + fun getServiceConfigurator(serviceAPIType: ServiceAPIType): IServiceConfigurator? = configurationMap[serviceAPIType] + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultBungeeConfigurator.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultBungeeConfigurator.kt new file mode 100644 index 000000000..a95261899 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultBungeeConfigurator.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.serviceconfigurator.configurators + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.utils.ConfigurationFileEditor +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.IServiceConfigurator +import eu.thesimplecloud.launcher.utils.FileCopier +import java.io.File + +class DefaultBungeeConfigurator : IServiceConfigurator { + + override fun configureService(cloudService: ICloudService, serviceTmpDirectory: File) { + val bungeeConfigFile = File(serviceTmpDirectory, "config.yml") + if (!bungeeConfigFile.exists()) { + FileCopier.copyFileOutOfJar(bungeeConfigFile, "/files/config.yml") + } + val fileEditor = ConfigurationFileEditor(bungeeConfigFile, ConfigurationFileEditor.YAML_SPLITTER) + fileEditor.setValue("host", "0.0.0.0:${cloudService.getPort()}") + fileEditor.setValue("max_players", "${cloudService.getMaxPlayers()}") + fileEditor.saveToFile(bungeeConfigFile) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultServerConfigurator.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultServerConfigurator.kt new file mode 100644 index 000000000..fe3cdef1d --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultServerConfigurator.kt @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.serviceconfigurator.configurators + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.utils.ConfigurationFileEditor +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.IServiceConfigurator +import eu.thesimplecloud.launcher.utils.FileCopier +import java.io.File + +class DefaultServerConfigurator : IServiceConfigurator { + + override fun configureService(cloudService: ICloudService, serviceTmpDirectory: File) { + val propertiesFile = File(serviceTmpDirectory, "server.properties") + val bukkitFile = File(serviceTmpDirectory, "bukkit.yml") + val spigotFile = File(serviceTmpDirectory, "spigot.yml") + if (!propertiesFile.exists()) + FileCopier.copyFileOutOfJar(propertiesFile, "/files/server.properties") + if (!bukkitFile.exists()) + FileCopier.copyFileOutOfJar(bukkitFile, "/files/bukkit.yml") + if (!spigotFile.exists()) + FileCopier.copyFileOutOfJar(spigotFile, "/files/spigot.yml") + val fileEditor = ConfigurationFileEditor(propertiesFile, ConfigurationFileEditor.PROPERTIES_SPLITTER) + fileEditor.setValue("server-ip", cloudService.getHost()) + fileEditor.setValue("server-port", cloudService.getPort().toString()) + fileEditor.setValue("max-players", cloudService.getMaxPlayers().toString()) + fileEditor.saveToFile(propertiesFile) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultVelocityConfigurator.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultVelocityConfigurator.kt new file mode 100644 index 000000000..51608fef5 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/process/serviceconfigurator/configurators/DefaultVelocityConfigurator.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.process.serviceconfigurator.configurators + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.utils.ConfigurationFileEditor +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.IServiceConfigurator +import eu.thesimplecloud.launcher.utils.FileCopier +import java.io.File + +class DefaultVelocityConfigurator : IServiceConfigurator { + + override fun configureService(cloudService: ICloudService, serviceTmpDirectory: File) { + val configFile = File(serviceTmpDirectory, "velocity.toml") + if (!configFile.exists()) { + FileCopier.copyFileOutOfJar(configFile, "/files/velocity.toml") + } + val fileEditor = ConfigurationFileEditor(configFile, ConfigurationFileEditor.TOML_SPLITTER) + fileEditor.setValue("bind", "\"0.0.0.0:${cloudService.getPort()}\"") + fileEditor.setValue("show-max-players", "${cloudService.getMaxPlayers()}") + fileEditor.saveToFile(configFile) + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/ConnectionHandlerImpl.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/ConnectionHandlerImpl.kt new file mode 100644 index 000000000..8f569ab9c --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/ConnectionHandlerImpl.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.startup + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.handler.DefaultConnectionHandler +import eu.thesimplecloud.launcher.startup.Launcher + +class ConnectionHandlerImpl : DefaultConnectionHandler() { + override fun onConnectionActive(connection: IConnection) { + super.onConnectionActive(connection) + Launcher.instance.consoleSender.sendProperty("wrapper.connected") + } + + override fun onConnectionInactive(connection: IConnection) { + super.onConnectionInactive(connection) + if (connection === Wrapper.instance.communicationClient.getConnection()) { + Wrapper.instance.resetWrapperAndStartReconnectLoop(Launcher.instance.launcherConfig) + } + } + + override fun onFailure(connection: IConnection, ex: Throwable) { + Launcher.instance.logger.exception(ex) + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/CpuUsageUpdater.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/CpuUsageUpdater.kt new file mode 100644 index 000000000..b99235b58 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/CpuUsageUpdater.kt @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.startup + +import com.sun.management.OperatingSystemMXBean +import eu.thesimplecloud.launcher.startup.Launcher +import java.lang.management.ManagementFactory +import java.util.concurrent.ScheduledFuture +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 29.12.2020 + * Time: 11:07 + * @author Frederick Baier + */ +class CpuUsageUpdater { + + private var scheduleFuture: ScheduledFuture<*>? = null + + fun startUpdater() { + this.scheduleFuture = Launcher.instance.scheduler.scheduleAtFixedRate({ + if (Wrapper.instance.isWrapperNameSet()) { + val thisWrapper = Wrapper.instance.getThisWrapper() + val wrapperUpdater = thisWrapper.getUpdater() + val currentUsage = getCurrentCPUUsage() + if (thisWrapper.getCpuUsage() != currentUsage) { + wrapperUpdater.setCpuUsage(currentUsage) + Wrapper.instance.updateWrapperData() + } + } + }, 2, 2, TimeUnit.SECONDS) + } + + private fun getCurrentCPUUsage(): Float { + val osBean: OperatingSystemMXBean = ManagementFactory.getPlatformMXBean( + OperatingSystemMXBean::class.java + ) + return osBean.systemCpuLoad.toFloat() + } + + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/PortManager.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/PortManager.kt new file mode 100644 index 000000000..209ecde5f --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/PortManager.kt @@ -0,0 +1,82 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.startup + +import java.io.IOException +import java.net.Socket +import java.util.concurrent.ConcurrentHashMap + + +class PortManager { + + private val usedPorts = ConcurrentHashMap.newKeySet() + + private val blockedPorts = ConcurrentHashMap.newKeySet() + + + @Synchronized + fun getUnusedPort(startPort: Int): Int { + var port = startPort + while (isInUse(port) || isPortBlockedByOtherApp(port)) { + port++ + } + usedPorts.add(port) + + return port + } + + private fun isPortBlockedByOtherApp(port: Int): Boolean { + if (this.blockedPorts.contains(port)) { + return true + } + val isPortAvailable = isPortAvailable(port) + if (!isPortAvailable) { + addBlockedPort(port) + } + return !isPortAvailable + } + + private fun isInUse(port: Int): Boolean { + return this.usedPorts.contains(port) + } + + private fun isPortAvailable(port: Int): Boolean { + try { + Socket("127.0.0.1", port).use { return false } + } catch (ignored: IOException) { + return true + } + } + + fun setPortUnused(port: Int) { + this.usedPorts.remove(port) + } + + private fun addBlockedPort(port: Int) { + if (this.blockedPorts.size > 200) { + this.blockedPorts.clear() + } + this.blockedPorts.add(port) + } + +} \ No newline at end of file diff --git a/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/Wrapper.kt b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/Wrapper.kt new file mode 100644 index 000000000..868dee831 --- /dev/null +++ b/simplecloud-base/src/main/kotlin/eu/thesimplecloud/base/wrapper/startup/Wrapper.kt @@ -0,0 +1,234 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.base.wrapper.startup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.base.core.jvm.JvmArgumentsConfig +import eu.thesimplecloud.base.wrapper.impl.CloudAPIImpl +import eu.thesimplecloud.base.wrapper.logger.LoggerMessageListenerImpl +import eu.thesimplecloud.base.wrapper.network.packets.template.PacketOutGetTemplates +import eu.thesimplecloud.base.wrapper.process.CloudServiceProcessManager +import eu.thesimplecloud.base.wrapper.process.filehandler.ServiceVersionJarLoader +import eu.thesimplecloud.base.wrapper.process.queue.CloudServiceProcessQueue +import eu.thesimplecloud.base.wrapper.process.serviceconfigurator.ServiceConfiguratorManager +import eu.thesimplecloud.client.packets.PacketOutCloudClientLogin +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.client.NettyClient +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.IPacket +import eu.thesimplecloud.launcher.application.ApplicationClassLoader +import eu.thesimplecloud.launcher.application.ICloudApplication +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.handler.ModuleHandler +import eu.thesimplecloud.launcher.language.LanguageFileLoader +import eu.thesimplecloud.launcher.startup.Launcher +import org.apache.commons.io.FileUtils +import java.io.File +import java.util.concurrent.TimeUnit +import kotlin.concurrent.thread + +class Wrapper : ICloudApplication { + + companion object { + @JvmStatic + lateinit var instance: Wrapper + private set + } + + lateinit var jvmArgumentsConfig: JvmArgumentsConfig + + @Volatile + var thisWrapperName: String? = null + var processQueue: CloudServiceProcessQueue? = null + val serviceConfigurationManager = ServiceConfiguratorManager() + val cloudServiceProcessManager = CloudServiceProcessManager() + val portManager = PortManager() + val communicationClient: INettyClient + val connectionToManager: IConnection + var templateClient: INettyClient? = null + private set + val serviceVersionLoader = ServiceVersionJarLoader() + var existingModules: List = ArrayList() + private set + val appClassLoader: ApplicationClassLoader + + init { + instance = this + this.appClassLoader = this::class.java.classLoader as ApplicationClassLoader + Launcher.instance.logger.addLoggerMessageListener(LoggerMessageListenerImpl()) + val launcherConfig = Launcher.instance.launcherConfig + this.communicationClient = NettyClient(launcherConfig.host, launcherConfig.port, ConnectionHandlerImpl()) + this.connectionToManager = this.communicationClient.getConnection() + this.communicationClient.setPacketSearchClassLoader(Launcher.instance.getNewClassLoaderWithLauncherAndBase()) + this.communicationClient.setClassLoaderToSearchObjectPacketClasses(appClassLoader) + this.communicationClient.setPacketClassConverter { moveToApplicationClassLoader(it) } + CloudAPIImpl() + LanguageFileLoader().loadFile(Launcher.instance.launcherConfig) + this.communicationClient.addPacketsByPackage("eu.thesimplecloud.client.packets") + this.communicationClient.addPacketsByPackage("eu.thesimplecloud.base.wrapper.network.packets") + this.communicationClient.addPacketsByPackage("eu.thesimplecloud.api.network.packets") + thread(start = true, isDaemon = true) { + resetWrapperAndStartReconnectLoop(launcherConfig) + } + if (isStartedInManagerDirectory()) { + Launcher.instance.consoleSender.sendProperty("wrapper.startup.template-client.not-activated") + Launcher.instance.consoleSender.sendProperty("wrapper.startup.template-client.help-message") + this.templateClient = null + } else { + Launcher.instance.consoleSender.sendProperty("wrapper.startup.template-client.using") + } + CpuUsageUpdater().startUpdater() + + //shutdown hook + Runtime.getRuntime().addShutdownHook(Thread { + if (this.connectionToManager.isOpen()) { + val wrapperInfo = getThisWrapper() + //set authenticated to false to prevent service starting + wrapperInfo.setAuthenticated(false) + CloudAPI.instance.getWrapperManager().update(wrapperInfo) + } + this.processQueue?.clearQueue() + stopAllRunningServicesAndWaitFor() + Thread.sleep(300) + if (this.templateClient != null) { + try { + FileUtils.deleteDirectory(File(DirectoryPaths.paths.modulesPath)) + } catch (e: Exception) { + + } + } + FileUtils.deleteDirectory(File(DirectoryPaths.paths.tempPath)) + this.communicationClient.shutdown() + this.templateClient?.shutdown() + }) + } + + private fun moveToApplicationClassLoader(clazz: Class): Class { + if (appClassLoader.isThisClassLoader(clazz)) return clazz + val loadedClass = appClassLoader.loadClass(clazz.name) + appClassLoader.setCachedClass(loadedClass) + return loadedClass as Class + } + + private fun stopAllRunningServicesAndWaitFor() { + this.cloudServiceProcessManager.stopAllServices() + while (this.cloudServiceProcessManager.getAllProcesses().isNotEmpty()) { + Thread.sleep(100) + } + } + + /** + * Starts this client. This method will return when the client is fully connected to the manager. + */ + fun resetWrapperAndStartReconnectLoop(launcherConfig: LauncherConfig) { + //reset wrapper + this.stopAllRunningServicesAndWaitFor() + this.communicationClient.shutdown().awaitUninterruptibly() + this.templateClient?.shutdown()?.awaitUninterruptibly() + this.existingModules = ArrayList() + this.thisWrapperName = null + this.processQueue = null + + while (!this.communicationClient.start().awaitUninterruptibly().isSuccess) { + Launcher.instance.consoleSender.sendProperty("wrapper.connection-failed") + try { + Thread.sleep(5000) + } catch (e: InterruptedException) { + } + } + this.connectionToManager.sendUnitQuery(PacketOutCloudClientLogin(NetworkComponentType.WRAPPER), 10000) + .syncUninterruptibly() + + if (!isStartedInManagerDirectory()) { + val templateClient = NettyClient(launcherConfig.host, launcherConfig.port + 1, ConnectionHandlerImpl()) + this.templateClient = templateClient + templateClient.setPacketSearchClassLoader(Launcher.instance.getNewClassLoaderWithLauncherAndBase()) + templateClient.setClassLoaderToSearchObjectPacketClasses(appClassLoader) + Launcher.instance.scheduler.schedule({ startTemplateClient(templateClient) }, 100, TimeUnit.MILLISECONDS) + } else { + reloadExistingModules() + } + + } + + private fun startTemplateClient(templateClient: NettyClient) { + templateClient.addPacketsByPackage("eu.thesimplecloud.base.wrapper.network.packets.template") + thread(start = true, isDaemon = false) { + templateClient.start().then { + Launcher.instance.consoleSender.sendProperty("wrapper.template.requesting") + templateClient.getConnection().sendUnitQuery(PacketOutGetTemplates(), TimeUnit.MINUTES.toMillis(15)) + .thenDelayed(3, TimeUnit.SECONDS) { + reloadExistingModules() + val wrapperUpdater = getThisWrapper().getUpdater() + wrapperUpdater.setTemplatesReceived(true) + wrapperUpdater.update() + Launcher.instance.consoleSender.sendProperty("wrapper.template.received") + }.addFailureListener { + Launcher.instance.logger.severe("An error occurred while requesting templates:") + Launcher.instance.logger.exception(it) + } + } + } + } + + @Synchronized + fun reloadExistingModules() { + this.existingModules = ModuleHandler().getAllCloudModuleFileContents() + } + + fun isWrapperNameSet(): Boolean = thisWrapperName != null + + fun getThisWrapper(): IWrapperInfo = CloudAPI.instance.getWrapperManager().getWrapperByName(this.thisWrapperName!!) + ?: throw IllegalStateException("Unable to find self wrapper.") + + /** + * Updates the memory the wrapper currently uses according to the registered service processes. + */ + fun updateWrapperData() { + val usedMemory = this.cloudServiceProcessManager.getAllProcesses().sumBy { it.getCloudService().getMaxMemory() } + val thisWrapper = this.getThisWrapper() + val wrapperUpdater = thisWrapper.getUpdater() + wrapperUpdater.setUsedMemory(usedMemory) + wrapperUpdater.setCurrentlyStartingServices(this.processQueue?.getStartingOrQueuedServiceAmount() ?: 0) + if (this.connectionToManager.isOpen()) + wrapperUpdater.update().awaitUninterruptibly() + } + + override fun onEnable() { + } + + override fun onDisable() { + } + + fun isStartedInManagerDirectory(): Boolean = File("storage/wrappers/").exists() + + fun startProcessQueue() { + check(processQueue == null) { "Cannot start process queue when it is already running" } + this.processQueue = CloudServiceProcessQueue() + this.processQueue?.startThread() + } +} \ No newline at end of file diff --git a/simplecloud-base/src/main/resources/files/bukkit.yml b/simplecloud-base/src/main/resources/files/bukkit.yml new file mode 100644 index 000000000..2625de7a7 --- /dev/null +++ b/simplecloud-base/src/main/resources/files/bukkit.yml @@ -0,0 +1,43 @@ +# This is the main configuration file for Bukkit. +# As you can see, there's actually not that much to configure without any plugins. +# For a reference for any variable inside this file, check out the Bukkit Wiki at +# http://wiki.bukkit.org/Bukkit.yml +# +# If you need help on this file, feel free to join us on irc or leave a message +# on the forums asking for advice. +# +# IRC: #spigot @ irc.spi.gt +# (If this means nothing to you, just go to http://www.spigotmc.org/pages/irc/ ) +# Forums: http://www.spigotmc.org/ +# Bug tracker: http://www.spigotmc.org/go/bugs + + +settings: + allow-end: false + warn-on-overload: true + permissions-file: permissions.yml + update-folder: update + plugin-profiling: false + connection-throttle: 0 + query-plugins: true + deprecated-verbose: default + shutdown-message: Cloud-Server closed +spawn-limits: + monsters: 70 + animals: 15 + water-animals: 5 + ambient: 15 +chunk-gc: + period-in-ticks: 600 + load-threshold: 0 +ticks-per: + animal-spawns: 400 + monster-spawns: 1 + autosave: 6000 +aliases: now-in-command.yml +database: + username: bukkit + isolation: SERIALIZABLE + driver: org.sqlite.JDBC + password: walrus + url: jdbc:sqlite:{DIR}{NAME}.db diff --git a/simplecloud-base/src/main/resources/files/config.yml b/simplecloud-base/src/main/resources/files/config.yml new file mode 100644 index 000000000..89ce7f0ba --- /dev/null +++ b/simplecloud-base/src/main/resources/files/config.yml @@ -0,0 +1,50 @@ +server_connect_timeout: 5000 +remote_ping_cache: -1 +forge_support: false +player_limit: -1 +permissions: + default: + - bungeecord.command.server + - bungeecord.command.list + admin: + - bungeecord.command.alert + - bungeecord.command.end + - bungeecord.command.ip + - bungeecord.command.reload +timeout: 30000 +log_commands: false +network_compression_threshold: 256 +online_mode: true +disabled_commands: + - disabledcommandhere +servers: + lobby: + motd: '&1Just another BungeeCord - Forced Host' + address: localhost:25565 + restricted: false +listeners: + - query_port: 25577 + motd: '&1Another Bungee server' + tab_list: GLOBAL_PING + query_enabled: false + proxy_protocol: false + forced_hosts: + pvp.md-5.net: pvp + ping_passthrough: false + priorities: + - lobby + bind_local_address: true + host: 0.0.0.0:25565 + max_players: 1 + tab_size: 60 + force_default_server: false +ip_forward: true +remote_ping_timeout: 5000 +prevent_proxy_connections: false +groups: + md_5: + - admin +connection_throttle: -1 +stats: a83781af-9bc4-48a0-b5d1-66367af0966b +connection_throttle_limit: 3 +log_pings: true diff --git a/simplecloud-base/src/main/resources/files/server-icon.png b/simplecloud-base/src/main/resources/files/server-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..203fab3c1323798902a586a0baaedf74a8adec5d GIT binary patch literal 2073 zcmV+!2RP)EestUIvqvoN2gLN zLm4|A>sS~%HGmT>anh+J6jNdg)C43UMW}ovAt4EYOGt9xx4ZXt_AZx8F1Hs5iT}92 z%sZER_WgK%zvtQK*=%6Kgb5QSOqeiX!h{JECQO(xVZy{03*_@+%NVn1VfN6KUjL&4 z<>uKWi<2=hLO_Cw=Jy5Fvvyf{Ul!@xgpiA$mtW&90AozP>IuFmTKM$`>RPz6f1R-& z{>x8y$A6$I_ z)HQYCVz=LraBM`cMQyT3QMvK%K*7!Fr8#zK&3O1aW&$wAM1M$K;}2=iYGF3<@aapq zaK#fjBF`zKXj%@uK^5CSJc}JwXW>`E!w3%<`W3<<&1%8%R~GpvIHVuSB7JA9{EcBu z1YnFU=<|ij51#DE`1M~-NXO2(lBW8c{7h_EIs*#|vhma(kK&`#SK@Q}2@ey3aF{j8 zj_QpI-02dXLI~*@6XyNkZ*&8XUs>r1DDOV<+iK^l<^QGaJpq8H0MADT;bMd0QlEnN zKWRsOOE2DDcPHE-hWZwF^m_k%eQkVAbX@jon3`)Nx8_*+-)#O>)mV|&aYGrPsM`Hk zy`l2Eeo<*X*Xc>PzqzC-9s52dTSnD$3-R-^)2KM!nKWafYofON92rM9epT}XwHiI? z5?t|7o;2m8Sq=iIyq+w%E&&*0_MoDzy6O!*E(>(3VBs=4djn{=(1VI&ZP;_91tE=% zn9?zk3MZvw--aUGxw!`Iy`dq5lNHB9KbwtR$6Ppd$=`nlBJ*qlkI7B}iwo?&#Rcg^ z)!2>r+*6~ zIMJDuaIy$*dLSRS=E!)e^fSY55F0NqnFM!`VcWsv8KeJXrBS^6tz6~d*^aJsk^4F! zi;`yc1@afY@BUunnxS^skB9yefx%pY~wM ztnBE1e0;y?8ai-}%g2zN7T*&?_8W8#Z^7=90c<_uc69l|yHoK?DF9?gbcaKhoAPU0>#|B~o@)U=fd?@~seHh`ybG#Y{o5&|69QPq^ zd%f1rc@$R67`tm!0(gSz`dvrbgy!y0LPX+(_g$9-4DgQo=(cY(aCc zhRK;?N?~TnLCw}W(a1-P^DR`QCzrh0jqXn?=xYvjyO(lT-UCXag0g;eJ6$JX=~h{ zjrx7N7szu6(R3Z58?Q{bn4c3$N|+8Rf(8-Ze?Exs&P+EHaIk&P|5Oy^QOubr4HGu; zoEJX^o+#uoKW{kUMEv*;__8GI7?l7vfqP^5%#1)`UfMMgPK@x5`XE-#u_4plsxl;RwoqC3Rnr`5pr#Xz3T*#Bkuz;q{EJi*>k2|x((Sa`Co;>jt2 zT)ULC{UIR*;}NFl@Nszaco5r{IzTO!Bq=>K!hdbzaHIp+dA|Tkq_@05tYS36*>qcx@rP0*~)WlvJh+ z^0f${BdCTS45-+Cv|X|7J{gefJ5{)RKzL9u)_->^iNpv*%Hh55SkUeP)>efRTH3e literal 0 HcmV?d00001 diff --git a/simplecloud-base/src/main/resources/files/server.properties b/simplecloud-base/src/main/resources/files/server.properties new file mode 100644 index 000000000..24ade3ec4 --- /dev/null +++ b/simplecloud-base/src/main/resources/files/server.properties @@ -0,0 +1,58 @@ +# +# MIT License +# +# Copyright (C) 2020-2022 The SimpleCloud authors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +# documentation files (the "Software"), to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +#Minecraft server properties +#Tue Aug 22 15:33:36 CEST 2017 +generator-settings= +op-permission-level=4 +allow-nether=false +resource-pack-hash= +level-name=world +enable-query=false +allow-flight=false +announce-player-achievements=false +server-port=25565 +max-world-size=29999984 +level-type=DEFAULT +enable-rcon=false +level-seed= +force-gamemode=false +server-ip=127.0.0.1 +network-compression-threshold=256 +max-build-height=256 +spawn-npcs=false +white-list=false +spawn-animals=true +hardcore=false +snooper-enabled=true +online-mode=false +resource-pack= +pvp=true +difficulty=1 +enable-command-block=false +gamemode=0 +player-idle-timeout=0 +max-players=20 +spawn-monsters=true +generate-structures=true +view-distance=8 +spawn-protection=0 +motd=Cloud-Service diff --git a/simplecloud-base/src/main/resources/files/spigot.yml b/simplecloud-base/src/main/resources/files/spigot.yml new file mode 100644 index 000000000..ac6e47490 --- /dev/null +++ b/simplecloud-base/src/main/resources/files/spigot.yml @@ -0,0 +1,133 @@ +# This is the main configuration file for Spigot. +# As you can see, there's tons to configure. Some options may impact gameplay, so use +# with caution, and make sure you know what each option does before configuring. +# For a reference for any variable inside this file, check out the Spigot wiki at +# http://www.spigotmc.org/wiki/spigot-configuration/ +# +# If you need help with the configuration or have any questions related to Spigot, +# join us at the IRC or drop by our forums and leave a post. +# +# IRC: #spigot @ irc.spi.gt ( http://www.spigotmc.org/pages/irc/ ) +# Forums: http://www.spigotmc.org/ + +config-version: 8 +settings: + debug: false + save-user-cache-on-stop-only: false + moved-wrongly-threshold: 0.0625 + moved-too-quickly-threshold: 100.0 + filter-creative-items: true + late-bind: false + attribute: + maxHealth: + max: 2048.0 + movementSpeed: + max: 2048.0 + attackDamage: + max: 2048.0 + user-cache-size: 0 + bungeecord: true + sample-count: 12 + int-cache-limit: 1024 + player-shuffle: 0 + timeout-time: 60 + restart-on-crash: true + restart-script: ./start.sh + netty-threads: 4 +commands: + tab-complete: 0 + silent-commandblock-console: false + log: true + spam-exclusions: + - /skill + replace-commands: + - setblock + - summon + - testforblock + - tellraw +messages: + whitelist: You are not whitelisted on this server! + unknown-command: Unknown command. Type "/help" for help. + server-full: The server is full! + outdated-client: Outdated client! Please use {0} + outdated-server: Outdated server! I'm still on {0} + restart: Server is restarting +stats: + disable-saving: false + forced-stats: { } +world-settings: + default: + verbose: true + item-despawn-rate: 6000 + merge-radius: + item: 2.5 + exp: 3.0 + arrow-despawn-rate: 1200 + enable-zombie-pigmen-portal-spawns: true + wither-spawn-sound-radius: 0 + chunks-per-tick: 650 + clear-tick-list: false + hanging-tick-frequency: 100 + mob-spawn-range: 4 + nerf-spawner-mobs: false + growth: + cactus-modifier: 100 + cane-modifier: 100 + melon-modifier: 100 + mushroom-modifier: 100 + pumpkin-modifier: 100 + sapling-modifier: 100 + wheat-modifier: 100 + netherwart-modifier: 100 + entity-activation-range: + animals: 32 + monsters: 32 + misc: 16 + entity-tracking-range: + players: 48 + animals: 48 + monsters: 48 + misc: 32 + other: 64 + anti-xray: + enabled: true + engine-mode: 1 + hide-blocks: + - 14 + - 15 + - 16 + - 21 + - 48 + - 49 + - 54 + - 56 + - 73 + - 74 + - 82 + - 129 + - 130 + replace-blocks: + - 1 + - 5 + save-structure-info: true + max-tnt-per-tick: 100 + ticks-per: + hopper-transfer: 8 + hopper-check: 8 + hopper-amount: 1 + random-light-updates: false + hunger: + walk-exhaustion: 0.2 + sprint-exhaustion: 0.8 + combat-exhaustion: 0.3 + regen-exhaustion: 3.0 + max-tick-time: + tile: 50 + entity: 50 + max-bulk-chunks: 10 + zombie-aggressive-towards-villager: true + view-distance: 8 + dragon-death-sound-radius: 0 + seed-village: 10387312 + seed-feature: 14357617 + max-entity-collisions: 8 diff --git a/simplecloud-base/src/main/resources/files/velocity.toml b/simplecloud-base/src/main/resources/files/velocity.toml new file mode 100644 index 000000000..ee9fc453f --- /dev/null +++ b/simplecloud-base/src/main/resources/files/velocity.toml @@ -0,0 +1,95 @@ +# Config version. Do not change this +config-version = "1.0" + +# What port should the proxy be bound to? By default, we'll bind to all addresses on port 25577. +bind = "0.0.0.0:25577" + +# What should be the MOTD? This gets displayed when the player adds your server to +# their server list. Legacy color codes and JSON are accepted. +motd = "&3A Velocity Server" + +# What should we display for the maximum number of players? (Velocity does not support a cap +# on the number of players online.) +show-max-players = 500 + +# Should we authenticate players with Mojang? By default, this is on. +online-mode = true + +# Should we forward IP addresses and other data to backend servers? +# Available options: +# - "none": No forwarding will be done. All players will appear to be connecting from the +# proxy and will have offline-mode UUIDs. +# - "legacy": Forward player IPs and UUIDs in a BungeeCord-compatible format. Use this if +# you run servers using Minecraft 1.12 or lower. +# - "modern": Forward player IPs and UUIDs as part of the login process using Velocity's +# native forwarding. Only applicable for Minecraft 1.13 or higher. +player-info-forwarding-mode = "LEGACY" + +# If you are using modern IP forwarding, configure an unique secret here. +forwarding-secret = "CmlJNM3GzwNx" + +# Announce whether or not your server supports Forge. If you run a modded server, we +# suggest turning this on. +announce-forge = false + +[servers] +# Configure your servers here. Each key represents the server's name, and the value +# represents the IP address of the server to connect to. +fallback = "127.0.0.1:0" + +# In what order we should try servers when a player logs in or is kicked from aserver. +try = [ + "fallback" +] + +[forced-hosts] +# Configure your forced hosts here. + +[advanced] +# How large a Minecraft packet has to be before we compress it. Setting this to zero will +# compress all packets, and setting it to -1 will disable compression entirely. +compression-threshold = 256 + +# How much compression should be done (from 0-9). The default is -1, which uses the +# default level of 6. +compression-level = -1 + +# How fast (in milliseconds) are clients allowed to connect after the last connection? By +# default, this is three seconds. Disable this by setting this to 0. +login-ratelimit = 3000 + +# Specify a custom timeout for connection timeouts here. The default is five seconds. +connection-timeout = 5000 + +# Specify a read timeout for connections here. The default is 30 seconds. +read-timeout = 30000 + +# Enables compatibility with HAProxy. +proxy-protocol = false + +[query] +# Whether to enable responding to GameSpy 4 query responses or not. +enabled = false + +# If query is enabled, on what port should the query protocol listen on? +port = 25577 + +# This is the map name that is reported to the query services. +map = "Velocity" + +# Whether plugins should be shown in query response by default or not +show-plugins = false + +[metrics] +# Whether metrics will be reported to bStats (https://bstats.org). +# bStats collects some basic information, like how many people use Velocity and their +# player count. We recommend keeping bStats enabled, but if you're not comfortable with +# this, you can turn this setting off. There is no performance penalty associated with +# having metrics enabled, and data sent to bStats can't identify your server. +enabled = true + +# A unique, anonymous ID to identify this proxy with. +id = "0a79a7d9-5700-4984-b4eb-d2fd2d8af2a6" + +log-failure = false + diff --git a/simplecloud-base/src/main/resources/manager.json b/simplecloud-base/src/main/resources/manager.json new file mode 100644 index 000000000..ea1860778 --- /dev/null +++ b/simplecloud-base/src/main/resources/manager.json @@ -0,0 +1,19 @@ +{ + "name": "Manager", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.base.manager.startup.Manager", + "moduleCopyType": "NONE", + "repositories": [ + "https://repo.thesimplecloud.eu/artifactory/gradle-dev/", + "https://repo.maven.apache.org/maven2/" + ], + "dependencies": [ + { + "groupId": "org.jetbrains.kotlinx", + "artifactId": "kotlinx-coroutines-core", + "version": "1.4.3" + } + ], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-base/src/main/resources/wrapper.json b/simplecloud-base/src/main/resources/wrapper.json new file mode 100644 index 000000000..e24e176aa --- /dev/null +++ b/simplecloud-base/src/main/resources/wrapper.json @@ -0,0 +1,19 @@ +{ + "name": "Wrapper", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.base.wrapper.startup.Wrapper", + "moduleCopyType": "NONE", + "repositories": [ + "https://repo.thesimplecloud.eu/artifactory/gradle-dev/", + "https://repo.maven.apache.org/maven2/" + ], + "dependencies": [ + { + "groupId": "org.jetbrains.kotlinx", + "artifactId": "kotlinx-coroutines-core", + "version": "1.4.3" + } + ], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-client/build.gradle b/simplecloud-client/build.gradle new file mode 100644 index 000000000..fe6e13164 --- /dev/null +++ b/simplecloud-client/build.gradle @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +dependencies { + compileOnly project(":simplecloud-api") +} + +jar { + dependsOn ':simplecloud-api:jar' +} diff --git a/simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutCloudClientLogin.kt b/simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutCloudClientLogin.kt new file mode 100644 index 000000000..b1f93cacf --- /dev/null +++ b/simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutCloudClientLogin.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.client.packets + +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket + +class PacketOutCloudClientLogin() : JsonPacket() { + + constructor(cloudClientType: NetworkComponentType, name: String) : this() { + this.jsonLib.append("name", name).append("cloudClientType", cloudClientType) + } + + constructor(cloudClientType: NetworkComponentType) : this() { + this.jsonLib.append("cloudClientType", cloudClientType) + } + + override suspend fun handle(connection: IConnection) = unit() + + +} \ No newline at end of file diff --git a/simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutScreenMessage.kt b/simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutScreenMessage.kt new file mode 100644 index 000000000..2722e56cb --- /dev/null +++ b/simplecloud-client/src/main/kotlin/eu/thesimplecloud/client/packets/PacketOutScreenMessage.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.client.packets + +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket + +class PacketOutScreenMessage( + cloudClientType: NetworkComponentType, + commandExecutable: ICommandExecutable, + message: String +) : JsonPacket() { + + init { + this.jsonLib.append("cloudClientType", cloudClientType).append("name", commandExecutable.getName()) + .append("message", message) + } + + override suspend fun handle(connection: IConnection) = unit() + +} \ No newline at end of file diff --git a/simplecloud-dependency-loader/build.gradle b/simplecloud-dependency-loader/build.gradle new file mode 100644 index 000000000..3184183f5 --- /dev/null +++ b/simplecloud-dependency-loader/build.gradle @@ -0,0 +1,23 @@ +dependencies { + api "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + compileOnly 'org.eclipse.aether:aether-impl:1.1.0' + compileOnly 'org.eclipse.aether:aether-connector-basic:1.1.0' + compileOnly 'org.eclipse.aether:aether-transport-file:1.1.0' + compileOnly 'org.eclipse.aether:aether-transport-http:1.1.0' + compileOnly 'org.apache.maven:maven-aether-provider:3.3.9' + compileOnly(project(":simplecloud-runner")) + compileOnly(project(":simplecloud-api")) +} + +shadowJar { + archiveFileName.set("dependency-loader.jar") +} + +jar { + manifest { + attributes( + 'Main-Class': 'eu.thesimplecloud.loader.dependency.DependencyLoaderMainKt', + 'Implementation-Version': project.version, + ) + } +} diff --git a/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/AdvancedDependencyDownloader.kt b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/AdvancedDependencyDownloader.kt new file mode 100644 index 000000000..f56f80565 --- /dev/null +++ b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/AdvancedDependencyDownloader.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.loader.dependency + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import eu.thesimplecloud.runner.dependency.CloudDependency +import eu.thesimplecloud.runner.dependency.SimpleDependencyDownloader +import org.eclipse.aether.artifact.DefaultArtifact +import java.io.IOException + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 11.06.2021 + * Time: 21:18 + */ +class AdvancedDependencyDownloader(repositories: List) : SimpleDependencyDownloader(repositories) { + + fun downloadFiles(dependency: AdvancedCloudDependency) { + if (dependency.getDownloadedFile().exists()) return + this.repositories.forEach { repoUrl -> + try { + downloadAnyways(dependency, repoUrl) + return + } catch (e: Exception) { + //ignore because the repository was wrong and another repository will be correct + } + } + + throw IllegalArgumentException("No valid repository was found for ${dependency.getName()} repos: $repositories") + } + + @Throws(IOException::class) + private fun downloadAnyways(dependency: AdvancedCloudDependency, repoUrl: String) { + dependency.download(repoUrl) + resolveDependenciesAndSaveToInfoFile(dependency, repoUrl) + } + + private fun resolveDependenciesAndSaveToInfoFile(dependency: AdvancedCloudDependency, repoUrl: String) { + val aetherArtifact = DefaultArtifact("${dependency.groupId}:${dependency.artifactId}:${dependency.version}") + val dependencies = DependencyResolver(repoUrl, aetherArtifact).collectDependencies() + val cloudDependencies = dependencies.map { it.artifact } + .map { CloudDependency(it.groupId, it.artifactId, it.version) } + JsonLib.fromObject(cloudDependencies).saveAsFile(dependency.getDownloadedInfoFile()) + } + +} \ No newline at end of file diff --git a/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoader.kt b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoader.kt new file mode 100644 index 000000000..0d2a537fc --- /dev/null +++ b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoader.kt @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.loader.dependency + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import java.io.File +import java.util.concurrent.CopyOnWriteArraySet + +/** + * Created by IntelliJ IDEA. + * Date: 04.09.2020 + * Time: 17:49 + * @author Frederick Baier + */ +class DependencyLoader { + + companion object { + val INSTANCE = DependencyLoader() + } + + private val resolvedDependencies = CopyOnWriteArraySet() + private val installedDependencies = CopyOnWriteArraySet() + private var loggerEnabled: Boolean = true + + fun disableLogger() { + this.loggerEnabled = false + } + + fun reset() { + resolvedDependencies.clear() + } + + fun loadDependencies(repositories: List, dependencies: List): Set { + if (dependencies.isEmpty()) return emptySet() + val dependenciesString = dependencies.joinToString { it.getName() } + loggerMessage("Loading dependencies: $dependenciesString") + + val allDependencies = dependencies.map { collectSubDependencies(it, repositories) }.flatten() + val dependenciesByArtifactId = allDependencies.groupBy { it.artifactId }.values + val newestVersions = dependenciesByArtifactId.map { + it.reduce { acc, dependency -> dependency.getDependencyWithNewerVersion(acc) } + } + val dependencyFiles = newestVersions.map { it.getDownloadedFile() } + + val installedDependenciesString = newestVersions.joinToString { it.getName() } + loggerMessage("Installed dependencies: $installedDependenciesString") + + installedDependencies.addAll(newestVersions) + + return dependencyFiles.toSet() + } + + private fun collectSubDependencies( + dependency: AdvancedCloudDependency, + repositories: List, + list: MutableList = ArrayList() + ): List { + if (this.resolvedDependencies.contains(dependency)) return list + this.resolvedDependencies.add(dependency) + list.add(dependency) + resolveDependencyFilesIfNotExist(dependency, repositories) + loggerMessage("Loading dependency ${dependency.getName()}") + val subDependencies = getSubDependenciesOfDependency(dependency) + subDependencies.forEach { collectSubDependencies(it, repositories, list) } + return list + } + + private fun resolveDependencyFilesIfNotExist(dependency: AdvancedCloudDependency, repositories: List) { + if (!dependency.getDownloadedInfoFile().exists()) { + AdvancedDependencyDownloader(repositories).downloadFiles(dependency) + } + } + + private fun getSubDependenciesOfDependency(dependency: AdvancedCloudDependency): List { + val infoFile = dependency.getDownloadedInfoFile() + val subDependencies = JsonLib.fromJsonFile(infoFile)!! + .getObject(Array::class.java) + return subDependencies.asList() + } + + private fun loggerMessage(message: String) { + if (loggerEnabled) { + println(message) + } + } + + fun getInstalledDependencies(): Collection { + return this.installedDependencies + } + +} \ No newline at end of file diff --git a/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoaderMain.kt b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoaderMain.kt new file mode 100644 index 000000000..d23c31cec --- /dev/null +++ b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyLoaderMain.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.loader.dependency + +import java.io.File +import java.net.URLClassLoader + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 11.06.2021 + * Time: 20:17 + */ + +private val copiedLauncherFile = File("launcher.jar") + +fun main(args: Array) { + val loadedDependencyFiles = LauncherDependencyLoader().loadLauncherDependencies() + val loadedDependencyURLs = loadedDependencyFiles.map { it.toURI().toURL() }.toTypedArray() + + val currentContextClassLoader = Thread.currentThread().contextClassLoader + val classLoader = URLClassLoader(arrayOf(copiedLauncherFile.toURI().toURL(), *loadedDependencyURLs), currentContextClassLoader) + + Thread.currentThread().contextClassLoader = classLoader + + executeLauncherMain(classLoader, args) +} + +private fun executeLauncherMain(classLoader: URLClassLoader, args: Array) { + val loadedClass = classLoader.loadClass("eu.thesimplecloud.launcher.startup.LauncherMainKt") + val method = loadedClass.getMethod("main", Array::class.java) + method.invoke(null, args) +} diff --git a/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyResolver.kt b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyResolver.kt new file mode 100644 index 000000000..d42feef52 --- /dev/null +++ b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/DependencyResolver.kt @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.loader.dependency + +import org.apache.maven.repository.internal.MavenRepositorySystemUtils +import org.eclipse.aether.DefaultRepositorySystemSession +import org.eclipse.aether.RepositorySystem +import org.eclipse.aether.RepositorySystemSession +import org.eclipse.aether.artifact.DefaultArtifact +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory +import org.eclipse.aether.graph.Dependency +import org.eclipse.aether.impl.DefaultServiceLocator +import org.eclipse.aether.repository.LocalRepository +import org.eclipse.aether.repository.RemoteRepository +import org.eclipse.aether.resolution.ArtifactDescriptorRequest +import org.eclipse.aether.resolution.VersionRangeRequest +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory +import org.eclipse.aether.spi.connector.transport.TransporterFactory +import org.eclipse.aether.transport.file.FileTransporterFactory +import org.eclipse.aether.transport.http.HttpTransporterFactory +import java.io.File +import java.util.* + +/** + * Created by IntelliJ IDEA. + * Date: 16.07.2020 + * Time: 16:22 + * @author Frederick Baier + */ +class DependencyResolver(repositoryURL: String, private val dependency: DefaultArtifact) { + + private val locator: DefaultServiceLocator = MavenRepositorySystemUtils.newServiceLocator() + private val system: RepositorySystem = newRepositorySystem(locator) + private val session: RepositorySystemSession = newSession(system) + + private val repository = RemoteRepository.Builder(UUID.randomUUID().toString(), "default", repositoryURL).build() + + fun collectDependencies(): List { + return collectDependencies(dependency).filter { !it.isOptional }.filter { it.scope == "compile" } + } + + fun determineLatestVersion(): String { + val request = VersionRangeRequest(dependency, listOf(repository), null) + return system.resolveVersionRange(session, request).highestVersion.toString() + } + + private fun collectDependencies(artifact: DefaultArtifact): MutableList { + val request = ArtifactDescriptorRequest() + request.artifact = artifact + request.repositories = listOf(repository) + return system.readArtifactDescriptor(session, request).dependencies + } + + private fun newRepositorySystem(locator: DefaultServiceLocator): RepositorySystem { + locator.addService(RepositoryConnectorFactory::class.java, BasicRepositoryConnectorFactory::class.java) + locator.addService(TransporterFactory::class.java, FileTransporterFactory::class.java) + locator.addService(TransporterFactory::class.java, HttpTransporterFactory::class.java) + return locator.getService(RepositorySystem::class.java) + } + + private fun newSession(system: RepositorySystem): RepositorySystemSession { + val session: DefaultRepositorySystemSession = MavenRepositorySystemUtils.newSession() + val localRepo = LocalRepository(File("dependencies/repo/")) + session.localRepositoryManager = system.newLocalRepositoryManager(session, localRepo) + return session + } + +} \ No newline at end of file diff --git a/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/LauncherDependencyLoader.kt b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/LauncherDependencyLoader.kt new file mode 100644 index 000000000..93572736e --- /dev/null +++ b/simplecloud-dependency-loader/src/main/kotlin/eu/thesimplecloud/loader/dependency/LauncherDependencyLoader.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.loader.dependency + +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import java.io.File + + +class LauncherDependencyLoader { + + fun loadLauncherDependencies(): Set { + val dependencyLoader = DependencyLoader.INSTANCE + return dependencyLoader.loadDependencies( + listOf( + "https://repo.maven.apache.org/maven2/", + "https://repo.thesimplecloud.eu/artifactory/gradle-release-local/" + ), + listOf( + AdvancedCloudDependency("eu.thesimplecloud.clientserverapi", "clientserverapi", "4.1.17"), + AdvancedCloudDependency("org.apache.commons", "commons-lang3", "3.12.0"), + AdvancedCloudDependency("org.slf4j", "slf4j-nop", "1.7.32"), + AdvancedCloudDependency("org.fusesource.jansi", "jansi", "2.4.0"), + AdvancedCloudDependency("org.jline", "jline", "3.21.0"), + AdvancedCloudDependency("org.litote.kmongo", "kmongo", "4.4.0"), + AdvancedCloudDependency("commons-io", "commons-io", "2.11.0"), + AdvancedCloudDependency("org.slf4j", "slf4j-simple", "1.7.32"), + AdvancedCloudDependency("com.google.guava", "guava", "31.0.1-jre"), + AdvancedCloudDependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core", "1.5.2"), + AdvancedCloudDependency("com.google.code.gson", "gson", "2.9.0"), + AdvancedCloudDependency("io.netty", "netty-all", "4.1.71.Final"), + AdvancedCloudDependency("org.reflections", "reflections", "0.9.12"), + AdvancedCloudDependency("org.mariadb.jdbc", "mariadb-java-client", "2.7.4"), + AdvancedCloudDependency("com.github.ajalt", "clikt", "2.8.0"), + AdvancedCloudDependency("net.kyori", "adventure-api", "4.11.0"), + AdvancedCloudDependency("net.kyori", "adventure-text-serializer-gson", "4.11.0") + ) + ) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/build.gradle b/simplecloud-launcher/build.gradle new file mode 100644 index 000000000..2df3d04bc --- /dev/null +++ b/simplecloud-launcher/build.gradle @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +dependencies { + testApi "io.mockk:mockk:1.13.5" + compileOnly group: 'org.jline', name: 'jline', version: '3.21.0' + compileOnly group: 'org.reflections', name: 'reflections', version: '0.9.12' + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + compileOnly(project(":simplecloud-dependency-loader")) + testApi(project(":simplecloud-dependency-loader")) + compileOnly(project(":simplecloud-runner")) + testApi(project(":simplecloud-runner")) + api(project(":simplecloud-api")) { + transitive = false + } + compileOnly("com.github.ajalt:clikt:2.8.0") + compileOnly group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: dependencyKotlinCouroutinesVersion + compileOnly group: 'org.fusesource.jansi', name: 'jansi', version: '2.4.0' + + compileOnly(group: 'eu.thesimplecloud.clientserverapi', name: 'clientserverapi', version: depedencyClientServerAPIVersion) { + transitive = false + } + compileOnly(group: 'eu.thesimplecloud.jsonlib', name: 'json-lib', version: "1.0.8") + + compileOnly 'org.eclipse.aether:aether-impl:1.1.0' + compileOnly 'org.eclipse.aether:aether-connector-basic:1.1.0' + compileOnly 'org.eclipse.aether:aether-transport-file:1.1.0' + compileOnly 'org.eclipse.aether:aether-transport-http:1.1.0' + compileOnly 'org.apache.maven:maven-aether-provider:3.3.9' + + testApi group: 'commons-io', name: 'commons-io', version: dependencyCommonsIOVersion + testApi group: 'com.google.guava', name: 'guava', version: dependencyGuavaVersion + testApi group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion + testApi group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: dependencyKotlinCouroutinesVersion + testApi group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + testApi group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' + +} + +shadowJar { + archiveFileName.set("launcher.jar") +} + +jar { + manifest { + attributes( + 'Main-Class': 'eu.thesimplecloud.launcher.startup.ClassLoaderValidatorMain', + 'Implementation-Version': project.version, + ) + } +} diff --git a/simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/ClassLoaderValidatorMain.java b/simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/ClassLoaderValidatorMain.java new file mode 100644 index 000000000..b9ba1a311 --- /dev/null +++ b/simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/ClassLoaderValidatorMain.java @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.startup; + +/** + * Created by IntelliJ IDEA. + * Date: 05.09.2020 + * Time: 12:36 + * + * @author Frederick Baier + */ +public class ClassLoaderValidatorMain { + + public static void main(String[] args) { + validateClassLoader(); + LauncherMainKt.main(args); + } + + private static void validateClassLoader() { + if (Thread.currentThread().getContextClassLoader() == ClassLoader.getSystemClassLoader()) { + System.out.println("Invalid classloader. Launcher must be executed via runner.jar"); + System.out.println("Start runner.jar instead."); + throw new IllegalStateException("Invalid classloader"); + } + } + +} diff --git a/simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/WrapperRamWriter.kt b/simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/WrapperRamWriter.kt new file mode 100644 index 000000000..89bd2512d --- /dev/null +++ b/simplecloud-launcher/src/main/java/eu/thesimplecloud/launcher/startup/WrapperRamWriter.kt @@ -0,0 +1,34 @@ +package eu.thesimplecloud.launcher.startup + +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperInfo +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +class WrapperRamWriter(private val wrapperRam: Map) { + + private val directory = File("storage/wrappers") + + + fun write() { + val wrapperToRam = wrapperRam.filter { it.value.toIntOrNull() != null }.map { it.key to it.value.toInt() } + wrapperToRam.forEach { + writeRamToFile(it.first, it.second) + } + } + + private fun writeRamToFile(wrapperName: String, ram: Int) { + val wrapperFile = File(directory, "$wrapperName.json") + if (!wrapperFile.exists()) { + return + } + val wrapperInfo = JsonLib.fromJsonFile(wrapperFile)!!.getObject(DefaultWrapperInfo::class.java) + val newWrapperInfo = DefaultWrapperInfo( + wrapperInfo.getName(), + wrapperInfo.getHost(), + wrapperInfo.getMaxSimultaneouslyStartingServices(), + ram + ) + JsonLib.fromObject(newWrapperInfo).saveAsFile(wrapperFile) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationClassLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationClassLoader.kt new file mode 100644 index 000000000..d83c924eb --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationClassLoader.kt @@ -0,0 +1,62 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.application + +import eu.thesimplecloud.launcher.external.module.ModuleClassLoader +import eu.thesimplecloud.launcher.external.module.handler.IModuleHandler +import java.net.URL + +class ApplicationClassLoader( + urls: Array, + parent: ClassLoader, + applicationName: String, + moduleHandler: IModuleHandler +) : ModuleClassLoader(urls, parent, "Cloud-Application-$applicationName", moduleHandler) { + + companion object { + init { + ClassLoader.registerAsParallelCapable() + } + } + + fun clearCachedClasses() { + this.cachedClasses.clear() + } + + override fun findClass(name: String): Class<*> { + return super.findClass(name) + } + + fun hasCached(clazz: Class<*>): Boolean { + return this.cachedClasses.values.contains(clazz) + } + + fun setCachedClass(clazz: Class<*>) { + this.cachedClasses[clazz.name] = clazz + } + + fun isThisClassLoader(clazz: Class<*>): Boolean { + return clazz.classLoader === this + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationStarter.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationStarter.kt new file mode 100644 index 000000000..daf0efe4d --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ApplicationStarter.kt @@ -0,0 +1,67 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.application + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.handler.ModuleHandler +import eu.thesimplecloud.launcher.external.module.handler.UnsafeModuleLoader +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.launcher.updater.BaseUpdater +import eu.thesimplecloud.launcher.updater.UpdateExecutor +import java.io.File +import java.net.URL + +class ApplicationStarter { + //TODO replace properties + fun startApplication(applicationType: CloudApplicationType) { + val launcherClassLoader = Launcher.instance.currentClassLoader + Thread.currentThread().contextClassLoader = launcherClassLoader + val moduleHandler = ModuleHandler() + val createClassLoaderFunction: (Array, String) -> ClassLoader = + { urls, name -> ApplicationClassLoader(urls, launcherClassLoader, name, moduleHandler) } + val moduleFileName = applicationType.name.lowercase() + ".json" + val file = File(DirectoryPaths.paths.storagePath + "base.jar") + if (!Launcher.instance.launcherStartArguments.disableAutoUpdater || !file.exists()) { + Launcher.instance.consoleSender.sendMessage("Checking for base updates...") + val updater = BaseUpdater() + if (updater.isUpdateAvailable()) { + Launcher.instance.consoleSender.sendMessage("Base update found: ${updater.getVersionToInstall()!!} (current: ${updater.getCurrentVersion()})") + Launcher.instance.consoleSender.sendMessage("Downloading base update...") + UpdateExecutor().executeUpdate(updater) + } else { + Launcher.instance.consoleSender.sendMessage("You are running the latest version of SimpleCloud.") + } + } + val moduleFileContent = moduleHandler.loadModuleFileContent(file, moduleFileName) + val loadedModuleFileContent = LoadedModuleFileContent(file, moduleFileContent, null) + val loadedModule = UnsafeModuleLoader(createClassLoaderFunction).loadModule(loadedModuleFileContent) + + + val cloudModule = loadedModule.cloudModule as ICloudApplication + cloudModule.onEnable() + Launcher.instance.activeApplication = cloudModule + } + + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/CloudApplicationType.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/CloudApplicationType.kt new file mode 100644 index 000000000..02d917247 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/CloudApplicationType.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.application + +enum class CloudApplicationType { + + MANAGER, WRAPPER; + + fun getApplicationName() = this.name.substring(0, 1) + this.name.substring(1).lowercase() + + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ICloudApplication.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ICloudApplication.kt new file mode 100644 index 000000000..3da2f38ca --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/application/ICloudApplication.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.application + +import eu.thesimplecloud.api.external.ICloudModule + +interface ICloudApplication : ICloudModule { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/CreateJavaVersion.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/CreateJavaVersion.kt new file mode 100644 index 000000000..77bf42ec7 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/CreateJavaVersion.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.setups.JavaSetup +import eu.thesimplecloud.launcher.startup.Launcher + +@Command("create", CommandType.CONSOLE) +class CreateJavaVersion : ICommandHandler { + + @CommandSubPath("javaversion", "Creates a new java version") + fun createJavaVersion(sender: ICommandSender) { + Launcher.instance.setupManager.queueSetup(JavaSetup()) + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/HelpCommand.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/HelpCommand.kt new file mode 100644 index 000000000..8dbec4407 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/HelpCommand.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.ConsoleSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.startup.Launcher + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 07.09.2019 + * Time: 16:07 + */ +@Command("help", CommandType.CONSOLE_AND_INGAME, "cloud.command.help") +class HelpCommand() : ICommandHandler { + + @CommandSubPath + fun handleCommand(sender: ICommandSender) { + val allCommands = Launcher.instance.commandManager.commands + .filter { it.commandType != CommandType.INGAME } + .filter { !it.path.startsWith("help") } + + if (sender is ConsoleSender) { + val commandAmount = Launcher.instance.commandManager.commands + .map { it.path.split(" ")[0] }.toSet().size - 1 + sender.sendProperty("commands.help.header", commandAmount.toString()) + + allCommands.forEach { + sender.sendProperty("commands.help.command", it.path.trim(), it.commandDescription) + } + } else { + sender as ICloudPlayer + allCommands.filter { it.commandType != CommandType.CONSOLE }.forEach { + sender.sendProperty("commands.help.command.ingame", it.getPathWithCloudPrefixIfRequired().trim()) + } + } + + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/StopCommand.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/StopCommand.kt new file mode 100644 index 000000000..0170dbc71 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/StopCommand.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.startup.Launcher + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 07.09.2019 + * Time: 14:15+ + */ +@Command("stop", CommandType.CONSOLE) +class StopCommand() : ICommandHandler { + + @CommandSubPath(description = "Stops the cloud") + fun handleCommand(sender: ICommandSender) { + sender.sendMessage("Stopping the cloud...") + Launcher.instance.shutdown() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/VersionCommand.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/VersionCommand.kt new file mode 100644 index 000000000..1cb5b1745 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/commands/VersionCommand.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath + +/** + * Created by IntelliJ IDEA. + * Date: 08.06.2020 + * Time: 17:14 + * @author Frederick Baier + */ +@Command("version", CommandType.CONSOLE_AND_INGAME) +class VersionCommand : ICommandHandler { + + @CommandSubPath("", "Shows the version") + fun handle(commandSender: ICommandSender) { + commandSender.sendMessage("Version: ${System.getProperty("simplecloud.version")}") + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersion.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersion.kt new file mode 100644 index 000000000..0eb712137 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersion.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.config.java + + +class JavaVersion( + var versions: MutableMap = mutableMapOf() +) { + + companion object { + lateinit var paths: JavaVersion + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersionConfigLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersionConfigLoader.kt new file mode 100644 index 000000000..36a404f78 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/java/JavaVersionConfigLoader.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.config.java + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import java.io.File + +class JavaVersionConfigLoader : AbstractJsonLibConfigLoader( + JavaVersion::class.java, + File("storage/java-versions.json"), + { JavaVersion() }, + true +) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfig.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfig.kt new file mode 100644 index 000000000..7291deacc --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfig.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.config.launcher + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths + +data class LauncherConfig( + var host: String, + val port: Int, + val startServicePort: Int, + val language: String, + val directoryPaths: DirectoryPaths +) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfigLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfigLoader.kt new file mode 100644 index 000000000..5e6198e3c --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/config/launcher/LauncherConfigLoader.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.config.launcher + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +class LauncherConfigLoader : AbstractJsonLibConfigLoader( + LauncherConfig::class.java, + File("launcher.json"), + { LauncherConfig("127.0.0.1", 1630, 50_000,"en", DirectoryPaths()) }, + false +) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleCompleter.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleCompleter.kt new file mode 100644 index 000000000..55d8680fa --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleCompleter.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console + +import eu.thesimplecloud.launcher.startup.Launcher +import org.jline.reader.Candidate +import org.jline.reader.Completer +import org.jline.reader.LineReader +import org.jline.reader.ParsedLine + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 17.04.2020 + * Time: 00:17 + */ +class ConsoleCompleter(private val consoleManager: ConsoleManager) : Completer { + + override fun complete(reader: LineReader, line: ParsedLine, candidates: MutableList) { + val commandString = line.line() + + val suggestions = getConsoleSuggestions(commandString) + if (suggestions.isEmpty()) { + return + } + + val responses = ArrayList() + responses.addAll(suggestions) + + if (responses.isNotEmpty()) { + responses.sort() + candidates.addAll(responses.map { Candidate(it) }) + } + } + + private fun getConsoleSuggestions(commandString: String): List { + if (!Launcher.instance.setupManager.hasActiveSetup()) { + return consoleManager.commandManager.getAvailableTabCompleteArgs( + "cloud $commandString", + consoleManager.consoleSender + ) + } + return Launcher.instance.setupManager.getSetupSuggestions(commandString, consoleManager.consoleSender) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleManager.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleManager.kt new file mode 100644 index 000000000..9f9f70e57 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleManager.kt @@ -0,0 +1,115 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console + +import eu.thesimplecloud.launcher.console.command.CommandManager +import eu.thesimplecloud.launcher.logging.LogType +import eu.thesimplecloud.launcher.startup.Launcher +import org.jline.reader.LineReader +import org.jline.reader.LineReaderBuilder +import org.jline.reader.UserInterruptException +import org.jline.terminal.TerminalBuilder + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 06.09.2019 + * Time: 21:29 + */ +class ConsoleManager(val commandManager: CommandManager, val consoleSender: ConsoleSender) : IConsoleManager { + + var thread: Thread? = null + + val lineReader = createLineReader() + private val prompt = Launcher.instance.logger.getColoredString("§bSimpleCloud §7>§f ", LogType.EMPTY) + + private fun createLineReader(): LineReader { + val consoleCompleter = ConsoleCompleter(this) + + val terminal = TerminalBuilder.builder() + .system(true) + .streams(System.`in`, System.out) + .encoding(Charsets.UTF_8) + .dumb(true) + .build() + + return LineReaderBuilder.builder() + .completer(consoleCompleter) + .terminal(terminal) + .option(LineReader.Option.DISABLE_EVENT_EXPANSION, true) + .option(LineReader.Option.AUTO_REMOVE_SLASH, false) + .option(LineReader.Option.INSERT_TAB, false) + .build() + } + + override fun startThread() { + thread = Thread { + var readLine: String + try { + while (!Thread.currentThread().isInterrupted) { + readLine = lineReader.readLine(prompt) + handleInput(readLine) + } + } catch (_: UserInterruptException) { + } catch (_: IllegalStateException) { + } + } + thread?.start() + } + + private fun handleInput(readLine: String) { + val screenManager = Launcher.instance.screenManager + if (screenManager.hasActiveScreen()) { + if (readLine.equals("leave", true)) { + Launcher.instance.screenManager.leaveActiveScreen() + return + } + screenManager.getActiveScreen()?.executeCommand(readLine) + return + } + if (Launcher.instance.setupManager.hasActiveSetup()) { + if (readLine.equals("exit", true)) { + Launcher.instance.setupManager.cancelCurrentSetup() + return + } + + Launcher.instance.setupManager.onResponse(readLine.trim()) + return + } + if (readLine.isBlank()) return + //add cloud to execute a cloud command + try { + commandManager.handleCommand("cloud $readLine", consoleSender) + } catch (e: Exception) { + Launcher.instance.logger.exception(e) + } + } + + + override fun stopThread() { + lineReader.terminal.reader().shutdown() + lineReader.terminal.pause() + thread?.interrupt() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleSender.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleSender.kt new file mode 100644 index 000000000..d64593e54 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/ConsoleSender.kt @@ -0,0 +1,78 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.launcher.startup.Launcher + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 07.09.2019 + * Time: 14:37 + */ +class ConsoleSender : ICommandSender { + + override fun sendMessage(message: String): ICommunicationPromise { + if (message.isBlank()) return CommunicationPromise.UNIT_PROMISE + if (message.startsWith("§c") || message.startsWith("&c")) { + Launcher.instance.logger.warning(filterColorCodes(message)) + } else { + Launcher.instance.logger.console(filterColorCodes(message)) + } + return CommunicationPromise.UNIT_PROMISE + } + + fun sendPropertyInSetup(property: String, vararg placeholderValues: String) { + if (CloudAPI.isAvailable()) { + val replacedMessage = CloudAPI.instance.getLanguageManager().getMessage(property, *placeholderValues) + Launcher.instance.logger.setup(replacedMessage) + return + } + Launcher.instance.logger.setup(property) + } + + override fun hasPermission(permission: String): ICommunicationPromise { + return CommunicationPromise.of(true) + } + + private fun filterColorCodes(message: String): String { + val message = message.replace("$", "&") + val builder = StringBuilder() + val charArray = message.toCharArray() + var lastChar = '0' + for (i in charArray.indices) { + val char = charArray[i] + val isCharToRemove = char == '&' || lastChar == '&' + lastChar = char + if (isCharToRemove) { + continue + } + builder.append(char) + } + return builder.toString() + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/IConsoleManager.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/IConsoleManager.kt new file mode 100644 index 000000000..f5d1dd199 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/IConsoleManager.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console + +interface IConsoleManager { + + /** + * Starts the thread to receive user input + */ + fun startThread() + + /** + * Stops the thread + */ + fun stopThread() + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandData.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandData.kt new file mode 100644 index 000000000..890e71376 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandData.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command + +import eu.thesimplecloud.api.external.ICloudModule +import java.lang.reflect.Method + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 30.08.2019 + * Time: 20:10 + */ +class CommandData( + val cloudModule: ICloudModule, + val path: String, + val commandDescription: String, + val source: ICommandHandler, + val method: Method, + val commandType: CommandType, + val permission: String, + val aliases: Array, + val isLegacy: Boolean, + val parameterDataList: MutableList = ArrayList() +) { + + fun getParameterDataByName(name: String) = this.parameterDataList.firstOrNull { it.name == name } + + fun getParameterDataByNameWithBraces(name: String) = getParameterDataByName(name.drop(1).dropLast(1)) + + fun getPathWithCloudPrefixIfRequired() = getPathWithCloudPrefixIfRequired(this.path) + + fun getPathWithCloudPrefixIfRequired(path: String) = + (if (commandType == CommandType.INGAME) "" else "cloud ") + path + + fun getAllPathsWithAliases(): Collection { + val path = path.split(" ").drop(1).joinToString(" ") + return aliases.map { getPathWithCloudPrefixIfRequired("$it $path") } + .union(listOf(getPathWithCloudPrefixIfRequired())) + } + + fun getIndexOfParameter(parameterName: String): Int { + return getPathWithCloudPrefixIfRequired().split(" ").indexOf("<$parameterName>") + } + + fun hasCloudPrefix() = this.commandType != CommandType.INGAME + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandManager.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandManager.kt new file mode 100644 index 000000000..d9dd742c3 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandManager.kt @@ -0,0 +1,327 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.ICloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.parser.string.StringParser +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.utils.getEnumValues +import eu.thesimplecloud.launcher.console.ConsoleSender +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.EmptyCommandSuggestionProvider +import eu.thesimplecloud.launcher.event.command.CommandExecuteEvent +import eu.thesimplecloud.launcher.event.command.CommandRegisteredEvent +import eu.thesimplecloud.launcher.event.command.CommandUnregisteredEvent +import eu.thesimplecloud.launcher.exception.CommandRegistrationException +import eu.thesimplecloud.launcher.startup.Launcher +import org.reflections.Reflections +import java.util.concurrent.CopyOnWriteArrayList + + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 30.08.2019 + * Time: 17:41 + */ +class CommandManager { + + + val commands = CopyOnWriteArrayList() + private val allowedTypesWithoutCommandArgument = listOf(ICommandSender::class.java, Array::class.java) + + fun handleCommand(readLine: String, commandSender: ICommandSender) { + val readLine = if (readLine.trim().equals("cloud", true)) "cloud help" else readLine.trim() + + if (readLine.toLowerCase().startsWith("cloud") && commandSender is ICloudPlayer) { + if (!commandSender.hasPermission("cloud.command.use").getBlocking()) { + commandSender.sendProperty("command.cloud.no-permission") + return + } + } + + val covertPathFunction: (CommandData) -> String = + { if (commandSender is ConsoleSender) it.path else it.getPathWithCloudPrefixIfRequired() } + val matchingCommandData = getMatchingCommandData(readLine) + if (matchingCommandData == null) { + val list = getAvailableArgsMatchingCommandData(readLine) + if (commandSender is ConsoleSender) { + list.forEach { commandSender.sendMessage(">> ${covertPathFunction(it)} (${it.commandDescription})") } + } else { + list.filter { it.commandType != CommandType.CONSOLE } + .forEach { commandSender.sendMessage("§8>> §7${covertPathFunction(it)}") } + } + if (list.isEmpty()) { + if (commandSender is ICloudPlayer) { + commandSender.sendMessage("This command could not be found! Type \"help\" for help.") + } else { + Launcher.instance.logger.warning("This command could not be found! Type \"help\" for help.") + } + return + } + + return + } + if (matchingCommandData.commandType == CommandType.CONSOLE && commandSender !is ConsoleSender) { + commandSender.sendProperty("commandmanager.onlyconsole") + return + } + if (commandSender is ICloudPlayer) { + if (matchingCommandData.permission.trim() + .isNotEmpty() && !commandSender.hasPermission(matchingCommandData.permission).awaitUninterruptibly() + .get() + ) { + commandSender.sendProperty("command.player.no-permission") + return + } + } + + val event = CommandExecuteEvent(commandSender, matchingCommandData) + getCloudAPI()?.getEventManager()?.call(event) + if (event.isCancelled()) + return + + val list = ArrayList() + val messageArray = readLine.split(" ") + for (parameterData in matchingCommandData.parameterDataList) { + if (parameterData.name == null) { + when (parameterData.type) { + ICommandSender::class.java -> list.add(commandSender) + Array::class.java -> list.add( + messageArray.drop(if (matchingCommandData.hasCloudPrefix()) 2 else 1).toTypedArray() + ) + } + continue + } + + val parameterName: String = parameterData.name + val indexOfParameter = matchingCommandData.getIndexOfParameter(parameterName) + val parameterValue = messageArray[indexOfParameter] + + val obj = try { + StringParser().parseToObject(parameterValue, parameterData.type) + } catch (e: Exception) { + commandSender.sendMessage("§cCan't parse parameter at index $indexOfParameter(\"$parameterValue\") to class ${parameterData.type.simpleName}") + return + } + + if (obj == null) { + commandSender.sendMessage("§cCan't parse parameter at index $indexOfParameter(\"$parameterValue\") to class ${parameterData.type.simpleName}") + if (parameterData.type.isEnum) { + val clazz = parameterData.type as Class> + val enumValues = clazz.getEnumValues() + commandSender.sendMessage("Allowed are: " + enumValues.joinToString(", ")) + } + return + } + list.add(obj) + } + try { + matchingCommandData.method.invoke(matchingCommandData.source, *list.toArray()) + } catch (e: Exception) { + throw e + } + } + + + fun getMatchingCommandData(message: String): CommandData? { + val messageArray = message.split(" ") + val commandDataList = getCommandDataByArgumentLength(messageArray.size) + return commandDataList.firstOrNull { commandData -> + commandData.getAllPathsWithAliases().any { + val path = it.trim() + val pathArray = path.split(" ") + + pathArray.withIndex() + .all { isParameter(it.value) || it.value.toLowerCase() == messageArray[it.index].toLowerCase() } + } + } + } + + private fun getAvailableArgsMatchingCommandData(message: String): List { + val messageArray = message.split(" ") + val dataList = getCommandDataByMinimumArgumentLength(messageArray.size) + val dataListWithoutLegacies = dataList.filter { !it.isLegacy } + return dataListWithoutLegacies.filter { commandData -> + commandData.getAllPathsWithAliases().any { + val path = it.trim() + val pathArray = path.split(" ") + + messageArray.withIndex().all { + val pathValue = pathArray[it.index] + isParameter(pathValue) || it.value.toLowerCase() == pathValue.toLowerCase() + } + } + } + } + + fun getAvailableTabCompleteArgs(message: String, sender: ICommandSender): List { + val messageArray = message.split(" ").map { it.trim() } + val suggestions = HashSet() + val dataList = getAvailableArgsMatchingCommandData(messageArray.dropLast(1).joinToString(" ")) + + dataList.forEach { + if (sender is ICloudPlayer && it.commandType == CommandType.CONSOLE) { + return@forEach + } + if (sender !is ICloudPlayer && it.commandType == CommandType.INGAME) { + return@forEach + } + + val path = it.getPathWithCloudPrefixIfRequired() + val pathArray = path.split(" ") + + if (pathArray.size == messageArray.lastIndex) { + return@forEach + } + + val currentPathValue = pathArray[messageArray.lastIndex] + + val permission = it.permission + if (permission.isEmpty() || sender.hasPermission(permission).getBlocking()) { + if (isParameter(currentPathValue)) { + val commandParameterData = it.getParameterDataByNameWithBraces(currentPathValue) ?: return@forEach + suggestions.addAll( + commandParameterData.provider.getSuggestions( + sender, + message, + messageArray.last() + ) + ) + } else { + suggestions.add(currentPathValue) + } + } + } + + return suggestions.filter { it.toLowerCase().startsWith(messageArray.last().toLowerCase()) } + } + + private fun isParameter(s: String) = s.startsWith("<") && s.endsWith(">") + + private fun getCommandDataByMinimumArgumentLength(length: Int) = + this.commands.filter { it.getPathWithCloudPrefixIfRequired().split(" ").size >= length } + .union(this.commands.filter { it.isLegacy }) + + private fun getCommandDataByArgumentLength(length: Int) = + this.commands.filter { it.getPathWithCloudPrefixIfRequired().trim().split(" ").size == length } + .union(this.commands.filter { it.isLegacy }) + + fun registerAllCommands(cloudModule: ICloudModule, classLoader: ClassLoader, vararg packages: String) { + packages.forEach { pack -> + val reflection = Reflections(pack, Launcher.instance.getNewClassLoaderWithLauncherAndBase()) + reflection.getSubTypesOf(ICommandHandler::class.java).forEach { + val classToUse = Class.forName(it.name, true, classLoader) as Class + try { + registerCommand(cloudModule, classToUse.getDeclaredConstructor().newInstance()) + } catch (e: InstantiationException) { + e.printStackTrace() + } catch (e: IllegalAccessException) { + e.printStackTrace() + } + } + } + + val size = commands.size + Launcher.instance.logger.success("Loaded $size command" + (if (size == 1) "" else "s")) + + } + + fun registerCommand(cloudModule: ICloudModule, command: ICommandHandler) { + val commandClass = command::class.java + val classAnnotation = commandClass.getAnnotation(Command::class.java) + classAnnotation ?: throw NullPointerException() + + try { + for (method in commandClass.declaredMethods) { + val commandSubPath = method.getAnnotation(CommandSubPath::class.java) + commandSubPath ?: continue + val path = + if (commandSubPath.path.isBlank()) classAnnotation.name else classAnnotation.name + " " + commandSubPath.path + val isLegacyCommand = method.parameters.map { it.type }.contains(Array::class.java) + val commandData = CommandData( + cloudModule, + path, + commandSubPath.description, + command, + method, + classAnnotation.commandType, + classAnnotation.permission, + classAnnotation.aliases, + isLegacyCommand + ) + for (parameter in method.parameters) { + val commandArgument = parameter.getAnnotation(CommandArgument::class.java) + if (commandArgument == null) { + if (!allowedTypesWithoutCommandArgument.contains(parameter.type) || !allowedTypesWithoutCommandArgument.any { + it.isAssignableFrom( + parameter.type + ) + }) { + throw CommandRegistrationException("Forbidden parameter type without CommandArgument annotation: ${parameter.type.name}") + } + } + commandData.parameterDataList.add( + CommandParameterData( + parameter.type, + commandArgument?.suggestionProvider?.java?.getDeclaredConstructor()?.newInstance() + ?: EmptyCommandSuggestionProvider(), + commandArgument?.name + ) + ) + } + commands.add(commandData) + getCloudAPI()?.getEventManager()?.call(CommandRegisteredEvent(commandData)) + } + } catch (e: Exception) { + throw e + } + } + + fun unregisterCommands(cloudModule: ICloudModule) { + val moduleCommands = this.commands.filter { it.cloudModule == cloudModule } + this.commands.removeAll(moduleCommands) + moduleCommands.forEach { + getCloudAPI()?.getEventManager()?.call(CommandUnregisteredEvent(it)) + } + } + + fun getAllIngameCommandPrefixes(): Collection = + this.commands.filter { it.commandType == CommandType.INGAME } + .map { it.getAllPathsWithAliases().map { path -> path.split(" ")[0] } }.flatten().toSet() + .union(listOf("cloud")) + + private fun getCloudAPI(): ICloudAPI? { + return try { + CloudAPI.instance + } catch (_: Exception) { + return null + } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandParameterData.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandParameterData.kt new file mode 100644 index 000000000..cc596d0e2 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandParameterData.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command + +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 07.09.2019 + * Time: 14:41 + */ +class CommandParameterData(val type: Class<*>, val provider: ICommandSuggestionProvider, val name: String? = null) { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandType.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandType.kt new file mode 100644 index 000000000..8dbd937d0 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/CommandType.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command + +enum class CommandType { + + CONSOLE, + + /** + * This feature requires ingame the use of /cloud as prefix + */ + CONSOLE_AND_INGAME, + + INGAME, + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/ICommandHandler.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/ICommandHandler.kt new file mode 100644 index 000000000..9c3802495 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/ICommandHandler.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 30.08.2019 + * Time: 19:31 + */ +interface ICommandHandler { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/Command.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/Command.kt new file mode 100644 index 000000000..6d8552ba1 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/Command.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.annotations + +import eu.thesimplecloud.launcher.console.command.CommandType + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 30.08.2019 + * Time: 19:20 + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class Command( + val name: String, + val commandType: CommandType, + /** + * Only used if the command can be executed ingame. + */ + val permission: String = "", + val aliases: Array = [] +) { + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandArgument.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandArgument.kt new file mode 100644 index 000000000..a8ef1175d --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandArgument.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.annotations + +import eu.thesimplecloud.launcher.console.command.provider.EmptyCommandSuggestionProvider +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import kotlin.reflect.KClass + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 07.09.2019 + * Time: 14:46 + */ +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.RUNTIME) +annotation class CommandArgument( + val name: String, + val suggestionProvider: KClass = EmptyCommandSuggestionProvider::class +) { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandSubPath.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandSubPath.kt new file mode 100644 index 000000000..b58e0cf73 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/annotations/CommandSubPath.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.annotations + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 30.08.2019 + * Time: 19:22 + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class CommandSubPath(val path: String = "", val description: String = "") { + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/CloudPlayerCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/CloudPlayerCommandSuggestionProvider.kt new file mode 100644 index 000000000..ddfdfe406 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/CloudPlayerCommandSuggestionProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class CloudPlayerCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/EmptyCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/EmptyCommandSuggestionProvider.kt new file mode 100644 index 000000000..c069ae113 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/EmptyCommandSuggestionProvider.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class EmptyCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return emptyList() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ICommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ICommandSuggestionProvider.kt new file mode 100644 index 000000000..2d5937500 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ICommandSuggestionProvider.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:36 + */ +interface ICommandSuggestionProvider { + + /** + * Returns the suggestions for an argument + * @param sender the sender og the tab request + * @param fullCommand the full command so far including the last argument + * @param lastArgument the last argument of the [fullCommand] + * @return a list with arguments to suggest + */ + fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceCommandSuggestionProvider.kt new file mode 100644 index 000000000..e4434c4fc --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceCommandSuggestionProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class ServiceCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return CloudAPI.instance.getCloudServiceManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceGroupCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceGroupCommandSuggestionProvider.kt new file mode 100644 index 000000000..51da254d3 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceGroupCommandSuggestionProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class ServiceGroupCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceStateCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceStateCommandSuggestionProvider.kt new file mode 100644 index 000000000..40d74bafe --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/ServiceStateCommandSuggestionProvider.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.ServiceState + +class ServiceStateCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return ServiceState.values().map { it.name.uppercase() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/TemplateCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/TemplateCommandSuggestionProvider.kt new file mode 100644 index 000000000..57aaf6fca --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/TemplateCommandSuggestionProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class TemplateCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return CloudAPI.instance.getTemplateManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/WrapperCommandSuggestionProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/WrapperCommandSuggestionProvider.kt new file mode 100644 index 000000000..8352ad449 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/command/provider/WrapperCommandSuggestionProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.command.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class WrapperCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return CloudAPI.instance.getWrapperManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/ISetup.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/ISetup.kt new file mode 100644 index 000000000..8c639edf0 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/ISetup.kt @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup + + +interface ISetup diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/SetupManager.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/SetupManager.kt new file mode 100644 index 000000000..9f085eeb1 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/SetupManager.kt @@ -0,0 +1,232 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup + +import eu.thesimplecloud.api.parser.string.StringParser +import eu.thesimplecloud.api.utils.containsIgnoreCase +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.launcher.console.ConsoleSender +import eu.thesimplecloud.launcher.console.setup.annotations.SetupCancelled +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.extension.replace +import eu.thesimplecloud.launcher.startup.Launcher +import java.lang.reflect.Method +import java.lang.reflect.Parameter + +class SetupManager(val launcher: Launcher) { + + val logger = launcher.logger + val setupQueue = ArrayList() + var currentSetup: SetupData? = null + var currentQuestion: SetupQuestionData? = null + private set + private var currentQuestionIndex = 0 + + private var setupsCompletedPromise = CommunicationPromise(enableTimeout = false) + + fun queueSetup(setup: ISetup, first: Boolean = false) { + val questions = ArrayList() + val methods = setup::class.java.methods + methods.filter { it.isAnnotationPresent(SetupQuestion::class.java) }.forEach { method -> + check(method.parameters.size == 1) { "Function marked with SetupQuestion must have one parameter." } + questions.add( + SetupQuestionData( + method.getAnnotation(SetupQuestion::class.java), + method, + method.parameters[0] + ) + ) + } + + val setupFinishedMethods = methods.filter { it.isAnnotationPresent(SetupFinished::class.java) } + val setupCancelledMethods = methods.filter { it.isAnnotationPresent(SetupCancelled::class.java) } + check(setupFinishedMethods.size <= 1) { "Only one function in a setup can be marked with SetupFinished." } + check(setupCancelledMethods.size <= 1) { "Only one function in a setup can be marked with SetupCancelled." } + val finishedMethod = setupFinishedMethods.firstOrNull() + val cancelledMethod = setupCancelledMethods.firstOrNull() + finishedMethod?.let { check(it.parameters.isEmpty()) { "The function marked with SetupFinished must have 0 parameters." } } + cancelledMethod?.let { check(it.parameters.isEmpty()) { "The function marked with SetupFinished must have 0 parameters." } } + + val setupData = + SetupData(setup, cancelledMethod, finishedMethod, questions.sortedBy { it.setupQuestion.number }) + if (this.currentSetup == null) { + startSetup(setupData) + return + } + if (first) + this.setupQueue.add(0, setupData) + else + this.setupQueue.add(setupData) + } + + fun hasActiveSetup(): Boolean { + return this.currentSetup != null + } + + private fun startSetup(setupData: SetupData) { + this.currentSetup = setupData + this.currentQuestion = setupData.questions[currentQuestionIndex] + + Launcher.instance.clearConsole() + Launcher.instance.logger.setup("Setup started. Type `exit` to leave the setup.") + printCurrentQuestion() + } + + private fun printCurrentQuestion() { + val currentQuestion = this.currentQuestion + ?: throw IllegalStateException("There is no setup at the moment") + val suggestionProvider = currentQuestion.setupQuestion.answerProvider.java.newInstance() + //search suggestions for an empty input + val suggestions = suggestionProvider.getSuggestions(launcher.consoleSender) + .replace("", "") + val suffix = if (suggestions.isNotEmpty()) "§ePossible answers: " + suggestions.joinToString() else "" + if (suffix.isEmpty()) { + launcher.consoleSender.sendPropertyInSetup(currentQuestion.setupQuestion.property) + } else { + launcher.consoleSender.sendPropertyInSetup(currentQuestion.setupQuestion.property) + Launcher.instance.logger.setup(suffix) + } + } + + fun onResponse(response: String) { + val currentQuestion = this.currentQuestion ?: return + val parsedValue = StringParser().parseToObject(response, currentQuestion.parameter.type) + val possibleAnswers = currentQuestion.setupQuestion.answerProvider.java.newInstance() + .getSuggestions(launcher.consoleSender) + if (parsedValue is String) { + if (possibleAnswers.isNotEmpty() && !possibleAnswers.containsIgnoreCase(parsedValue)) { + Launcher.instance.logger.setup("Invalid response") + return + } + } + val invokeResponse = try { + currentQuestion.method.invoke(this.currentSetup!!.source, parsedValue) + } catch (e: Exception) { + Launcher.instance.logger.setup("Invalid response") + return + } + if (invokeResponse is Boolean && invokeResponse == false) { + return + } + nextQuestion() + } + + + private fun nextQuestion() { + val activeSetup = this.currentSetup ?: return + if (!hasNextQuestion(activeSetup)) { + finishCurrentSetup() + return + } + this.currentQuestionIndex++ + this.currentQuestion = activeSetup.questions[currentQuestionIndex] + //this.logger.updatePrompt(false) + printCurrentQuestion() + } + + private fun finishCurrentSetup() { + Launcher.instance.clearConsole() + + val currentSetupReference = this.currentSetup + resetSetup() + + if (this.setupQueue.isEmpty()) { + Launcher.instance.logger.printCachedMessages() + } + + currentSetupReference?.callFinishedMethod() + this.logger.success("Setup completed.") + checkForNextSetup() + } + + fun cancelCurrentSetup() { + Launcher.instance.clearConsole() + + val currentSetupReference = this.currentSetup + resetSetup() + + if (this.setupQueue.isEmpty()) { + Launcher.instance.logger.printCachedMessages() + } + + currentSetupReference?.callCancelledMethod() + this.logger.warning("Setup cancelled.") + checkForNextSetup() + } + + private fun checkForNextSetup() { + if (this.setupQueue.isEmpty()) { + this.setupsCompletedPromise.trySuccess(Unit) + this.setupsCompletedPromise = CommunicationPromise(enableTimeout = false) + } + if (this.setupQueue.isNotEmpty()) { + startSetup(this.setupQueue.removeAt(0)) + } + } + + private fun resetSetup() { + this.currentSetup = null + this.currentQuestion = null + this.currentQuestionIndex = 0 + } + + private fun hasNextQuestion(setupData: SetupData) = this.currentQuestionIndex + 1 in setupData.questions.indices + + fun waitForAllSetups() { + if (this.currentSetup != null) + this.setupsCompletedPromise.awaitUninterruptibly() + } + + fun getSetupSuggestions(userInput: String, consoleSender: ConsoleSender): List { + if (!hasActiveSetup()) { + throw IllegalStateException("There is no active setup") + } + + val suggestions = currentQuestion!!.setupQuestion.answerProvider.java.newInstance() + .getSuggestions(consoleSender) + + return suggestions.filter { it.toLowerCase().startsWith(userInput.toLowerCase()) } + } + + + class SetupData( + val source: ISetup, + val cancelledMethod: Method?, + val finishedMethod: Method?, + val questions: List + ) { + + fun callFinishedMethod() { + finishedMethod?.invoke(source) + } + + fun callCancelledMethod() { + cancelledMethod?.invoke(source) + } + + } + + class SetupQuestionData(val setupQuestion: SetupQuestion, val method: Method, val parameter: Parameter) + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupCancelled.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupCancelled.kt new file mode 100644 index 000000000..4be918389 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupCancelled.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.annotations + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class SetupCancelled { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupFinished.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupFinished.kt new file mode 100644 index 000000000..f2d03efb3 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupFinished.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.annotations + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class SetupFinished { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupQuestion.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupQuestion.kt new file mode 100644 index 000000000..de2f0a9d2 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/annotations/SetupQuestion.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.annotations + +import eu.thesimplecloud.launcher.console.setup.provider.EmptySetupAnswerProvider +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider +import kotlin.reflect.KClass + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class SetupQuestion( + val number: Int, + val property: String, + val answerProvider: KClass = EmptySetupAnswerProvider::class +) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/BooleanSetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/BooleanSetupAnswerProvider.kt new file mode 100644 index 000000000..9433c5ad5 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/BooleanSetupAnswerProvider.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.provider + +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.06.2020 + * Time: 16:18 + */ +class BooleanSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return listOf("yes", "no") + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/EmptySetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/EmptySetupAnswerProvider.kt new file mode 100644 index 000000000..642d7c24e --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/EmptySetupAnswerProvider.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.provider + +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.06.2020 + * Time: 16:18 + */ +class EmptySetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return emptyList() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/ISetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/ISetupAnswerProvider.kt new file mode 100644 index 000000000..4ebdc5bbb --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/ISetupAnswerProvider.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.provider + +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.06.2020 + * Time: 16:15 + */ +interface ISetupAnswerProvider { + + /** + * Returns the suggestions for an argument + * @param sender the sender of the tab request + * @return a list with arguments to suggest + */ + fun getSuggestions(sender: ICommandSender): Collection + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/TemplateSetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/TemplateSetupAnswerProvider.kt new file mode 100644 index 000000000..1336a3ae4 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/TemplateSetupAnswerProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class TemplateSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return CloudAPI.instance.getTemplateManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/WrapperSetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/WrapperSetupAnswerProvider.kt new file mode 100644 index 000000000..e40d354d6 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/console/setup/provider/WrapperSetupAnswerProvider.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.console.setup.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class WrapperSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): List { + return CloudAPI.instance.getWrapperManager().getAllCachedObjects().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandEvent.kt new file mode 100644 index 000000000..f8b3b5d3d --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.command + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.launcher.console.command.CommandData + +open class CommandEvent(val command: CommandData) : IEvent \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandExecuteEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandExecuteEvent.kt new file mode 100644 index 000000000..3cce02628 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandExecuteEvent.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.command + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.eventapi.ICancellable +import eu.thesimplecloud.launcher.console.command.CommandData + +/** + * This event will be called when a registered cloud command is going to be executed by a player or the console. + */ +class CommandExecuteEvent(val commandSender: ICommandSender, command: CommandData) : CommandEvent(command), + ICancellable { + + private var cancelled = false + + override fun isCancelled(): Boolean = this.cancelled + + override fun setCancelled(cancel: Boolean) { + this.cancelled = cancel + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandRegisteredEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandRegisteredEvent.kt new file mode 100644 index 000000000..3f4b52dd8 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandRegisteredEvent.kt @@ -0,0 +1,27 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.command + +import eu.thesimplecloud.launcher.console.command.CommandData + +class CommandRegisteredEvent(command: CommandData) : CommandEvent(command) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandUnregisteredEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandUnregisteredEvent.kt new file mode 100644 index 000000000..eeb839a61 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/command/CommandUnregisteredEvent.kt @@ -0,0 +1,27 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.command + +import eu.thesimplecloud.launcher.console.command.CommandData + +class CommandUnregisteredEvent(command: CommandData) : CommandEvent(command) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleEvent.kt new file mode 100644 index 000000000..f9d4137e3 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.module + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.launcher.external.module.LoadedModule + +open class ModuleEvent(val module: LoadedModule) : IEvent \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleLoadedEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleLoadedEvent.kt new file mode 100644 index 000000000..e222862c1 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleLoadedEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.module + +import eu.thesimplecloud.launcher.external.module.LoadedModule + +class ModuleLoadedEvent(module: LoadedModule) : ModuleEvent(module) { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleUnloadedEvent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleUnloadedEvent.kt new file mode 100644 index 000000000..de9dd3bd1 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/event/module/ModuleUnloadedEvent.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.event.module + +import eu.thesimplecloud.launcher.external.module.LoadedModule + +class ModuleUnloadedEvent(module: LoadedModule) : ModuleEvent(module) { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/CommandRegistrationException.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/CommandRegistrationException.kt new file mode 100644 index 000000000..5af9a5b2a --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/CommandRegistrationException.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.exception + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 07.09.2019 + * Time: 15:10 + */ +class CommandRegistrationException(message: String?) : Exception(message) { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/DependencyException.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/DependencyException.kt new file mode 100644 index 000000000..bc2c58145 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/DependencyException.kt @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.exception + +class DependencyException(message: String?) : Exception(message) { +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/module/ModuleLoadException.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/module/ModuleLoadException.kt new file mode 100644 index 000000000..24a4f87ff --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/exception/module/ModuleLoadException.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.exception.module + +class ModuleLoadException(moduleName: String, ex: Exception?) : + Exception("An error occurred while loading module: $moduleName", ex) { + + constructor(moduleName: String) : this(moduleName, null) + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/extension/IterableExtension.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/extension/IterableExtension.kt new file mode 100644 index 000000000..a99906857 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/extension/IterableExtension.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.extension + +/** + * Created by IntelliJ IDEA. + * Date: 23.10.2020 + * Time: 15:33 + * @author Frederick Baier + */ + +fun Iterable.replace(oldValue: T, newValue: T): List { + val returnList = ArrayList() + + for (item in this) { + if (item == oldValue) + returnList.add(newValue) + else + returnList.add(item) + } + return returnList +} + +fun Iterable.hasNulls(): Boolean { + return this.any { it == null } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/ExtensionLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/ExtensionLoader.kt new file mode 100644 index 000000000..d465b67e8 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/ExtensionLoader.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external + +import eu.thesimplecloud.launcher.startup.Launcher +import java.io.File +import java.net.URLClassLoader + +class ExtensionLoader { + + fun loadClassInstance(jar: File, classpath: String, parentClass: Class): C { + val newClass = loadClass(jar, classpath, parentClass) + // Apparently its bad to use Class.newInstance, so we use + // newClass.getConstructor() instead + val constructor = newClass.getConstructor() + return constructor.newInstance() + + } + + fun loadClass(jar: File, classpath: String, parentClass: Class): Class { + val urlClassLoader = URLClassLoader(arrayOf(jar.toURI().toURL()), Launcher.instance.currentClassLoader) + val clazz = Class.forName(classpath, true, urlClassLoader) + return clazz.asSubclass(parentClass) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModule.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModule.kt new file mode 100644 index 000000000..1298fc7b7 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModule.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module + +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.external.module.update.UpdaterFileContent +import java.io.File + +class LoadedModule( + val cloudModule: ICloudModule, + val file: File, + val fileContent: ModuleFileContent, + val updaterFileContent: UpdaterFileContent?, + val moduleClassLoader: ClassLoader +) { + + fun getLoadedModuleFileContent(): LoadedModuleFileContent { + return LoadedModuleFileContent(file, fileContent, updaterFileContent) + } + + fun getName(): String { + return this.fileContent.name + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModuleFileContent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModuleFileContent.kt new file mode 100644 index 000000000..3af3be3f3 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/LoadedModuleFileContent.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module + +import eu.thesimplecloud.launcher.external.module.update.UpdaterFileContent +import java.io.File + +data class LoadedModuleFileContent( + val file: File, + val content: ModuleFileContent, + val updaterFileContent: UpdaterFileContent? +) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleClassLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleClassLoader.kt new file mode 100644 index 000000000..2d7162948 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleClassLoader.kt @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module + +import com.google.common.collect.Maps +import eu.thesimplecloud.launcher.external.module.handler.IModuleHandler +import java.net.URL +import java.net.URLClassLoader + +open class ModuleClassLoader( + urls: Array, + parent: ClassLoader, + val moduleName: String, + var moduleHandler: IModuleHandler? +) : URLClassLoader(urls, parent) { + + @Volatile + private var closed: Boolean = false + protected val cachedClasses: MutableMap> = Maps.newConcurrentMap() + + companion object { + init { + ClassLoader.registerAsParallelCapable() + } + } + + override fun findClass(name: String): Class<*> { + if (closed) throw IllegalStateException("ModuleClassLoaders is already closed") + return findClass0(name, true) + } + + fun findClass0(name: String, checkGlobal: Boolean): Class<*> { + val clazz = this.cachedClasses[name] + if (clazz != null) return clazz + val classByName = runCatching { super.findClass(name) }.getOrNull() + if (classByName != null) { + this.cachedClasses[name] = classByName + return classByName + } + if (checkGlobal) { + val otherModuleClass = this.moduleHandler?.findModuleClass(name) + if (otherModuleClass != null) { + this.cachedClasses[name] = otherModuleClass + return otherModuleClass + } + } + throw ClassNotFoundException(name) + } + + override fun close() { + super.close() + this.closed = true + } + + fun isClosed(): Boolean = this.closed + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleCopyType.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleCopyType.kt new file mode 100644 index 000000000..3ac7f88c1 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleCopyType.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module + +/** + * Shows on which services the module shall be copied as plugin. + */ +enum class ModuleCopyType { + + /** + * The module will not be copied to any service. + */ + NONE, + + /** + * The module will be copied to all services. + */ + ALL, + + /** + * The module will be copied to all proxy services. + */ + PROXY, + + /** + * The modules will be copied to all minecraft servers. + */ + SERVER, + + /** + * The module will be copied to all lobby services. + */ + LOBBY + + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleFileContent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleFileContent.kt new file mode 100644 index 000000000..8d9e84e59 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/ModuleFileContent.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module + +import eu.thesimplecloud.runner.dependency.CloudDependency + +data class ModuleFileContent( + val name: String, + val author: String, + val mainClass: String, + val moduleCopyType: ModuleCopyType, + val repositories: List, + val dependencies: List, + val depend: List, + val softDepend: List +) { + + fun isDependencyOf(moduleFileContent: ModuleFileContent): Boolean { + return moduleFileContent.depend.contains(name) + } + + fun dependsOn(dependencyFileContent: ModuleFileContent): Boolean { + return this.depend.contains(dependencyFileContent.name) + } + + fun dependsOrSoftDependsOn(dependencyFileContent: ModuleFileContent): Boolean { + return dependsOn(dependencyFileContent) || this.softDepend.contains(dependencyFileContent.name) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/IModuleHandler.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/IModuleHandler.kt new file mode 100644 index 000000000..d1b1d054f --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/IModuleHandler.kt @@ -0,0 +1,114 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.external.module.LoadedModule +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.ModuleFileContent +import java.io.File +import java.net.URL +import java.net.URLClassLoader + +interface IModuleHandler { + + /** + * Loads only the content of the modules json file. + */ + fun loadModuleFileContent(file: File, moduleFileName: String = "module.json"): ModuleFileContent + + /** + * Loads a single module + */ + fun loadSingleModule(module: LoadedModuleFileContent): LoadedModule { + return loadModuleList(listOf(module)).first() + } + + /** + * Loads a single module from a file + */ + fun loadSingleModuleFromFile(file: File): LoadedModule { + return loadModuleListFromFiles(listOf(file)).first() + } + + fun loadModuleListFromFiles(files: List): List + + /** + * Loads modules + */ + fun loadModuleList(modulesToLoad: List): List + + /** + * Loads all unloaded modules form the modules directory. + */ + fun loadAllUnloadedModules() + + /** + * Returns the first [LoadedModule] found by the specified [name] + */ + fun getLoadedModuleByName(name: String): LoadedModule? + + /** + * Returns the first [LoadedModule] found by the specified [cloudModule] + */ + fun getLoadedModuleByCloudModule(cloudModule: ICloudModule): LoadedModule? + + /** + * Unloaded the specified [cloudModule] + */ + fun unloadModule(cloudModule: ICloudModule) + + /** + * Unloads all modules + */ + fun unloadAllModules() + + /** + * Unloads all reloadable modules + * @see [ICloudModule.isReloadable] + */ + fun unloadAllReloadableModules() + + /** + * Returns a list containing all loaded modules. + */ + fun getLoadedModules(): List + + /** + * Searches the class with the given name. + * This methods searches also in classloaders of all modules. + */ + @Throws(ClassNotFoundException::class) + fun findModuleClass(name: String): Class<*> + + /** + * Searches for the give class in modules and in the system. + */ + @Throws(ClassNotFoundException::class) + fun findModuleOrSystemClass(name: String): Class<*> + + /** + * Sets the function to create module class loaders. + */ + fun setCreateModuleClassLoader(function: (Array, String) -> URLClassLoader) +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleHandler.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleHandler.kt new file mode 100644 index 000000000..292950595 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleHandler.kt @@ -0,0 +1,207 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.exception.module.ModuleLoadException +import eu.thesimplecloud.launcher.external.module.LoadedModule +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.ModuleClassLoader +import eu.thesimplecloud.launcher.external.module.ModuleFileContent +import eu.thesimplecloud.launcher.external.module.update.UpdaterFileContent +import eu.thesimplecloud.launcher.startup.Launcher +import java.io.File +import java.net.URL +import java.net.URLClassLoader +import java.util.concurrent.CopyOnWriteArrayList +import java.util.jar.JarEntry +import java.util.jar.JarFile + +class ModuleHandler( + private val parentClassLoader: ClassLoader = ClassLoader.getSystemClassLoader(), + private val currentLanguage: String = "en", + private val modulesWithPermissionToUpdate: List = emptyList(), + private val checkForUpdates: Boolean = false, + private val handleLoadError: (Throwable) -> Unit = { throw it } +) : IModuleHandler { + + private val loadedModules: MutableList = CopyOnWriteArrayList() + + private var createModuleClassLoaderFunction: (Array, String) -> URLClassLoader = { args, name -> + ModuleClassLoader(args, parentClassLoader, name, this) + } + + + override fun loadAllUnloadedModules() { + loadModuleListFromFiles(getAllModuleJarFiles()) + } + + override fun getLoadedModuleByName(name: String): LoadedModule? { + return this.loadedModules.firstOrNull { it.getName() == name } + } + + override fun getLoadedModuleByCloudModule(cloudModule: ICloudModule): LoadedModule? { + return this.loadedModules.firstOrNull { it.cloudModule == cloudModule } + } + + override fun unloadModule(cloudModule: ICloudModule) { + val loadedModule = getLoadedModuleByCloudModule(cloudModule) + ?: throw IllegalArgumentException("Specified cloud module is not registered") + unloadModule(loadedModule) + } + + override fun unloadAllModules() { + this.loadedModules.forEach { unloadModule(it) } + } + + override fun unloadAllReloadableModules() { + this.loadedModules.filter { it.cloudModule.isReloadable() }.forEach { unloadModule(it) } + } + + override fun getLoadedModules(): List { + return this.loadedModules + } + + private fun unloadModule(loadedModule: LoadedModule) { + UnsafeModuleUnloader(loadedModule).unload() + this.loadedModules.remove(loadedModule) + } + + override fun findModuleClass(name: String): Class<*> { + val mapNotNull = this.loadedModules.mapNotNull { + //Launcher.instance.logger.info("searching class $name in ${it.getName()}") + runCatching { + (it.moduleClassLoader as ModuleClassLoader).findClass0(name, false) + }.getOrNull() + } + return mapNotNull.firstOrNull() ?: throw ClassNotFoundException(name) + } + + override fun findModuleOrSystemClass(name: String): Class<*> { + val clazz = kotlin.runCatching { + this.findModuleClass(name) + }.getOrNull() + if (clazz != null) return clazz + + val classLoader = Launcher.instance.currentClassLoader + return Class.forName(name, true, classLoader) + } + + override fun setCreateModuleClassLoader(function: (Array, String) -> URLClassLoader) { + this.createModuleClassLoaderFunction = function + } + + override fun loadModuleFileContent(file: File, moduleFileName: String): ModuleFileContent { + return this.loadJsonFileInJar(file, moduleFileName) + } + + override fun loadModuleListFromFiles(files: List): List { + val modules = files.map { loadModuleFileContent(it) } + val updatedModuleList = modules.map { + if (this.checkForUpdates) { + if (checkForUpdate(it)) { + return@map loadModuleFileContent(it.file) + } + } + return@map it + } + return loadModuleList(updatedModuleList) + } + + private fun checkForUpdate(loadedModuleFileContent: LoadedModuleFileContent): Boolean { + return ModuleUpdateInstaller(loadedModuleFileContent).updateIfAvailable() + } + + override fun loadModuleList(modulesToLoad: List): List { + val moduleListLoader = ModuleListLoader( + modulesToLoad, + this.loadedModules, + this.createModuleClassLoaderFunction, + this.handleLoadError + ) + val newModules = moduleListLoader.loadModules() + this.loadedModules.addAll(newModules) + newModules.forEach { registerLanguageFile(it) } + newModules.forEach { enableModule(it) } + return newModules + } + + private fun registerLanguageFile(loadedModule: LoadedModule) { + ModuleLanguageFileLoader(this.currentLanguage, loadedModule.file, loadedModule.cloudModule) + .registerLanguageFileIfExist() + } + + private fun enableModule(module: LoadedModule) { + try { + module.cloudModule.onEnable() + } catch (e: Exception) { + this.handleLoadError(e) + } + } + + + private fun loadModuleFileContent(file: File): LoadedModuleFileContent { + val moduleFileContent = loadModuleFileContent(file, "module.json") + val updaterFileContent = this.checkPermissionAndLoadUpdaterFile(file, moduleFileContent) + return LoadedModuleFileContent( + file, + moduleFileContent, + updaterFileContent + ) + } + + private inline fun loadJsonFileInJar(file: File, path: String): T { + require(file.exists()) { "Specified file to load $path from does not exist: ${file.path}" } + try { + val jar = JarFile(file) + val entry: JarEntry = jar.getJarEntry(path) + ?: throw ModuleLoadException("${file.path}: No '$path' found.") + val fileStream = jar.getInputStream(entry) + val jsonLib = JsonLib.fromInputStream(fileStream) + jar.close() + return jsonLib.getObjectOrNull(T::class.java) + ?: throw ModuleLoadException("${file.path}: Invalid '$path'.") + } catch (ex: Exception) { + throw ModuleLoadException(file.path, ex) + } + } + + private fun checkPermissionAndLoadUpdaterFile( + file: File, + moduleFileContent: ModuleFileContent + ): UpdaterFileContent? { + if (!this.modulesWithPermissionToUpdate.contains(moduleFileContent.name)) return null + return runCatching { loadJsonFileInJar(file, "updater.json") }.getOrNull() + } + + private fun getAllModuleJarFiles(): List { + return File(DirectoryPaths.paths.modulesPath).listFiles()?.filter { it.name.endsWith(".jar") } ?: emptyList() + } + + fun getAllCloudModuleFileContents(): List { + return getAllModuleJarFiles().map { loadModuleFileContent(it) } + } + +} diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleLanguageFileLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleLanguageFileLoader.kt new file mode 100644 index 000000000..887929fa7 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleLanguageFileLoader.kt @@ -0,0 +1,85 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.LoadedLanguageFile +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.exception.module.ModuleLoadException +import eu.thesimplecloud.launcher.language.LanguageFileLoader +import java.io.File +import java.util.jar.JarEntry +import java.util.jar.JarFile + +/** + * Created by IntelliJ IDEA. + * Date: 29.11.2020 + * Time: 17:27 + * @author Frederick Baier + */ +class ModuleLanguageFileLoader( + private val currentLanguage: String, + private val moduleFile: File, + private val cloudModule: ICloudModule +) { + + fun registerLanguageFileIfExist() { + val languageFile = loadLanguageFile(moduleFile) + languageFile?.let { + CloudAPI.instance.getLanguageManager().registerLanguageFile(cloudModule, languageFile) + } + } + + private fun loadLanguageFile(file: File): LoadedLanguageFile? { + val loadedLanguageFile = loadLanguageFile(file, this.currentLanguage) + return loadedLanguageFile ?: loadFallbackLanguageFile(file) + } + + private fun loadFallbackLanguageFile(file: File): LoadedLanguageFile? { + return loadLanguageFile(file, LanguageFileLoader.FALLBACK_LANGUAGE) + } + + private fun loadLanguageFile(file: File, language: String): LoadedLanguageFile? { + val map: Map? = + runCatching { loadJsonFileInJar>(file, "languages/${language}.json") }.getOrNull() + return map?.let { LanguageFileLoader().buildFileFromMap(it) } + } + + private inline fun loadJsonFileInJar(file: File, path: String): T { + require(file.exists()) { "Specified file to load $path from does not exist: ${file.path}" } + try { + val jar = JarFile(file) + val entry: JarEntry = jar.getJarEntry(path) + ?: throw ModuleLoadException("${file.path}: No '$path' found.") + val fileStream = jar.getInputStream(entry) + val jsonLib = JsonLib.fromInputStream(fileStream) + jar.close() + return jsonLib.getObjectOrNull(T::class.java) + ?: throw ModuleLoadException("${file.path}: Invalid '$path'.") + } catch (ex: Exception) { + throw ModuleLoadException(file.path, ex) + } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleListLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleListLoader.kt new file mode 100644 index 000000000..b31fe4077 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleListLoader.kt @@ -0,0 +1,127 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.launcher.exception.module.ModuleLoadException +import eu.thesimplecloud.launcher.extension.hasNulls +import eu.thesimplecloud.launcher.external.module.LoadedModule +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.ModuleFileContent +import java.net.URL + +/** + * Created by IntelliJ IDEA. + * Date: 26.11.2020 + * Time: 15:48 + * @author Frederick Baier + */ +class ModuleListLoader( + private val modulesToLoad: List, + private val loadedModuleList: List, + private val classLoaderFunction: (Array, String) -> ClassLoader, + private val handleLoadError: (Throwable) -> Unit = { throw it } +) { + + private val loadedModules: MutableList = ArrayList() + + fun loadModules(): List { + this.modulesToLoad.forEach { + loadSingleModuleCatching(it) + } + return this.loadedModules + } + + private fun loadSingleModuleCatching(module: LoadedModuleFileContent) { + try { + loadSingleModule(module) + } catch (ex: Exception) { + this.handleLoadError(ModuleLoadException(module.content.name, ex)) + } + } + + private fun loadSingleModule(module: LoadedModuleFileContent) { + checkRequirements(module) + val moduleDependencies = getAllHardAndAvailableSoftDependencies(module) + moduleDependencies.forEach { loadSingleModule(it) } + loadModuleSafe(module) + } + + private fun checkRequirements(module: LoadedModuleFileContent) { + if (hasMissingDependencies(module)) { + throw ModuleLoadException("Missing dependency detected in module: ${module.content.name}") + } + if (hasRecursiveDependencies(module)) { + throw ModuleLoadException("Recursive dependency detected in module: ${module.content.name}") + } + } + + private fun loadModuleSafe(module: LoadedModuleFileContent) { + if (isModuleLoaded(module)) + return + val loadedModule = UnsafeModuleLoader(classLoaderFunction).loadModule(module) + this.loadedModules.add(loadedModule) + } + + private fun isModuleLoaded(module: LoadedModuleFileContent): Boolean { + return isModuleAlreadyLoaded(module) || wasModuleLoadedBefore(module) + } + + private fun isModuleAlreadyLoaded(module: LoadedModuleFileContent): Boolean { + return this.loadedModules.map { it.fileContent.name }.contains(module.content.name) + } + + private fun wasModuleLoadedBefore(module: LoadedModuleFileContent): Boolean { + return this.loadedModuleList.map { it.fileContent.name }.contains(module.content.name) + } + + private fun hasMissingDependencies(module: LoadedModuleFileContent): Boolean { + val allHardDependencies = getAllHardDependencies(module.content) + return allHardDependencies.hasNulls() + } + + private fun hasRecursiveDependencies(module: LoadedModuleFileContent): Boolean { + return RecursiveDependencyChecker( + module, + this::getAllHardAndAvailableSoftDependencies + ).hasRecursiveDependencies() + } + + private fun getAllHardAndAvailableSoftDependencies(module: LoadedModuleFileContent): Set { + val hardDependencies = getAllHardDependencies(module.content).requireNoNulls() + val availableSoftDependencies = getAllSoftDependencies(module.content).filterNotNull() + return hardDependencies.union(availableSoftDependencies) + } + + private fun getAllHardDependencies(content: ModuleFileContent): List { + return content.depend.map { findModuleFileContentByName(it) } + } + + private fun getAllSoftDependencies(content: ModuleFileContent): List { + return content.softDepend.map { findModuleFileContentByName(it) } + } + + private fun findModuleFileContentByName(name: String): LoadedModuleFileContent? { + return this.modulesToLoad.firstOrNull { it.content.name == name } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleUpdateInstaller.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleUpdateInstaller.kt new file mode 100644 index 000000000..154f5a7ff --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/ModuleUpdateInstaller.kt @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.updater.ModuleUpdater +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.launcher.updater.UpdateExecutor + +/** + * Created by IntelliJ IDEA. + * Date: 29.11.2020 + * Time: 18:28 + * @author Frederick Baier + */ +class ModuleUpdateInstaller( + private val loadedModuleFileContent: LoadedModuleFileContent +) { + + /** + * Installs the update if there is one + * @return whether a update was installed + */ + fun updateIfAvailable(): Boolean { + val (_, content, updaterFileContent) = loadedModuleFileContent + if (updaterFileContent != null && !Launcher.instance.launcherStartArguments.disableAutoUpdater) { + val updater = ModuleUpdater(updaterFileContent, loadedModuleFileContent.file) + if (updater.isUpdateAvailable()) { + Launcher.instance.consoleSender.sendProperty("manager.module.updating", content.name) + UpdateExecutor().executeUpdate(updater) + Launcher.instance.consoleSender.sendProperty("manager.module.updated", content.name) + return true + } + } + return false + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/RecursiveDependencyChecker.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/RecursiveDependencyChecker.kt new file mode 100644 index 000000000..717b897cd --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/RecursiveDependencyChecker.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent + +/** + * Created by IntelliJ IDEA. + * Date: 26.11.2020 + * Time: 17:33 + * @author Frederick Baier + */ +class RecursiveDependencyChecker( + private val moduleToCheck: LoadedModuleFileContent, + private val dependencyGetFunction: (LoadedModuleFileContent) -> Collection +) { + + fun hasRecursiveDependencies(): Boolean { + val allDependencies = collectAllDependencies(moduleToCheck) + return allDependencies.any { doesDependencyDependOnModuleToCheck(it) } + } + + private fun doesDependencyDependOnModuleToCheck(dependency: LoadedModuleFileContent): Boolean { + return dependency.content.dependsOrSoftDependsOn(moduleToCheck.content) + } + + fun collectAllDependencies( + module: LoadedModuleFileContent, + list: MutableList = ArrayList() + ): MutableList { + if (list.contains(module)) + return list + list.add(module) + + val dependencies = dependencyGetFunction(module) + dependencies.forEach { collectAllDependencies(it, list) } + return list + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleLoader.kt new file mode 100644 index 000000000..87772f6c4 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleLoader.kt @@ -0,0 +1,82 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.event.module.ModuleLoadedEvent +import eu.thesimplecloud.launcher.external.module.LoadedModule +import eu.thesimplecloud.launcher.external.module.LoadedModuleFileContent +import eu.thesimplecloud.launcher.external.module.ModuleFileContent +import eu.thesimplecloud.loader.dependency.DependencyLoader +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import java.io.File +import java.net.URL + +/** + * Created by IntelliJ IDEA. + * Date: 26.11.2020 + * Time: 16:56 + * @author Frederick Baier + */ +class UnsafeModuleLoader( + private val classLoaderFunction: (Array, String) -> ClassLoader +) { + + fun loadModule(loadedModuleFileContent: LoadedModuleFileContent): LoadedModule { + val moduleFile = loadedModuleFileContent.file + val content = loadedModuleFileContent.content + val loadedDependencyFiles = getRequiredDependencies(content) + val loadedDependencyURLs = loadedDependencyFiles.map { it.toURI().toURL() }.toTypedArray() + val classLoader = + this.classLoaderFunction(arrayOf(moduleFile.toURI().toURL(), *loadedDependencyURLs), content.name) + val cloudModule = this.loadModuleClassInstance(classLoader, content.mainClass) + val loadedModule = + LoadedModule(cloudModule, moduleFile, content, loadedModuleFileContent.updaterFileContent, classLoader) + CloudAPI.instance.getEventManager().call(ModuleLoadedEvent(loadedModule)) + + return loadedModule + } + + private fun loadModuleClassInstance(classLoader: ClassLoader, mainClassName: String): ICloudModule { + val mainClass = loadModuleClass(classLoader, mainClassName) + val constructor = mainClass.getConstructor() + return constructor.newInstance() + } + + private fun loadModuleClass(classLoader: ClassLoader, mainClassName: String): Class { + val mainClass = classLoader.loadClass(mainClassName) + return mainClass.asSubclass(ICloudModule::class.java) + } + + private fun getRequiredDependencies(moduleFileContent: ModuleFileContent): Set { + val dependencyLoader = DependencyLoader.INSTANCE + val launcherDependencies = moduleFileContent.dependencies + .map { AdvancedCloudDependency(it.groupId, it.artifactId, it.version) } + return dependencyLoader.loadDependencies( + moduleFileContent.repositories, + launcherDependencies + ) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleUnloader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleUnloader.kt new file mode 100644 index 000000000..17386f162 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/handler/UnsafeModuleUnloader.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.handler + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.launcher.event.module.ModuleUnloadedEvent +import eu.thesimplecloud.launcher.exception.module.ModuleLoadException +import eu.thesimplecloud.launcher.external.module.LoadedModule +import eu.thesimplecloud.launcher.external.module.ModuleClassLoader + +/** + * Created by IntelliJ IDEA. + * Date: 27.11.2020 + * Time: 21:04 + * @author Frederick Baier + */ +class UnsafeModuleUnloader(val loadedModule: LoadedModule) { + + fun unload() { + val cloudModule = loadedModule.cloudModule + try { + cloudModule.onDisable() + } catch (ex: Exception) { + throw ModuleLoadException("Error while unloading module ${loadedModule.getName()}", ex) + } + + //unregister all listeners etc. + CloudAPI.instance.getEventManager().unregisterAllListenersByCloudModule(cloudModule) + (loadedModule.moduleClassLoader as ModuleClassLoader).close() + + //unregister all message channel + CloudAPI.instance.getMessageChannelManager().unregisterMessageChannel(cloudModule) + + CloudAPI.instance.getEventManager().call(ModuleUnloadedEvent(loadedModule)) + + //reset all property values + CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().forEach { player -> + player.getProperties().forEach { (it.value as Property).resetValue() } + } + CloudAPI.instance.getCloudServiceManager().getAllCachedObjects().forEach { group -> + group.getProperties().forEach { (it.value as Property).resetValue() } + } + + CloudAPI.instance.getLanguageManager().unregisterLanguageFileByCloudModule(cloudModule) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdateMethod.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdateMethod.kt new file mode 100644 index 000000000..f61695b28 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdateMethod.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.update + +/** + * Created by IntelliJ IDEA. + * Date: 13.06.2020 + * Time: 08:13 + * @author Frederick Baier + */ +enum class UpdateMethod { + + /** + * The current version of the cloud will be used to check for an updater + */ + CLOUD, + + /** + * The newest version will be loaded from web every time the cloud starts. + */ + WEB + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdaterFileContent.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdaterFileContent.kt new file mode 100644 index 000000000..d58152500 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/update/UpdaterFileContent.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.update + +/** + * Created by IntelliJ IDEA. + * Date: 12.06.2020 + * Time: 18:10 + * @author Frederick Baier + */ +class UpdaterFileContent( + val groupId: String, + val artifactId: String, + val repository: String, + val updateMethod: UpdateMethod +) \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/updater/ModuleUpdater.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/updater/ModuleUpdater.kt new file mode 100644 index 000000000..80cd58220 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/external/module/updater/ModuleUpdater.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.external.module.updater + +import eu.thesimplecloud.launcher.external.module.update.UpdateMethod +import eu.thesimplecloud.launcher.external.module.update.UpdaterFileContent +import eu.thesimplecloud.launcher.updater.AbstractUpdater +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 12.06.2020 + * Time: 21:03 + * @author Frederick Baier + */ +class ModuleUpdater( + private val updaterFileContent: UpdaterFileContent, + moduleFile: File +) : AbstractUpdater(updaterFileContent.groupId, updaterFileContent.artifactId, moduleFile) { + + override fun getCurrentVersion(): String { + return getVersionFromManifestFile(this.updateFile) + } + + override fun executeJar() { + } + + override fun getVersionToInstall(): String? { + return when (updaterFileContent.updateMethod) { + UpdateMethod.CLOUD -> getCurrentLauncherVersion() + UpdateMethod.WEB -> super.getVersionToInstall() + } + } + + override fun getRepositoryURL(): String { + val repository = updaterFileContent.repository + if (repository.equals("CLOUD", true)) + return super.getRepositoryURL() + return repository + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/language/LanguageFileLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/language/LanguageFileLoader.kt new file mode 100644 index 000000000..808e73cb7 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/language/LanguageFileLoader.kt @@ -0,0 +1,115 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.language + +import com.google.gson.JsonObject +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.language.LanguageProperty +import eu.thesimplecloud.api.language.LoadedLanguageFile +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.utils.FileCopier +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 18.10.2020 + * Time: 15:30 + * @author Frederick Baier + */ +class LanguageFileLoader { + + private val languageDir = File(DirectoryPaths.paths.languagesPath) + + private val allLanguages = listOf("en", "de") + + fun loadFile(launcherConfig: LauncherConfig) { + if (!languageDir.exists() || languageDir.listFiles().isEmpty()) { + languageDir.mkdirs() + copyLanguageFiles() + } + val language = launcherConfig.language + loadLanguage(language) + } + + private fun copyLanguageFiles() { + allLanguages.forEach { + FileCopier.copyFileOutOfJar(getLanguageFileByLanguage(it), "/language/$it.json") + } + } + + private fun loadLanguage(language: String) { + val languageFile = getLanguageFileByLanguage(language) + + if (languageFile.exists()) + addMissingPropertiesToLanguageFile(languageFile, language) + + if (!languageFile.exists()) { + if (languageFile != getLanguageFileByLanguage(FALLBACK_LANGUAGE)) { + loadLanguage(FALLBACK_LANGUAGE) + return + } + } + CloudAPI.instance.getLanguageManager() + .registerLanguageFile(CloudAPI.instance.getThisSidesCloudModule(), loadLanguageFile(languageFile)) + } + + private fun addMissingPropertiesToLanguageFile(languageFile: File, language: String) { + val inputStream = this::class.java.getResourceAsStream("/language/$language.json") + val actualJson = JsonLib.fromInputStream(inputStream) + val copiedJson = JsonLib.fromJsonFile(languageFile)!! + val actualJsonObject = actualJson.jsonElement as JsonObject + val allPropertiesActualJson = actualJsonObject.entrySet().map { it.key } + val allPropertiesCopiedJson = (copiedJson.jsonElement as JsonObject).entrySet().map { it.key } + val missingProperties = allPropertiesActualJson.toMutableList() + missingProperties.removeAll(allPropertiesCopiedJson) + + if (missingProperties.isEmpty()) return + missingProperties.forEach { + copiedJson.append(it, actualJsonObject[it]) + } + copiedJson.saveAsFile(languageFile) + } + + fun loadLanguageFile(file: File): LoadedLanguageFile { + val map = JsonLib.fromJsonFile(file)!!.getObject(HashMap::class.java) as Map + return buildFileFromMap(map) + } + + fun buildFileFromMap(map: Map): LoadedLanguageFile { + val properties = map.entries.map { LanguageProperty(it.key, it.value) } + return LoadedLanguageFile(properties) + } + + private fun getLanguageFileByLanguage(language: String): File { + return File(languageDir, "$language.json") + } + + companion object { + const val FALLBACK_LANGUAGE = "en" + + val isFirstStart = !LanguageFileLoader().getLanguageFileByLanguage(FALLBACK_LANGUAGE).exists() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/AnsiColorHelper.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/AnsiColorHelper.kt new file mode 100644 index 000000000..ac804bde8 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/AnsiColorHelper.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.logging + +import org.fusesource.jansi.Ansi + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 05.09.2019 + * Time: 17:38 + */ +enum class AnsiColorHelper(val ansiName: String, val index: Char, val ansiCode: String) { + + RESET("reset", 'r', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.DEFAULT).boldOff().toString()), + WHITE("white", 'f', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.WHITE).bold().toString()), + BLACK("black", '0', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLACK).bold().toString()), + RED("red", 'c', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.RED).bold().toString()), + YELLOW("yellow", 'e', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.YELLOW).bold().toString()), + BLUE("blue", '9', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLUE).bold().toString()), + GREEN("green", 'a', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.GREEN).bold().toString()), + PURPLE("purple", '5', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.MAGENTA).boldOff().toString()), + ORANGE("orange", '6', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.YELLOW).boldOff().toString()), + GRAY("gray", '7', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.WHITE).boldOff().toString()), + DARK_RED("dark_red", '4', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.RED).boldOff().toString()), + DARK_GRAY("dark_gray", '8', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLACK).boldOff().toString()), + DARK_BLUE("dark_blue", '1', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLUE).boldOff().toString()), + DARK_GREEN("dark_green", '2', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.GREEN).boldOff().toString()), + LIGHT_BLUE("light_blue", 'b', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.CYAN).bold().toString()), + CYAN("cyan", '3', Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.CYAN).boldOff().toString()); + + companion object { + fun toColoredString(msg: String): String { + var text = msg + for (consoleColour in values()) { + text = text.replace('§'.toString() + "" + consoleColour.index, consoleColour.ansiCode) + text = text.replace('&'.toString() + "" + consoleColour.index, consoleColour.ansiCode) + } + + return text + } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/ILoggerMessageListener.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/ILoggerMessageListener.kt new file mode 100644 index 000000000..0cc316610 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/ILoggerMessageListener.kt @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.logging + +interface ILoggerMessageListener { + + fun message(msg: String, logType: LogType) + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LogType.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LogType.kt new file mode 100644 index 000000000..29692b13a --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LogType.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.logging + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 05.09.2019 + * Time: 17:50 + */ +enum class LogType { + + SUCCESS, INFO, ERROR, WARNING, EMPTY, CONSOLE, SETUP + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LoggerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LoggerProvider.kt new file mode 100644 index 000000000..7f958fb40 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/logging/LoggerProvider.kt @@ -0,0 +1,233 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.logging + +import eu.thesimplecloud.launcher.screens.IScreenManager +import eu.thesimplecloud.launcher.startup.Launcher +import org.jline.reader.LineReader +import org.jline.utils.InfoCmp +import java.io.File +import java.io.PrintWriter +import java.io.StringWriter +import java.nio.charset.StandardCharsets +import java.text.SimpleDateFormat +import java.util.* +import java.util.concurrent.TimeUnit +import java.util.logging.FileHandler +import java.util.logging.Level +import java.util.logging.Logger +import java.util.logging.SimpleFormatter + + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 05.09.2019 + * Time: 17:02 + */ +class LoggerProvider(val screenManager: IScreenManager) : Logger("SimpleCloudLogger", null) { + + private val dataFormat = SimpleDateFormat("[HH:mm:ss]") + + private val loggerMessageListeners = ArrayList() + + private val logsDir = File("logs/") + + private val cachedMessages = ArrayList>() + + init { + level = Level.ALL + useParentHandlers = false + + System.setProperty("java.util.logging.SimpleFormatter.format", "[%1\$tT] [%4$-7s] %5\$s %n") + + if (!logsDir.exists()) + logsDir.mkdirs() + + val file = File("logs/") + val simpleFormatter = SimpleFormatter() + + val fileHandler = FileHandler(file.canonicalPath + "/simplecloud-log", 5242880, 100, false) + fileHandler.encoding = StandardCharsets.UTF_8.name() + fileHandler.level = Level.ALL + fileHandler.formatter = simpleFormatter + + addHandler(fileHandler) + + deleteOldLogs() + } + + private fun deleteOldLogs() { + val allLogFiles = (logsDir.listFiles() ?: emptyArray()).filterNotNull() + allLogFiles.filter { isOlderThanTenDays(it) }.forEach { it.delete() } + } + + private fun isOlderThanTenDays(logFile: File): Boolean { + val tenDaysInMillis = TimeUnit.DAYS.toMillis(10) + return (System.currentTimeMillis() - logFile.lastModified()) > tenDaysInMillis + } + + fun addLoggerMessageListener(loggerMessageListener: ILoggerMessageListener) { + this.loggerMessageListeners.add(loggerMessageListener) + } + + @Synchronized + fun success(msg: String) { + printMessage(msg, LogType.SUCCESS) + } + + @Synchronized + override fun info(msg: String) { + super.info(msg) + printMessage(msg, LogType.INFO) + } + + @Synchronized + override fun warning(msg: String) { + super.warning(msg) + printMessage(msg, LogType.WARNING) + } + + @Synchronized + override fun severe(msg: String) { + super.severe(msg) + printMessage(msg, LogType.ERROR) + } + + @Synchronized + fun console(msg: String) { + super.info(msg) + printMessage(msg, LogType.CONSOLE) + } + + @Synchronized + fun setup(msg: String) { + super.info(msg) + printMessage(msg, LogType.SETUP) + } + + @Synchronized + fun empty(msg: String) { + super.info(msg) + printMessage(msg, LogType.EMPTY) + } + + @Synchronized + fun printCachedMessages() { + cachedMessages.forEach { + printMessage(it.first, it.second, false) + } + } + + private fun printMessage(msg: String, logType: LogType, cache: Boolean = true) { + if (cache && Launcher.instance.isBaseLoaded + && (logType != LogType.SETUP && logType != LogType.EMPTY && logType != LogType.WARNING) + ) { + if (cachedMessages.size == 50) { + cachedMessages.removeAt(0) + } + + cachedMessages.add(Pair(msg, logType)) + } + if (isMessageBlocked(logType)) { + return + } + val coloredMessage = getColoredString(msg, logType) + this.loggerMessageListeners.forEach { it.message(msg, logType) } + + val lineReader = Launcher.instance.consoleManager.lineReader + + lineReader.terminal.puts(InfoCmp.Capability.carriage_return) + lineReader.terminal.writer().println(coloredMessage); + lineReader.terminal.flush(); + + if (lineReader.isReading) { + lineReader.callWidget(LineReader.REDRAW_LINE) + lineReader.callWidget(LineReader.REDISPLAY) + } + + } + + private fun isMessageBlocked(logType: LogType): Boolean { + if (logType == LogType.WARNING) { + return false + } + + if ((screenManager.hasActiveScreen() && logType != LogType.EMPTY) + || (Launcher.instance.setupManager.hasActiveSetup() && logType != LogType.SETUP) + ) { + return true + } + + return false + } + + fun getColoredString(text: String, type: LogType): String { + var logType = "" + when (type) { + LogType.SUCCESS -> { + logType = "§aSUCCESS§7" + } + + LogType.INFO -> { + logType = "§3INFO§7" + } + + LogType.WARNING -> { + logType = "§6WARNING§7" + } + + LogType.ERROR -> { + logType = "§cERROR§7" + } + + LogType.CONSOLE -> { + logType = "§3CONSOLE§7" + } + + LogType.SETUP -> { + logType = "§3SETUP§7" + } + + else -> {} + } + + var message = "§r$text§r" + if (type != LogType.EMPTY) { + val time = dataFormat.format(Calendar.getInstance().time) + message = "$time $logType: §r$text§r" + } + + return AnsiColorHelper.toColoredString(message) + } + + @Synchronized + fun exception(cause: Throwable) { + val sw = StringWriter() + val pw = PrintWriter(sw, true) + cause.printStackTrace(pw) + val stackTraceMessage = sw.buffer.toString() + this.severe(stackTraceMessage) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreen.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreen.kt new file mode 100644 index 000000000..9acfabacf --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreen.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.screens + +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.api.utils.Nameable + +interface IScreen : Nameable { + + override fun getName(): String = this.getCommandExecutable().getName() + + /** + * Returns the [ICommandExecutable] this screen is recording. + */ + fun getCommandExecutable(): ICommandExecutable + + /** + * Executes a command on this screen. + */ + fun executeCommand(command: String) = getCommandExecutable().executeCommand(command) + + /** + * Returns a list of all saved messages. + */ + fun getAllSavedMessages(): List + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreenManager.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreenManager.kt new file mode 100644 index 000000000..e7879adcb --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/IScreenManager.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.screens + +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.launcher.screens.session.ScreenSession + +interface IScreenManager { + + + /** + * Registers a screen. + */ + fun registerScreen(commandExecutable: ICommandExecutable): IScreen + + /** + * Unregisters the screen found by the specified name. + */ + fun unregisterScreen(name: String) + + /** + * Returns all registered screens. + */ + fun getAllScreens(): Set + + /** + * Adds a message to the screen found by the specified name. + */ + fun addScreenMessage(commandExecutable: ICommandExecutable, message: String) + + /** + * Returns the screen found by the specified name. + */ + fun getScreen(name: String) = getAllScreens().firstOrNull { it.getName().equals(name, true) } + + /** + * Returns the active screen. + */ + fun getActiveScreen(): IScreen? = getActiveScreenSession()?.screen + + /** + * Returns the active screen session + */ + fun getActiveScreenSession(): ScreenSession? + + /** + * Returns whether a screen is active. + */ + fun hasActiveScreen(): Boolean = getActiveScreen() != null + + /** + * Join the specified [ScreenSession] + */ + fun joinScreen(screenSession: ScreenSession) + + /** + * Leaves the active screen. + */ + fun leaveActiveScreen() + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenImpl.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenImpl.kt new file mode 100644 index 000000000..21a3a541f --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenImpl.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.screens + +import eu.thesimplecloud.api.screen.ICommandExecutable +import java.util.concurrent.CopyOnWriteArrayList + +class ScreenImpl(private val commandExecutable: ICommandExecutable) : IScreen { + + private val messages = CopyOnWriteArrayList() + + override fun getCommandExecutable(): ICommandExecutable = this.commandExecutable + + fun addMessage(message: String) { + this.messages.add(message) + if (this.messages.size > 100) { + this.messages.removeAt(0) + } + } + + override fun getAllSavedMessages(): List = this.messages + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenManagerImpl.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenManagerImpl.kt new file mode 100644 index 000000000..2a252b1db --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/ScreenManagerImpl.kt @@ -0,0 +1,89 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.screens + +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.launcher.screens.session.ScreenSession +import eu.thesimplecloud.launcher.startup.Launcher +import java.util.concurrent.CopyOnWriteArraySet + +class ScreenManagerImpl : IScreenManager { + + private val screens = CopyOnWriteArraySet() + + private var activeSession: ScreenSession? = null + + override fun registerScreen(commandExecutable: ICommandExecutable): IScreen { + val screen = ScreenImpl(commandExecutable) + this.screens.add(screen) + + joinScreenIfActive(screen) + + return screen + } + + override fun unregisterScreen(name: String) { + this.screens.removeIf { it.getName().equals(name, true) } + } + + override fun addScreenMessage(commandExecutable: ICommandExecutable, message: String) { + val screen = getScreen(commandExecutable.getName()) ?: registerScreen(commandExecutable) + screen as ScreenImpl + screen.addMessage(message) + if (activeSession?.screen == screen) { + Launcher.instance.logger.empty(message) + } + } + + override fun getAllScreens(): Set = this.screens + + override fun getActiveScreenSession(): ScreenSession? { + return this.activeSession + } + + override fun joinScreen(screenSession: ScreenSession) { + this.activeSession = screenSession + + Launcher.instance.clearConsole() + val screen = screenSession.screen + screen.getAllSavedMessages().forEach { Launcher.instance.logger.empty(it) } + Launcher.instance.logger.empty("You joined the screen ${screen.getName()}. To leave the screen write \"leave\"") + Launcher.instance.logger.empty("All commands will be executed on the screen.") + } + + override fun leaveActiveScreen() { + this.activeSession = null + Launcher.instance.clearConsole() + + Launcher.instance.logger.printCachedMessages() + } + + private fun joinScreenIfActive(screen: IScreen) { + val activeSession = this.activeSession ?: return + if (activeSession.screenCloseBehaviour != ScreenSession.ScreenCloseBehaviour.REOPEN) return + if (activeSession.screen.getName().equals(screen.getName(), true)) { + joinScreen(ScreenSession(screen, ScreenSession.ScreenCloseBehaviour.REOPEN)) + } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/session/ScreenSession.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/session/ScreenSession.kt new file mode 100644 index 000000000..13fc5d2d7 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/screens/session/ScreenSession.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.screens.session + +import eu.thesimplecloud.launcher.screens.IScreen + +/** + * Created by IntelliJ IDEA. + * Date: 21.09.2020 + * Time: 13:29 + * @author Frederick Baier + */ +class ScreenSession( + val screen: IScreen, + val screenCloseBehaviour: ScreenCloseBehaviour +) { + + + enum class ScreenCloseBehaviour { + + /** + * Closes the screen after the service the screen belongs to closes + */ + + CLOSE, + + /** + * Keeps the screen open until "leave" was typed into the console + */ + KEEP_OPEN, + + /** + * Reopens the screen if the service starts again + */ + REOPEN; + + + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/AutoIpSetup.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/AutoIpSetup.kt new file mode 100644 index 000000000..f2632c579 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/AutoIpSetup.kt @@ -0,0 +1,71 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.console.setup.provider.BooleanSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.launcher.utils.IpValidator +import eu.thesimplecloud.launcher.utils.WebsiteContentLoader + +class AutoIpSetup : ISetup { + + @SetupQuestion( + 0, + "Do you want to retrieve your ip automatically via `ipify.org`?", + BooleanSetupAnswerProvider::class + ) + fun setup(boolean: Boolean): Boolean { + if (!boolean) { + Launcher.instance.setupManager.queueSetup(IpSetup(), true) + return true + } + + val ip = try { + val data = WebsiteContentLoader().loadContent("https://api.ipify.org?format=json") + JsonLib.fromJsonString(data).getString("ip") + } catch (e: Exception) { + Launcher.instance.logger.warning("Unable to connect to \"ipify.org\".") + return false + } + if (ip == null || !IpValidator().validate(ip)) { + Launcher.instance.logger.warning("Received response can not be parsed to an ip.") + return false + } + + val launcherConfig = Launcher.instance.launcherConfig + val config = LauncherConfig( + ip, + launcherConfig.port, + 50000, + launcherConfig.language, + launcherConfig.directoryPaths + ) + Launcher.instance.replaceLauncherConfig(config) + return true + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/IpSetup.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/IpSetup.kt new file mode 100644 index 000000000..0e013f208 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/IpSetup.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups + +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.launcher.utils.IpValidator + +class IpSetup : ISetup { + + + @SetupQuestion(0, "Please provide the ip of the manager") + fun setup(string: String): Boolean { + if (!IpValidator().validate(string)) { + Launcher.instance.consoleSender.sendPropertyInSetup("The specified ip is invalid.") + return false + } + + val launcherConfig = Launcher.instance.launcherConfig + val config = LauncherConfig( + string, + launcherConfig.port, + 50000, + launcherConfig.language, + launcherConfig.directoryPaths + ) + Launcher.instance.replaceLauncherConfig(config) + return true + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/JavaSetup.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/JavaSetup.kt new file mode 100644 index 000000000..8413cbb74 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/JavaSetup.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups + +import eu.thesimplecloud.launcher.config.java.JavaVersion +import eu.thesimplecloud.launcher.config.java.JavaVersionConfigLoader +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher + +class JavaSetup : ISetup { + + lateinit var name: String + lateinit var path: String + + @SetupQuestion(0, "manager.setup.service-versions.question.javaName") + fun javaNameSetup(name: String): Boolean { + return if (name.isNotEmpty()) { + this.name = name + true + } else { + false + } + } + + @SetupQuestion(1, "manager.setup.service-versions.question.java") + fun javaVersionSetup(path: String): Boolean { + return if (path.isNotEmpty()) { + this.path = path + setup() + true + } else { + false + } + } + + fun setup() { + Launcher.instance.consoleSender.sendPropertyInSetup("manager.setup.service-versions.question.java.success") + val javaVersion = JavaVersion.paths + javaVersion.versions[name] = path + JavaVersionConfigLoader().saveConfig(javaVersion) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/LanguageSetup.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/LanguageSetup.kt new file mode 100644 index 000000000..29f0cd837 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/LanguageSetup.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups + +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.setups.provider.LanguageSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher + +class LanguageSetup : ISetup { + + + @SetupQuestion(0, "Which language do you want to use?", LanguageSetupAnswerProvider::class) + fun setup(answer: String): Boolean { + val launcherConfig = Launcher.instance.launcherConfig + val config = LauncherConfig( + launcherConfig.host, + launcherConfig.port, + 50000, + answer.lowercase(), + launcherConfig.directoryPaths + ) + Launcher.instance.replaceLauncherConfig(config) + return true + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/StartSetup.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/StartSetup.kt new file mode 100644 index 000000000..1ad8c2e2e --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/StartSetup.kt @@ -0,0 +1,57 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups + +import eu.thesimplecloud.launcher.application.CloudApplicationType +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupCancelled +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.setups.provider.ApplicationTypeSetupAnswerProvider +import eu.thesimplecloud.launcher.startup.Launcher +import kotlin.concurrent.thread + +class StartSetup : ISetup { + + private var cloudApplicationType: CloudApplicationType? = null + + + @SetupQuestion(0, "Which application do you want to start?", ApplicationTypeSetupAnswerProvider::class) + fun setup(cloudApplicationType: CloudApplicationType) { + this.cloudApplicationType = cloudApplicationType + } + + @SetupFinished + fun onFinish() { + val cloudApplicationType = this.cloudApplicationType + checkNotNull(cloudApplicationType) { "Cloud application type was null after start setup." } + thread { + Launcher.instance.startApplication(cloudApplicationType) + } + } + + @SetupCancelled + fun onCancel() { + Launcher.instance.shutdown() + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/ApplicationTypeSetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/ApplicationTypeSetupAnswerProvider.kt new file mode 100644 index 000000000..1b19dc6cb --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/ApplicationTypeSetupAnswerProvider.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 21:19 + * @author Frederick Baier + */ +class ApplicationTypeSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): Collection { + return listOf("Manager", "Wrapper") + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/LanguageSetupAnswerProvider.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/LanguageSetupAnswerProvider.kt new file mode 100644 index 000000000..7229ce98a --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/setups/provider/LanguageSetupAnswerProvider.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.setups.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.setup.provider.ISetupAnswerProvider + +/** + * Created by IntelliJ IDEA. + * Date: 15.06.2020 + * Time: 21:19 + * @author Frederick Baier + */ +class LanguageSetupAnswerProvider : ISetupAnswerProvider { + + override fun getSuggestions(sender: ICommandSender): Collection { + return listOf("en", "de") + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/Launcher.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/Launcher.kt new file mode 100644 index 000000000..a2a39b639 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/Launcher.kt @@ -0,0 +1,246 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.startup + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.application.ApplicationStarter +import eu.thesimplecloud.launcher.application.CloudApplicationType +import eu.thesimplecloud.launcher.application.ICloudApplication +import eu.thesimplecloud.launcher.config.java.JavaVersion +import eu.thesimplecloud.launcher.config.java.JavaVersionConfigLoader +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.config.launcher.LauncherConfigLoader +import eu.thesimplecloud.launcher.console.ConsoleManager +import eu.thesimplecloud.launcher.console.ConsoleSender +import eu.thesimplecloud.launcher.console.command.CommandManager +import eu.thesimplecloud.launcher.console.setup.SetupManager +import eu.thesimplecloud.launcher.language.LanguageFileLoader +import eu.thesimplecloud.launcher.logging.LoggerProvider +import eu.thesimplecloud.launcher.screens.IScreenManager +import eu.thesimplecloud.launcher.screens.ScreenManagerImpl +import eu.thesimplecloud.launcher.setups.AutoIpSetup +import eu.thesimplecloud.launcher.setups.LanguageSetup +import eu.thesimplecloud.launcher.setups.StartSetup +import eu.thesimplecloud.launcher.updater.RunnerUpdater +import eu.thesimplecloud.launcher.updater.UpdateExecutor +import eu.thesimplecloud.loader.dependency.DependencyLoader +import java.io.File +import java.io.IOException +import java.net.URLClassLoader +import java.util.concurrent.Executors +import java.util.concurrent.ScheduledExecutorService +import kotlin.system.exitProcess + + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 06.09.2019 + * Time: 21:31 + */ +class Launcher(val launcherStartArguments: LauncherStartArguments) { + + companion object { + @JvmStatic + lateinit var instance: Launcher + private set + } + + private val launcherCloudModule = object : ICloudModule { + override fun onEnable() { + } + + override fun onDisable() { + } + } + + @Volatile + var isBaseLoaded = false + private set + + var activeApplication: ICloudApplication? = null + val screenManager: IScreenManager = ScreenManagerImpl() + val logger = LoggerProvider(screenManager) + val commandManager: CommandManager + val consoleSender = ConsoleSender() + val consoleManager: ConsoleManager + val setupManager = SetupManager(this) + private val launcherConfigLoader = LauncherConfigLoader() + private val javaVersionConfigLoader = JavaVersionConfigLoader() + val scheduler: ScheduledExecutorService = Executors.newScheduledThreadPool(1) + val currentClassLoader: ClassLoader = Thread.currentThread().contextClassLoader + var launcherConfig: LauncherConfig + private set + private val startedTime = System.currentTimeMillis() + + init { + instance = this + if (System.getProperty("simplecloud.version") == null) + System.setProperty("simplecloud.version", Launcher::class.java.`package`.implementationVersion) + Thread.setDefaultUncaughtExceptionHandler { _, cause -> + try { + this.logger.exception(cause) + } catch (e: Exception) { + println("An error occurred logging an exception") + println("Exception while logging:") + e.printStackTrace() + println("Exception to log:") + cause.printStackTrace() + } + } + System.setProperty("user.language", "en") + migrateOldLauncherFile() + + this.launcherConfig = this.launcherConfigLoader.loadConfig() + DirectoryPaths.paths = launcherConfig.directoryPaths + JavaVersion.paths = javaVersionConfigLoader.loadConfig() + this.commandManager = CommandManager() + this.consoleManager = ConsoleManager(this.commandManager, this.consoleSender) + } + + fun start() { + DependencyLoader.INSTANCE.disableLogger() + clearConsole() + if (!launcherStartArguments.disableAutoUpdater) { + if (executeUpdateIfAvailable()) { + return + } + } else { + this.logger.warning("Auto updater is disabled.") + } + this.commandManager.registerAllCommands( + launcherCloudModule, + this.currentClassLoader, + "eu.thesimplecloud.launcher.commands" + ) + this.consoleManager.startThread() + + if (LanguageFileLoader.isFirstStart) { + this.setupManager.queueSetup(LanguageSetup()) + } + if (!this.launcherConfigLoader.doesConfigFileExist()) + this.setupManager.queueSetup(AutoIpSetup()) + if (this.launcherStartArguments.startApplication == null) + this.setupManager.queueSetup(StartSetup()) + + this.setupManager.waitForAllSetups() + this.launcherStartArguments.startApplication?.let { startApplication(it) } + } + + private fun migrateOldLauncherFile() { + val jsonLib = JsonLib.fromJsonFile(File("launcher.json")) ?: return + if (jsonLib.getInt("startServicePort") != null) + return + jsonLib.append("startServicePort", 50000) + jsonLib.saveAsFile("launcher.json") + } + + private fun executeUpdateIfAvailable(): Boolean { + val updater = RunnerUpdater() + if (updater.isUpdateAvailable()) { + this.consoleSender.sendMessage("Found a new runner version: " + updater.getVersionToInstall()!!) + UpdateExecutor().executeUpdate(updater) + return true + } else { + this.consoleSender.sendMessage("You are running on the latest version of SimpleCloud.") + } + return false + } + + fun startApplication(cloudApplicationType: CloudApplicationType) { + this.isBaseLoaded = true + clearConsole() + logger.info("Starting ${cloudApplicationType.getApplicationName()}...") + ApplicationStarter().startApplication(cloudApplicationType) + } + + fun clearConsole() { + if (isWindows()) { + try { + ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: InterruptedException) { + e.printStackTrace() + } + } else { + print("\u001b[H\u001b[2J") + System.out.flush() + } + } + + fun executeCommand(command: String) { + if (command.isBlank()) return + this.commandManager.handleCommand(command, this.consoleSender) + } + + fun shutdown() { + activeApplication?.onDisable() + exitProcess(0) + } + + fun isWindows(): Boolean = System.getProperty("os.name").lowercase().contains("windows") + + fun getLauncherFile(): File { + if (System.getProperty("simplecloud.launcher.update-mode") != null) { + return File("launcher-update.jar") + } + return File(Launcher::class.java.protectionDomain.codeSource.location.toURI()) + } + + fun getBaseFile(): File { + return File("storage/base.jar") + } + + fun getNewClassLoaderWithLauncherAndBase(): URLClassLoader { + val launcherFileURL = this.getLauncherFile().toURI().toURL() + val currentContextClassLoader = Thread.currentThread().contextClassLoader + + return if (isBaseLoaded) { + val baseFileURL = this.getBaseFile().toURI().toURL() + URLClassLoader(arrayOf(baseFileURL, launcherFileURL), currentContextClassLoader) + } else { + URLClassLoader(arrayOf(launcherFileURL), currentContextClassLoader) + } + } + + fun isSnapshotBuild(): Boolean { + return System.getProperty("simplecloud.version").lowercase().contains("snapshot") + } + + fun getCurrentVersion(): String { + return System.getProperty("simplecloud.version") + } + + fun replaceLauncherConfig(config: LauncherConfig) { + this.launcherConfig = config + this.launcherConfigLoader.saveConfig(config) + } + + fun getUpTime(): Long { + return System.currentTimeMillis() - startedTime + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherMain.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherMain.kt new file mode 100644 index 000000000..147068064 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherMain.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.startup + +class LauncherMain { + companion object { + var specifiedArguments: Array? = null + } +} + +fun main(args: Array) { + LauncherMain.specifiedArguments = args + LauncherStartArguments().main(args) +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherStartArguments.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherStartArguments.kt new file mode 100644 index 000000000..867678150 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/startup/LauncherStartArguments.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.startup + +import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.parameters.options.associate +import com.github.ajalt.clikt.parameters.options.flag +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.types.enum +import eu.thesimplecloud.launcher.application.CloudApplicationType + +class LauncherStartArguments : CliktCommand() { + + val disableAutoUpdater: Boolean by option(help = "Disables the auto updater.").flag() + val startApplication: CloudApplicationType? by option(help = "Starts an application directly.").enum() + //--system-prop size=small + val wrapperRam: Map by option("--wrapper-ram").associate() + + override fun run() { + WrapperRamWriter(wrapperRam).write() + Launcher(this).start() + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/AbstractUpdater.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/AbstractUpdater.kt new file mode 100644 index 000000000..8324bb14b --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/AbstractUpdater.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.updater + +import eu.thesimplecloud.loader.dependency.DependencyResolver +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import org.eclipse.aether.artifact.DefaultArtifact +import java.io.File +import java.util.jar.JarFile + +abstract class AbstractUpdater( + private val groupId: String, + private val artifactId: String, + protected val updateFile: File +) : IUpdater { + + private var versionToInstall: String? = null + + private var wasVersionToInstallCalled: Boolean = false + + override fun getVersionToInstall(): String? { + if (!wasVersionToInstallCalled) { + this.wasVersionToInstallCalled = true + val aetherArtifact = DefaultArtifact("${groupId}:${artifactId}:(0,]") + this.versionToInstall = DependencyResolver(getRepositoryURL(), aetherArtifact) + .determineLatestVersion() + } + return this.versionToInstall + } + + override fun downloadJarsForUpdate() { + val latestVersion = getVersionToInstall() + ?: throw RuntimeException("Cannot perform update. Is the server down? (repo: ${getRepositoryURL()})") + val dependency = AdvancedCloudDependency(groupId, artifactId, latestVersion) + dependency.download(getRepositoryURL(), updateFile) + } + + fun getVersionFromManifestFile(file: File): String { + val jarFile = JarFile(file) + val version = jarFile.manifest.mainAttributes.getValue("Implementation-Version") + jarFile.close() + return version + } + + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/BaseUpdater.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/BaseUpdater.kt new file mode 100644 index 000000000..4e483c9aa --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/BaseUpdater.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.updater + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import java.io.File + +class BaseUpdater : AbstractUpdater( + "eu.thesimplecloud.simplecloud", + "simplecloud-base", + File(DirectoryPaths.paths.storagePath + "base.jar") +) { + + override fun getVersionToInstall(): String? { + return getCurrentLauncherVersion() + } + + override fun getCurrentVersion(): String { + //return empty string because it will be unequal to the newest base version + if (!this.updateFile.exists()) return "NOT_INSTALLED" + return getVersionFromManifestFile(this.updateFile) + } + + override fun executeJar() { + //do nothing + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/IUpdater.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/IUpdater.kt new file mode 100644 index 000000000..1e5fb91f2 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/IUpdater.kt @@ -0,0 +1,73 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.updater + +import eu.thesimplecloud.launcher.startup.Launcher + +interface IUpdater { + + /** + * Returns the latest version + */ + fun getVersionToInstall(): String? + + /** + * Returns the current version. + */ + fun getCurrentVersion(): String + + /** + * Returns whether an update is available + */ + fun isUpdateAvailable(): Boolean = + getCurrentVersion().isBlank() || (getVersionToInstall() != null && getVersionToInstall() != getCurrentVersion()) + + /** + * Downloads the jars needed to update + */ + fun downloadJarsForUpdate() + + /** + * Executes the jar to complete the update. + */ + fun executeJar() + + /** + * Returns the current launcher version + */ + fun getCurrentLauncherVersion(): String { + return System.getProperty("simplecloud.version") + } + + /** + * Returns the repository url to use + */ + fun getRepositoryURL(): String { + return if (Launcher.instance.isSnapshotBuild()) { + "https://repo.thesimplecloud.eu/artifactory/list/gradle-dev-local/" + } else { + "https://repo.thesimplecloud.eu/artifactory/list/gradle-release-local/" + } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/RunnerUpdater.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/RunnerUpdater.kt new file mode 100644 index 000000000..5fdd22693 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/RunnerUpdater.kt @@ -0,0 +1,105 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.updater + + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.runner.RunnerFileProvider +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import eu.thesimplecloud.runner.utils.WebContentLoader +import java.io.File +import java.net.URLClassLoader +import java.nio.file.Files +import java.nio.file.StandardCopyOption + +class RunnerUpdater : AbstractUpdater( + "eu.thesimplecloud.simplecloud", + "simplecloud-runner", + File("runner-update.jar") +) { + + private val dependencyLoaderFile = File("storage", "dependency-loader.jar") + + private var versionToInstall: String? = null + + override fun getCurrentVersion(): String { + return getCurrentLauncherVersion() + } + + override fun getVersionToInstall(): String? { + if (versionToInstall != null) return versionToInstall + val content = + WebContentLoader().loadContent("https://update.thesimplecloud.eu/latestVersion/${getCurrentVersion()}") + ?: return null + this.versionToInstall = JsonLib.fromJsonString(content).getString("latestVersion") + return this.versionToInstall + } + + override fun executeJar() { + val file = File("runner-update.jar") + val currentRunnerFile = RunnerFileProvider.RUNNER_FILE + val newClassLoader = URLClassLoader(arrayOf(file.toURI().toURL())) + Thread.currentThread().contextClassLoader = newClassLoader + Runtime.getRuntime().addShutdownHook(Thread { + Thread.sleep(200) + if (Launcher.instance.isWindows()) { + performWindowsUpdate(currentRunnerFile, file) + } else { + performLinuxUpdate(currentRunnerFile, file) + } + println("Update installed. Stopping in 5 seconds...") + Thread.sleep(5 * 1000) + }) + Launcher.instance.shutdown() + } + + private fun performWindowsUpdate(currentRunnerFile: File, updateRunnerFile: File) { + val updaterFile = File("storage/updater.jar") + val dependency = + AdvancedCloudDependency("eu.thesimplecloud.simplecloud", "simplecloud-updater", getVersionToInstall()!!) + dependency.download(getRepositoryURL(), updaterFile) + val processBuilder = ProcessBuilder( + "java", + "-jar", + "storage/updater.jar", + "300", + currentRunnerFile.absolutePath, + updateRunnerFile.absolutePath, + Launcher.instance.getLauncherFile().absolutePath, + this.dependencyLoaderFile.absolutePath + ) + processBuilder.directory(File(".")) + processBuilder.start() + } + + private fun performLinuxUpdate(currentRunnerFile: File, file: File) { + Files.move(file.toPath(), currentRunnerFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + deleteLauncherAndDependencyLoader() + } + + private fun deleteLauncherAndDependencyLoader() { + Launcher.instance.getLauncherFile().delete() + this.dependencyLoaderFile.delete() + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/UpdateExecutor.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/UpdateExecutor.kt new file mode 100644 index 000000000..0864c7039 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/updater/UpdateExecutor.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.updater + +class UpdateExecutor { + + fun executeUpdate(updater: IUpdater) { + updater.downloadJarsForUpdate() + updater.executeJar() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/FileCopier.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/FileCopier.kt new file mode 100644 index 000000000..267eb9cf9 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/FileCopier.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.utils + +import eu.thesimplecloud.api.directorypaths.DirectoryPaths +import eu.thesimplecloud.launcher.startup.Launcher +import org.apache.commons.io.FileUtils +import java.io.File +import java.io.IOException +import java.io.InputStream +import java.util.jar.JarFile + +class FileCopier { + + companion object { + + val classLoader = Launcher.instance.getNewClassLoaderWithLauncherAndBase() + + /** + * Copies a file outside this jar + */ + fun copyFileOutOfJar(fileDestination: File, filePathToCopy: String) { + val stream = FileCopier::class.java.getResourceAsStream(filePathToCopy) + ?: loadFromBaseJar(filePathToCopy) + + val parent = fileDestination.parentFile + parent?.mkdirs() + if (File(filePathToCopy).exists()) { + return + } + try { + fileDestination.createNewFile() + FileUtils.copyInputStreamToFile(stream, fileDestination) + } catch (e1: IOException) { + e1.printStackTrace() + } + + } + + private fun loadFromBaseJar(filePathToCopy: String): InputStream { + val jarFile = JarFile(DirectoryPaths.paths.storagePath + "base.jar") + //drop first "/" + val jarEntry = jarFile.getJarEntry(filePathToCopy.drop(1)) + return jarFile.getInputStream(jarEntry) + } + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/IpValidator.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/IpValidator.kt new file mode 100644 index 000000000..a208e9da8 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/IpValidator.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.utils + +import java.util.regex.Pattern + +class IpValidator { + + private val IPADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$" + + private val pattern = Pattern.compile(IPADDRESS_PATTERN) + + fun validate(ip: String): Boolean { + val matcher = pattern.matcher(ip) + return matcher.matches() + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/WebsiteContentLoader.kt b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/WebsiteContentLoader.kt new file mode 100644 index 000000000..a09698bc7 --- /dev/null +++ b/simplecloud-launcher/src/main/kotlin/eu/thesimplecloud/launcher/utils/WebsiteContentLoader.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.launcher.utils + +import java.io.BufferedReader +import java.io.InputStreamReader +import java.net.URL + +class WebsiteContentLoader { + + + fun loadContent(urlstring: String): String { + val url = URL(urlstring) + val reader = BufferedReader(InputStreamReader(url.openStream())) + + // write the output to stdout + var line = "" + reader.lines().forEach { line += it } + reader.close() + return line + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/resources/language/de.json b/simplecloud-launcher/src/main/resources/language/de.json new file mode 100644 index 000000000..952f0bbf4 --- /dev/null +++ b/simplecloud-launcher/src/main/resources/language/de.json @@ -0,0 +1,197 @@ +{ + "command.cloud.no-permission": "§cDu hast nicht die benötigte Berechtigung, um diesen Befehl auszuführen", + "command.player.no-permission": "§cDu hast nicht die benötigte Berechtigung, um diesen Befehl auszuführen", + "commandmanager.onlyconsole": "Dieser Befehl kann nur über die Konsole ausgeführt werden", + "commands.help.header": "Hilfe | Alle Befehle (%SIZE%)", + "commands.help.command": ">> %PATH% (%DESCRIPTION%)", + "commands.help.command.ingame": "§7>> %PATH%", + "ingame.no-fallback-server-found": "§cEs wurde kein Ausweichserver gefunden", + "ingame.no-permission": "§cDu hast nicht die benötigte Berechtigung, um diesen Server betreten zu können", + "ingame.service-not-registered": "§cDieser Server ist nicht in der Cloud registriert", + "ingame.service-in-maintenance": "§cDieser Server ist im Wartungsmodus", + "ingame.server-still-starting": "§cDieser Server startet noch", + "internalwrapper.setup.memory.finished": "Interner Wrapper erstellt", + "internalwrapper.setup.memory.question.memory.success": "Arbeitsspeicher gesetzt", + "internalwrapper.setup.memory.question.name": "Wie viel Arbeitsspeicher soll der Wrapper verwenden können? (Angaben in Megabyte [Base 2])", + "launcher.base.checking-for-updates": "Suche nach Updates für die Basis..", + "launcher.base.downloading-update": "Lade Basis Update herunter..", + "launcher.base.newest-version": "Du besitzt bereits die neuste Version", + "launcher.base.update-found": "Es wurde ein Basis Update gefunden: %VERSION% (aktuell: %CURRENT_VERSION%)", + "launcher.setup.auto-ip.ip-fetched": "Folgende IP-Adresse wurde erkannt: %IP%", + "launcher.setup.ip.ip-invalid": "Die angegebene IP-Adresse ist ungültig", + "launcher.setup.language.question": "Welche Sprache möchtest du verwenden? (en, de)", + "launcher.setup.start.question": "Möchtest du den Manager oder den Wrapper starten?", + "manager.command.copy.failed": "Kopiervorgang gescheitert: %CAUSE%", + "manager.command.copy.service-inactive": "Der angegebene Server ist inaktiv", + "manager.command.copy.start": "Kopiervorgang für %SERVICE% gestartet..", + "manager.command.copy.success": "Kopiervorgang erfolgreich abgeschlossen", + "manager.command.create.template.already-exist": "Das Template %NAME% existiert bereits", + "manager.command.create.template.name-too-long": "Der angegebene Name darf nicht länger als 17 Zeichen sein", + "manager.command.create.template.success": "Template %NAME% erstellt", + "manager.command.delete.group.not-exist": "Die Gruppe %NAME% existiert nicht", + "manager.command.delete.group.services-running": "Die Gruppe %NAME% konnte nicht gelöscht werden, da noch Server von dieser Gruppe laufen", + "manager.command.delete.group.success": "Die Gruppe %NAME% wurde gelöscht", + "manager.command.delete.service-version.not-exist": "Die angegebene Service-Version existiert nicht", + "manager.command.delete.service-version.still-in-use": "Diese Service-Version wird noch von Gruppen benutzt. Lösche diese zuerst.", + "manager.command.delete.service-version.deleted": "Service-Version %NAME% gelöscht", + "manager.command.delete.template.in-use.group": "Das Template %NAME% wird noch von registrierten Gruppen verwendet. Bitte lösche diese Gruppen zuerst", + "manager.command.delete.template.in-use.service": "Das Template %NAME% wird noch von registrierten Servern verwendet. Bitte stoppe diese Server zuerst", + "manager.command.delete.template.not-exist": "Das Template %NAME% existiert nicht", + "manager.command.delete.template.success": "Das Template %NAME% wurde gelöscht", + "manager.command.delete.wrapper.group-must-start": "Der Wrapper %NAME% konnte nicht gelöscht werden, da noch Gruppen existieren, die auf ihm Server starten", + "manager.command.delete.wrapper.not-exist": "Der Wrapper %NAME% existiert nicht", + "manager.command.delete.wrapper.services-running": "Der Wrapper %NAME% konnte nicht gelöscht werden, da noch Server auf ihm laufen", + "manager.command.edit.allowed-parameters": "Erlaubte Argumente sind:", + "manager.command.edit.group.invalid-value": "Ungültige Angabe. Erwarteter Typ: %TYPE%", + "manager.setup.service-versions.question.java.success": "Java Start Befehl gesetzt", + "manager.setup.service-versions.question.javaName": "Bitte geben den von dir bevorzugte Java-Namen an.", + "manager.setup.service-versions.question.java": "Bitte gebe die von dir bevorzugte Java-Version an. (java = Standard)", + "manager.command.edit.group.not-exist": "Die angegebene Gruppe existiert nicht", + "manager.command.edit.group.success": "Gruppeneditierung erfolgreich abgeschlossen", + "manager.command.edit.template.inheritance.add.already-added": "Das Template %NAME% erbt bereits von %OTHER_NAME%", + "manager.command.edit.template.inheritance.add.both-equal": "Ein Template kann nicht als Vererbung zu sich selbst hinzugefügt werden", + "manager.command.edit.template.inheritance.add.success": "Das Template %NAME% erbt nun von %OTHER_NAME%", + "manager.command.edit.template.inheritance.remove.not-added": "Das Template %NAME% erbt nicht von %OTHER_NAME%", + "manager.command.edit.template.inheritance.remove.success": "Das Template %NAME% erbt nicht mehr von %OTHER_NAME%", + "manager.command.edit.template.modules.add.already-added": "Das Modul %MODULE% wurde bereits dem Template %TEMPLATE% hinzugefügt", + "manager.command.edit.template.modules.add.success": "Das Modul %MODULE% wurde dem Template %TEMPLATE% erfolgreich hinzugefügt", + "manager.command.edit.template.modules.remove.not-added": "Das Modul %MODULE% wurde nicht dem Template %TEMPLATE% hinzugefügt", + "manager.command.edit.template.modules.remove.success": "Das Modul %MODULE% wurde von dem Template %TEMPLATE% entfernt", + "manager.command.edit.wrapper.invalid-value": "Ungültige Angabe. Erwarteter Typ: %TYPE%", + "manager.command.edit.wrapper.success": "Wrapperbearbeitung erfolgreich abgeschlossen", + "manager.command.edit.service.state.fail": "Dieser State kann nicht gesetzt werden", + "manager.command.edit.service.state.success": "State gesetzt", + "manager.command.edit.service.displayname.success": "Display Name gesetzt", + "manager.command.edit.service.maxplayers.success": "Maximale Spieler gesetzt", + "manager.command.execute.service-not-found": "§cServer nicht gefunden", + "manager.command.execute.success": "§aBefehl ausgeführt", + "manager.command.execute.usage": "§cBenutzung: execute ", + "manager.command.info.group.not-exist": "Die angegebene Gruppe existiert nicht", + "manager.command.info.onlinecount": "Spieleranzahl: %COUNT%", + "manager.command.info.player.not-exist": "Der angegebene Spieler existiert nicht", + "manager.command.info.service.not-exist": "Der angegebene Server existiert nicht", + "manager.command.info.wrapper.not-exist": "Der angegebene Wrapper existiert nicht", + "manager.command.reload.group-changed": "Es ist ein Fehler beim Neuladen der Gruppe %GROUP% aufgetreten, da sich der Name geändert hat", + "manager.command.reload.group-success": "Neuladen der Gruppe %GROUP% erfolgreich abgeschlossen", + "manager.command.reload.module.not-exists": "Das neuzuladende Modul existiert nicht", + "manager.command.reload.wrapper-changed": "Es ist ein Fehler beim Neuladen des Wrappers %WRAPPER% aufgetreten, da sich der Host geändert hat", + "manager.command.reload.wrapper-success": "Neuladen des Wrappers %WRAPPER% erfolgreich abgeschlossen", + "manager.command.reload.server.version": "Alle Server Versions wurden neu geladen.", + "manager.command.reload.jvm.arguments": "Alle Java Argumente wurden neu geladen.", + "manager.command.screen.list": "Zurzeit sind folgende Konsolen verfügbar:", + "manager.command.screen.not-exist": "Die angegebene Konsole existiert nicht", + "manager.command.shutdown.success": "Stoppe Server", + "manager.command.shutdowngroup.failure": "Zurzeit sind keine Server der Gruppe %GROUP% online", + "manager.command.shutdowngroup.success": "Stoppe alle Server der Gruppe %GROUP%", + "manager.command.start.success": "Es werden %COUNT% neue Server der Gruppe %GROUP% gestartet", + "manager.command.startstatic.group-not-static": "§cDie angegebene Gruppe ist §cnicht §estatisch", + "manager.command.startstatic.service-already-online": "§cDer angegebene Server ist §cbereits §7online", + "manager.command.startstatic.service-invalid": "§cDer angegebene Server ist ungültig", + "manager.command.startstatic.success": "Starte Server...", + "manager.connection.unknown-host": "Ein Client hat versucht, von einem unbekannten Host sich zu verbinden: %HOST%", + "manager.converted": "Umgewandelt von %PREVIOUS% zu %CURRENT%", + "manager.converting": "Wandle um von %PREVIOUS% zu %CURRENT%..", + "manager.disconnect.service": "Verbindung des Servers %SERVICE% wurde getrennt", + "manager.disconnect.wrapper": "Verbindung des Wrappers %WRAPPER% wurde getrennt", + "manager.login.service": "Verbindung zu Server %SERVICE% wurde aufgebaut", + "manager.login.wrapper": "Verbindung zu Wrapper %WRAPPER% wurde aufgebaut", + "manager.module.loaded": "Das Modul %NAME% von %AUTHOR% wurde geladen", + "manager.module.unload": "Das Modul %NAME% von %AUTHOR% wurde deaktiviert", + "manager.module.updated": "Das Modul %MODULE% wurde aktualisiert", + "manager.module.updating": "Das Modul %MODULE% wird aktualisiert..", + "manager.player.connected": "Der Spieler %PLAYER% hat sich verbunden. (%UUID%/%IP%/%PROXY%)", + "manager.player.disconnected": "Der Spieler %PLAYER% hat die Verbindung getrennt. (%UUID%/%IP%)", + "manager.server.listening": "Die Cloud läuft nun auf dem Port %PORT%", + "manager.server.stopped": "Ein Server wird nun gestoppt", + "manager.service.queued": "Der Server %SERVICE% ist nun in der Warteschlange", + "manager.service.start": "Der Wrapper %WRAPPER% wurde beauftragt, %SERVICE% zu starten", + "manager.service.stopped": "Der Server %SERVICE% wurde gestoppt", + "manager.setup.auto-ip.question": "Möchtest du deine IP-Adresse automatisch durch \"ipify.org\" erkennen lassen? (Das funktioniert nicht auf einer lokalen Maschine)", + "manager.setup.database-connection.host-invalid": "Der angegebene Hostname ist ungültig", + "manager.setup.database-connection.port-invalid": "Der angegebene Port ist ungültig", + "manager.setup.database-connection.question.database": "Bitte gib den Datenbanknamen an", + "manager.setup.database-connection.question.database.success": "Datenbankname gesetzt", + "manager.setup.database-connection.question.host": "Bitte gib den Hostnamen für die Datenbankverbindung an", + "manager.setup.database-connection.question.host.success": "Hostname gesetzt", + "manager.setup.database-connection.question.password": "Bitte gib das Passwort für die Datenbankverbindung an", + "manager.setup.database-connection.question.password.success": "Passwort gesetzt", + "manager.setup.database-connection.question.port": "Bitte gib den Port für die Datenbankverbindung an", + "manager.setup.database-connection.question.port.success": "Port gesetzt", + "manager.setup.database-connection.question.type": "Bitte gib den Typ der zu verwendenen Datenbank an", + "manager.setup.database-connection.question.type.success": "Typ gesetzt", + "manager.setup.database-connection.question.username": "Bitte gib den Benutzernamen für die Datenbankverbindung an", + "manager.setup.database-connection.question.username.success": "Benutzername gesetzt", + "manager.setup.ip.question": "Bitte gib die IP-Adresse für den Manager an", + "manager.setup.proxy-group.question.start-port": "Auf welchem Port sollen Proxys dieser Gruppe starten?", + "manager.setup.proxy-group.question.type": "Welche Proxy-Version soll diese Gruppe nutzen?", + "manager.setup.proxy-group.question.type.success": "Proxy-Version gesetzt", + "manager.setup.proxy-group.question.wrapper": "Auf welchem Wrapper sollen Server dieser Gruppe gestartet werden?", + "manager.setup.server-group.question.type.success": "Spigot-Version gesetzt", + "manager.setup.server-group.question.wrapper": "Auf welchem Wrapper sollen Server dieser Gruppe laufen? (Wird benötigt, wenn die zugehörige Gruppe statisch ist. Du kannst auch nichts angeben, sofern du möchtest, dass immer der Wrapper mit der wenigsten Auslastung verwendet werden soll.)", + "manager.setup.service-group.finished": "Die Gruppe %NAME% wurde erstellt", + "manager.setup.service-group.permission.success": "Die Berechtigung wurde gesetzt", + "manager.setup.service-group.priority.success": "Die Priorität wurde gesetzt", + "manager.setup.service-group.question.max-players": "Wie viele Spieler dürfen maximal Server dieser Gruppe betreten?", + "manager.setup.service-group.question.max-players.success": "Die maximale Spieleranzahl wurde gesetzt", + "manager.setup.service-group.question.max-players.too-low": "Die angegebene Anzahl von Spielern ist zu gering", + "manager.setup.service-group.question.maximum-online": "Wie viele Server sollen immer maximal online sein? (unendlich = -1)", + "manager.setup.service-group.question.maximum-online.success": "Die maximale Serveranzahl wurde gesetzt", + "manager.setup.service-group.question.maximum-online.too-low": "Die angegebene Zahl ist zu klein", + "manager.setup.service-group.question.memory": "Wie viel Arbeitsspeicher soll diese Gruppe haben? (Angaben in Megabyte [Base 2])", + "manager.setup.service-group.question.memory.success": "Die Arbeitsspeicherangabe wurde gesetzt", + "manager.setup.service-group.question.memory.too-low": "Die angegebene Arbeitsspeichermenge ist zu gering", + "manager.setup.service-group.question.minimum-online": "Wie viele Server sollen mindestens online sein? (SICHTBAR)", + "manager.setup.service-group.question.minimum-online.success": "Die minimale Serveranzahl wurde gesetzt", + "manager.setup.service-group.question.minimum-online.too-low": "Die angegebene Anzahl ist zu gering", + "manager.setup.service-group.question.name": "Welchen Namen soll diese Gruppe haben?", + "manager.setup.service-group.question.name.success": "Der Name wurde gesetzt", + "manager.setup.service-group.question.name.too-long": "Der angegebene Name ist zu lang", + "manager.setup.service-group.question.name.is-empty": "Der angegebene Name ist leer", + "manager.setup.service-group.question.percent": "Wie voll muss ein Server dieser Gruppe sein, damit automatisch ein neuer Server gestartet werden soll? (Angabe in Prozent)", + "manager.setup.service-group.question.percent.out-of-range": "Die angegebene Zahl befindet sich außerhalb des zulässigen Prozentbereiches", + "manager.setup.service-group.question.percent.success": "Die Prozentangabe wurde gesetzt", + "manager.setup.service-group.question.permission": "Welche Berechtigung müssen Spieler haben, um Server dieser Gruppe betreten zu dürfen? (Keine Angabe = keine Berechtigung nötig)", + "manager.setup.service-group.question.port.out-of-range": "Der angegebene Port befindet sich außerhalb des zulässigen Bereiches", + "manager.setup.service-group.question.port.success": "Der Start-Port wurde gesetzt", + "manager.setup.service-group.question.priority": "Welche Priorität soll diese Lobbygruppe haben? (0 = Standard)", + "manager.setup.service-group.question.priority.too-low": "Die angegebene Zahl ist zu klein", + "manager.setup.service-group.question.static": "Soll diese Servergruppe statisch sein?", + "manager.setup.service-group.question.template": "Welches Template soll diese Servergruppe benutzen? (create = Erstellt automatisch ein neues Template mit dem Gruppennamen)", + "manager.setup.service-group.question.template.created": "Das Template %TEMPLATE% wurde erstellt", + "manager.setup.service-group.question.template.not-exist": "Das angegebene Template existiert nicht", + "manager.setup.service-group.question.template.success": "Das Template wurde gesetzt", + "manager.setup.service-group.question.type": "Welche Serverversion soll diese Servergruppe nutzen?", + "manager.setup.service-versions.question.name": "Bitte geben den Namen der Version an", + "manager.setup.service-versions.question.name.success": "Name gesetzt", + "manager.setup.service-versions.question.apitype": "Bitte geben den API-Type dieser Version an", + "manager.setup.service-versions.question.apitype.success": "API-Type gesetzt", + "manager.setup.service-versions.question.paperclip": "Ist diese Version eine Paperclip? (yes/no)", + "manager.setup.service-versions.question.paperclip.success": "Paperclip-Status gesetzt", + "manager.setup.service-versions.question.url": "Bitte gebe die Donwload-URL dieser Version an", + "manager.setup.service-versions.question.url.invalid": "Die angegebene URL ist ungültig", + "manager.setup.service-versions.question.url.success": "URL gesetzt", + "manager.setup.service-versions.finished": "Service-Version %NAME% erstellt", + "manager.setup.wrapper.finished": "Der Wrapper %WRAPPER% wurde erstellt", + "manager.setup.wrapper.question.host": "Welche IP-Adresse soll für den Wrapper verwendet werden? (this = IP-Adresse dieses Systems)", + "manager.setup.wrapper.question.memory": "Wie viel Arbeitsspeicher soll dem Wrapper zugewiesen werden? (Angaben in Megabyte [Base 2])", + "manager.setup.wrapper.question.memory.success": "Die Arbeitsspeicherangabe wurde gesetzt", + "manager.setup.wrapper.question.name": "Welchen Namen soll der Wrapper haben?", + "manager.setup.wrapper.question.start-services": "Wie viele Server soll der Wrapper gleichzeitig starten?", + "manager.setup.wrapper.question.start-services.success": "Die Anzahl der gleichzeitig zu startenden Server wurde gesetzt", + "manager.setup.wrapper.question.start-services.too-low": "Die angegebene Zahl ist zu gering", + "manager.startup.loaded.groups": "Folgende Gruppen wurden geladen:", + "manager.startup.loaded.templates": "Folgende Templates wurden geladen:", + "manager.startup.loaded.wrappers": "Folgende Wrapper wurden geladen:", + "manager.templates.synchronization": "Die Templates werden mit dem Wrapper %WRAPPER% synchronisiert..", + "manager.templates.synchronization.complete": "Es wurden alle Templates mit dem Wrapper %WRAPPER% erfolgreich synchronisiert", + "wrapper.connected": "Zum Manager verbunden", + "wrapper.connection-failed": "Beim Verbindungsaufbau zum Manager ist ein Fehler aufgetreten. Neuer Versuch in fünf Sekunden..", + "wrapper.service.queued": "Der Server %NAME% ist nun in der Warteschlange", + "wrapper.service.starting": "Der Server %NAME% wird gestartet", + "wrapper.service.stopped": "Der Server %NAME% wurde gestoppt", + "wrapper.startup.template-client.help-message": "Wenn dein Manager nicht in diesem Verzeichnis läuft, lösche den Ordner \"storage/wrappers\" und starte danach den Wrapper neu", + "wrapper.startup.template-client.not-activated": "Es wurde ein Manager in diesem Verzeichnis erkannt. Es werden die Templates in diesem Verzeichnis benutzt.", + "wrapper.startup.template-client.using": "Nutze einen extra Client um Templates zu senden / empfangen", + "wrapper.template.received": "Die Templates wurden empfangen", + "wrapper.template.requesting": "Frage Templates an... (Timeout: 15 Minuten)" +} \ No newline at end of file diff --git a/simplecloud-launcher/src/main/resources/language/en.json b/simplecloud-launcher/src/main/resources/language/en.json new file mode 100644 index 000000000..9d3647571 --- /dev/null +++ b/simplecloud-launcher/src/main/resources/language/en.json @@ -0,0 +1,198 @@ +{ + "command.cloud.no-permission": "§cYou don't have the permission to execute this command", + "command.player.no-permission": "§cYou don't have the permission to execute this command", + "commandmanager.onlyconsole": "This command can only be executed via the console", + "commands.help.header": "Help | All commands (%SIZE%)", + "commands.help.command": ">> %PATH% (%DESCRIPTION%)", + "commands.help.command.ingame": "§7>> %PATH%", + "ingame.no-fallback-server-found": "§cNo fallback server found", + "ingame.no-permission": "§cYou don't have the permission to join this service", + "ingame.service-not-registered": "§cServer is not registered on the cloud", + "ingame.service-in-maintenance": "§cThis service is in maintenance", + "ingame.server-still-starting": "§cServer is still starting", + "internalwrapper.setup.memory.finished": "InternalWrapper created", + "internalwrapper.setup.memory.question.memory.success": "Memory set", + "internalwrapper.setup.memory.question.name": "How much memory shall the wrapper have? (value as megabyte [base 2])", + "launcher.base.checking-for-updates": "Checking for base updates..", + "launcher.base.downloading-update": "Downloading base update..", + "launcher.base.newest-version": "You are running the latest version", + "launcher.base.update-found": "Found base update %VERSION% (current:%CURRENT_VERSION%)", + "launcher.setup.auto-ip.ip-fetched": "Ip fetched: %IP%", + "launcher.setup.ip.ip-invalid": "The entered ip is invalid", + "launcher.setup.language.question": "Which language do you want to use? (en)", + "launcher.setup.start.question": "Do you want do start the Manager or the Wrapper?", + "manager.command.copy.failed": "Copying failed: %CAUSE%", + "manager.command.copy.service-inactive": "The specified service is inactive", + "manager.command.copy.start": "Copying service %SERVICE%..", + "manager.command.copy.success": "Service copied", + "manager.command.create.template.already-exist": "Template %NAME% does already exist", + "manager.setup.service-versions.question.java.success": "Java startup command set", + "manager.setup.service-versions.question.java": "Please specify which Java version you prefer. (java = default)", + "manager.setup.service-versions.question.javaName": "Please specify your preferred Java name.", + "manager.command.create.template.name-too-long": "The specified name must be shorter than 17 characters", + "manager.command.create.template.success": "Template %NAME% created", + "manager.command.delete.group.not-exist": "Group %NAME% does not exist", + "manager.command.delete.group.services-running": "Cannot delete group %NAME% because services of this group are still running", + "manager.command.delete.group.success": "Group %NAME% deleted", + "manager.command.delete.service-version.not-exist": "The specified Service-Version does not exist", + "manager.command.delete.service-version.still-in-use": "The specified Service-Version is still used by groups. Delete them first.", + "manager.command.delete.service-version.deleted": "Service-Version %NAME% deleted", + "manager.command.delete.template.in-use.group": "Template %NAME% is in use by registered service groups. Delete them first", + "manager.command.delete.template.in-use.service": "Template %NAME% is in use by registered services. Stop them first", + "manager.command.delete.template.not-exist": "Template %NAME% does not exist", + "manager.command.delete.template.success": "Template %NAME% deleted", + "manager.command.delete.wrapper.group-must-start": "Cannot delete wrapper %NAME% while groups are only able to start on it", + "manager.command.delete.wrapper.not-exist": "Wrapper %NAME% does not exist", + "manager.command.delete.wrapper.success": "The wrapper %NAME% has been successfully deleted", + "manager.command.delete.wrapper.services-running": "Cannot delete wrapper %NAME% while services are still running on it", + "manager.command.edit.allowed-parameters": "Allowed parameters are:", + "manager.command.edit.group.invalid-value": "Invalid value. Expected type: %TYPE%", + "manager.command.edit.group.not-exist": "The specified group does not exist", + "manager.command.edit.group.success": "Group edited", + "manager.command.edit.template.inheritance.add.already-added": "Template %NAME% is already inheriting from %OTHER_NAME%", + "manager.command.edit.template.inheritance.add.both-equal": "Cannot add a template as inheritance to itself", + "manager.command.edit.template.inheritance.add.success": "Template %NAME% is now inheriting from %OTHER_NAME%", + "manager.command.edit.template.inheritance.remove.not-added": "Template %NAME% is not inheriting from %OTHER_NAME%", + "manager.command.edit.template.inheritance.remove.success": "Template %NAME% is no longer inheriting from %OTHER_NAME%", + "manager.command.edit.template.modules.add.already-added": "Module %MODULE% is already added to template %TEMPLATE%", + "manager.command.edit.template.modules.add.success": "Added module %MODULE% to template %TEMPLATE%", + "manager.command.edit.template.modules.remove.not-added": "Module %MODULE% was not added to template %TEMPLATE%", + "manager.command.edit.template.modules.remove.success": "Module %MODULE% was removed from template %TEMPLATE%", + "manager.command.edit.wrapper.invalid-value": "Invalid value. Expected type: %TYPE%", + "manager.command.edit.wrapper.success": "Wrapper edited", + "manager.command.edit.service.state.fail": "Cannot set this state", + "manager.command.edit.service.state.success": "State set", + "manager.command.edit.service.displayname.success": "Display Name set", + "manager.command.edit.service.maxplayers.success": "Max players set", + "manager.command.execute.service-not-found": "§cService not found", + "manager.command.execute.success": "§aExecuted command", + "manager.command.execute.usage": "§cUsage: execute ", + "manager.command.info.group.not-exist": "The specified group does not exist", + "manager.command.info.onlinecount": "Online count: %COUNT%", + "manager.command.info.player.not-exist": "The specified player does not exist", + "manager.command.info.service.not-exist": "The specified service does not exist", + "manager.command.info.wrapper.not-exist": "The specified wrapper does not exist", + "manager.command.reload.group-changed": "Failed to reload group %GROUP% because the name has changed", + "manager.command.reload.group-success": "Reloaded group %GROUP%", + "manager.command.reload.module.not-exists": "Module to reload does not exists", + "manager.command.reload.wrapper-changed": "Failed to reload wrapper %WRAPPER% because the host has changed", + "manager.command.reload.wrapper-success": "Reloaded wrapper %WRAPPER%", + "manager.command.reload.server.version": "All server versions have been reloaded.", + "manager.command.reload.jvm.arguments": "All Java arguments have been reloaded.", + "manager.command.screen.list": "There are following screens available:", + "manager.command.screen.not-exist": "The specified screen does not exist", + "manager.command.shutdown.success": "Stopping service", + "manager.command.shutdowngroup.failure": "There are no running services of group %GROUP%", + "manager.command.shutdowngroup.success": "Stopping all services of group %GROUP%", + "manager.command.start.success": "Trying to start %COUNT% new services of group %GROUP%", + "manager.command.startstatic.group-not-static": "§cThe specified service group must be static", + "manager.command.startstatic.service-already-online": "§cThe specified service is already running", + "manager.command.startstatic.service-invalid": "§cThe specified service is invalid", + "manager.command.startstatic.success": "Starting service..", + "manager.connection.unknown-host": "A client connected from an unknown host: %HOST%", + "manager.converted": "Converted from %PREVIOUS% to %CURRENT%", + "manager.converting": "Converting from %PREVIOUS% to %CURRENT%..", + "manager.disconnect.service": "Service %SERVICE% disconnected", + "manager.disconnect.wrapper": "Wrapper %WRAPPER% disconnected", + "manager.login.service": "Service %SERVICE% logged in", + "manager.login.wrapper": "Wrapper %WRAPPER% logged in", + "manager.module.loaded": "Loaded module %NAME% by %AUTHOR%", + "manager.module.unload": "Unloaded module %NAME% by %AUTHOR%", + "manager.module.updated": "Updated module %MODULE%", + "manager.module.updating": "Updating module %MODULE%..", + "manager.player.connected": "Player %PLAYER% connected. (%UUID%/%IP%/%PROXY%)", + "manager.player.disconnected": "Player %PLAYER% disconnect. (%UUID%/%IP%)", + "manager.server.listening": "The cloud is now listening on port %PORT%", + "manager.server.stopped": "A server is now stopped", + "manager.service.queued": "Service %SERVICE% is now queued", + "manager.service.start": "Told Wrapper %WRAPPER% to start service %SERVICE%", + "manager.service.stopped": "Service %SERVICE% was stopped", + "manager.setup.auto-ip.question": "Do you want to automatically set up your ip via \"ipify.org\" (This does not work on your local machine)", + "manager.setup.database-connection.host-invalid": "The entered host is invalid", + "manager.setup.database-connection.port-invalid": "The entered port is invalid", + "manager.setup.database-connection.question.database": "Please provide the database name of the database", + "manager.setup.database-connection.question.database.success": "Database set", + "manager.setup.database-connection.question.host": "Please provide the host of your database", + "manager.setup.database-connection.question.host.success": "Host set", + "manager.setup.database-connection.question.password": "Please provide the password of the database", + "manager.setup.database-connection.question.password.success": "Password set", + "manager.setup.database-connection.question.port": "Please provide the port of the database", + "manager.setup.database-connection.question.port.success": "Port set", + "manager.setup.database-connection.question.type": "Please provide the type of your database", + "manager.setup.database-connection.question.type.success": "Type set", + "manager.setup.database-connection.question.username": "Please provide the username of the database", + "manager.setup.database-connection.question.username.success": "Username set", + "manager.setup.ip.question": "Please enter the ip of the manager", + "manager.setup.proxy-group.question.start-port": "On which port shall proxies of this group start?", + "manager.setup.proxy-group.question.type": "Which proxy shall the group use?", + "manager.setup.proxy-group.question.type.success": "Proxy version set", + "manager.setup.proxy-group.question.wrapper": "On which wrapper shall services of this group run?", + "manager.setup.server-group.question.type.success": "Spigot set", + "manager.setup.server-group.question.wrapper": "On which wrapper shall services of this group run? (Needed when the group is static. Otherwise you can leave it empty for the wrapper with the lowest workload.)", + "manager.setup.service-group.finished": "Group %NAME% created", + "manager.setup.service-group.permission.success": "Permission set", + "manager.setup.service-group.priority.success": "Priority set", + "manager.setup.service-group.question.max-players": "How many players shall be able to join the server at most?", + "manager.setup.service-group.question.max-players.success": "Max-Players set", + "manager.setup.service-group.question.max-players.too-low": "The specified amount of players is too low", + "manager.setup.service-group.question.maximum-online": "How many services shall be online at most? (unlimited = -1)", + "manager.setup.service-group.question.maximum-online.success": "Max-Online-Services set", + "manager.setup.service-group.question.maximum-online.too-low": "The specified number is too low", + "manager.setup.service-group.question.memory": "How much memory shall the server group have? (value as megabyte [base 2])", + "manager.setup.service-group.question.memory.success": "Memory set", + "manager.setup.service-group.question.memory.too-low": "The specified amount of memory is too low", + "manager.setup.service-group.question.minimum-online": "How many services shall always be online? (VISIBLE)", + "manager.setup.service-group.question.minimum-online.success": "Min-Online-Services set", + "manager.setup.service-group.question.minimum-online.too-low": "The specified number is too low", + "manager.setup.service-group.question.name": "Which name shall the group have?", + "manager.setup.service-group.question.name.success": "Name set", + "manager.setup.service-group.question.name.too-long": "The specified name is too long", + "manager.setup.service-group.question.name.is-empty": "The specified name is empty", + "manager.setup.service-group.question.percent": "How full shall a service of this server group be until a new service starts? (in percent)", + "manager.setup.service-group.question.percent.out-of-range": "The specified number is out of range", + "manager.setup.service-group.question.percent.success": "Percent to start a new service set", + "manager.setup.service-group.question.permission": "Which permission shall a player need to join this group? (leave it empty for no permission)", + "manager.setup.service-group.question.port.out-of-range": "The specified port is out of range", + "manager.setup.service-group.question.port.success": "Start-Port set", + "manager.setup.service-group.question.priority": "Which priority shall this lobby group have? (0 = default)", + "manager.setup.service-group.question.priority.too-low": "The specified number is too low", + "manager.setup.service-group.question.static": "Shall this server group be static?", + "manager.setup.service-group.question.template": "Which template shall the group use? (create = Creates a template with the group's name)", + "manager.setup.service-group.question.template.created": "Template %TEMPLATE% created", + "manager.setup.service-group.question.template.not-exist": "The specified template does not exist", + "manager.setup.service-group.question.template.success": "Template set", + "manager.setup.service-group.question.type": "Which server version shall the group use?", + "manager.setup.service-versions.question.name": "Please provide the name of the version", + "manager.setup.service-versions.question.name.success": "Name set", + "manager.setup.service-versions.question.apitype": "Please provide the API-Type of the version.", + "manager.setup.service-versions.question.apitype.success": "API-Type set", + "manager.setup.service-versions.question.paperclip": "Is this a paperclip file? (yes/no)", + "manager.setup.service-versions.question.paperclip.success": "Paperclip state set", + "manager.setup.service-versions.question.url": "Please provide the download url of this version", + "manager.setup.service-versions.question.url.invalid": "The specified URL is invalid", + "manager.setup.service-versions.question.url.success": "URL set", + "manager.setup.service-versions.finished": "Service version %NAME% created", + "manager.setup.wrapper.finished": "Wrapper %NAME% created", + "manager.setup.wrapper.question.host": "On which host starts the wrapper? (this = ip of this server)", + "manager.setup.wrapper.question.memory": "How much memory does the wrapper have? (value as megabyte [base 2])", + "manager.setup.wrapper.question.memory.success": "Memory set", + "manager.setup.wrapper.question.name": "Which name shall the wrapper have?", + "manager.setup.wrapper.question.start-services": "How much services shall the wrapper can start simultaneously?", + "manager.setup.wrapper.question.start-services.success": "Max simultaneously starting services set", + "manager.setup.wrapper.question.start-services.too-low": "The specified amount is too low", + "manager.startup.loaded.groups": "Loaded following groups:", + "manager.startup.loaded.templates": "Loaded following templates:", + "manager.startup.loaded.wrappers": "Loaded following wrappers:", + "manager.templates.synchronization": "Synchronizing templates with Wrapper %WRAPPER%..", + "manager.templates.synchronization.complete": "Synchronized templates with Wrapper %WRAPPER%", + "wrapper.connected": "Connected to the manager", + "wrapper.connection-failed": "Failed to connect to manager. Retrying in 5 seconds", + "wrapper.service.queued": "Service %NAME% is now queued", + "wrapper.service.starting": "Starting service %NAME%", + "wrapper.service.stopped": "Service %NAME% was stopped", + "wrapper.startup.template-client.help-message": "If your manager is not running in this directory delete the folder \"storage/wrappers\" and restart the wrapper", + "wrapper.startup.template-client.not-activated": "Detected that a manager is running in this directory. Using templates in this folder", + "wrapper.startup.template-client.using": "Using an extra client to receive / send templates", + "wrapper.template.received": "Templates received", + "wrapper.template.requesting": "Requesting templates... (Timeout: 15 Minutes)" +} \ No newline at end of file diff --git a/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/EmptyMockCloudAPIImpl.kt b/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/EmptyMockCloudAPIImpl.kt new file mode 100644 index 000000000..cde9f474f --- /dev/null +++ b/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/EmptyMockCloudAPIImpl.kt @@ -0,0 +1,98 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.BasicEventManager +import eu.thesimplecloud.api.eventapi.IEventManager +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.ILanguageManager +import eu.thesimplecloud.api.message.IMessageChannelManager +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.version.IServiceVersionHandler +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.sync.list.manager.ISynchronizedObjectListManager +import eu.thesimplecloud.api.sync.`object`.IGlobalPropertyHolder +import eu.thesimplecloud.clientserverapi.lib.bootstrap.ICommunicationBootstrap +import io.mockk.mockk + +open class EmptyMockCloudAPIImpl(val eventManager: BasicEventManager) : CloudAPI() { + override fun getCloudServiceGroupManager(): ICloudServiceGroupManager { + return mockk() + } + + override fun getCloudServiceManager(): ICloudServiceManager { + return mockk() + } + + override fun getCloudPlayerManager(): ICloudPlayerManager { + return mockk() + } + + override fun getEventManager(): IEventManager { + return eventManager + } + + override fun getCommandExecuteManager(): ICommandExecuteManager { + return mockk() + } + + override fun getGlobalPropertyHolder(): IGlobalPropertyHolder { + return mockk() + } + + override fun getThisSidesCommunicationBootstrap(): ICommunicationBootstrap { + return mockk() + } + + override fun getSynchronizedObjectListManager(): ISynchronizedObjectListManager { + throw UnsupportedOperationException() + } + + override fun getServiceVersionHandler(): IServiceVersionHandler { + return mockk() + } + + override fun getLanguageManager(): ILanguageManager { + return mockk() + } + + override fun getMessageChannelManager(): IMessageChannelManager { + return mockk() + } + + override fun getThisSidesName(): String { + return "" + } + + override fun getThisSidesNetworkComponent(): INetworkComponent { + return mockk() + } + + override fun getThisSidesCloudModule(): ICloudModule { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/launcher/external/ModuleListLoaderTest.kt b/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/launcher/external/ModuleListLoaderTest.kt new file mode 100644 index 000000000..990df06ec --- /dev/null +++ b/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/launcher/external/ModuleListLoaderTest.kt @@ -0,0 +1,130 @@ +package eu.thesimplecloud.launcher.external + +import eu.thesimplecloud.EmptyMockCloudAPIImpl +import eu.thesimplecloud.api.eventapi.BasicEventManager +import eu.thesimplecloud.launcher.exception.module.ModuleLoadException +import eu.thesimplecloud.launcher.external.module.* +import eu.thesimplecloud.launcher.external.module.handler.ModuleListLoader +import eu.thesimplecloud.launcher.external.module.handler.UnsafeModuleLoader +import io.mockk.* +import org.apache.commons.lang3.RandomStringUtils +import org.junit.Before +import org.junit.Test +import java.io.File + +/** + * Created by IntelliJ IDEA.T + * Date: 28.11.2020 + * Time: 11:37 + * @author Frederick Baier + */ +class ModuleListLoaderTest { + + private lateinit var moduleHandler: ModuleListLoader + + @Before + fun setUp() { + val eventManager = spyk() + EmptyMockCloudAPIImpl(eventManager) + every { eventManager.call(any(), any()) } returns Unit + mockkConstructor(UnsafeModuleLoader::class) + mockkConstructor(LoadedModule::class) + } + + @Test + fun testDependLoad() { + val content1 = generateLoadedModuleFileContent("Test2", listOf("Test1")) + val loadedModule = mockk() + every { anyConstructed().loadModule(any()) }.returns(loadedModule) + val content2 = generateLoadedModuleFileContent("Test1") + every { loadedModule.fileContent } returns content2.content + val modulesToLoad = listOf(content1, content2) + moduleHandler = ModuleListLoader( + modulesToLoad, + emptyList(), + { urls, name -> ModuleClassLoader(urls, ClassLoader.getSystemClassLoader(), name, null) }) + moduleHandler.loadModules() + + verify { anyConstructed().loadModule(content1) } + verify { anyConstructed().loadModule(content2) } + } + + @Test + fun testSoftDependLoad() { + val content1 = generateLoadedModuleFileContent("Test2", emptyList(), listOf("Test1")) + val loadedModule = mockk() + every { anyConstructed().loadModule(any()) }.returns(loadedModule) + val content2 = generateLoadedModuleFileContent("Test1") + every { loadedModule.fileContent } returns content2.content + val modulesToLoad = listOf(content1, content2) + moduleHandler = ModuleListLoader( + modulesToLoad, + emptyList(), + { urls, name -> ModuleClassLoader(urls, ClassLoader.getSystemClassLoader(), name, null) }) + moduleHandler.loadModules() + + verify { anyConstructed().loadModule(content1) } + verify { anyConstructed().loadModule(content2) } + } + + @Test(expected = ModuleLoadException::class) + fun testMissingDependency() { + val loadedModuleFileContent = generateLoadedModuleFileContent("Test", listOf("Test2")) + val modulesToLoad = listOf(loadedModuleFileContent) + moduleHandler = ModuleListLoader( + modulesToLoad, + emptyList(), + { urls, name -> ModuleClassLoader(urls, ClassLoader.getSystemClassLoader(), name, null) }) + moduleHandler.loadModules() + } + + @Test(expected = ModuleLoadException::class) + fun testRecursiveDependency() { + val content1 = generateLoadedModuleFileContent("Test2", listOf("Test1")) + val loadedModule = mockk() + every { anyConstructed().loadModule(any()) }.returns(loadedModule) + val content2 = generateLoadedModuleFileContent("Test1", listOf("Test2")) + every { loadedModule.fileContent } returns content2.content + val modulesToLoad = listOf(content1, content2) + moduleHandler = ModuleListLoader( + modulesToLoad, + emptyList(), + { urls, name -> ModuleClassLoader(urls, ClassLoader.getSystemClassLoader(), name, null) }) + moduleHandler.loadModules() + } + + + @Test(expected = ModuleLoadException::class) + fun testRecursiveDependencySoftDepend() { + val content1 = generateLoadedModuleFileContent("Test2", listOf("Test1")) + val loadedModule = mockk() + every { anyConstructed().loadModule(any()) }.returns(loadedModule) + val content2 = generateLoadedModuleFileContent("Test1", emptyList(), listOf("Test2")) + every { loadedModule.fileContent } returns content2.content + val modulesToLoad = listOf(content1, content2) + moduleHandler = ModuleListLoader( + modulesToLoad, + emptyList(), + { urls, name -> ModuleClassLoader(urls, ClassLoader.getSystemClassLoader(), name, null) }) + moduleHandler.loadModules() + } + + private fun generateLoadedModuleFileContent( + name: String, + moduleDepends: List = emptyList(), + moduleSoftDepends: List = emptyList() + ): LoadedModuleFileContent { + val fileContent = ModuleFileContent( + name, + RandomStringUtils.randomAlphabetic(20), + "eu.thesimplecloud.mockmodule.ModuleMain", + ModuleCopyType.NONE, + emptyList(), + emptyList(), + moduleDepends, + moduleSoftDepends + ) + return LoadedModuleFileContent(File(RandomStringUtils.randomAlphabetic(20) + ".jar"), fileContent, null) + } + +} \ No newline at end of file diff --git a/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/mockmodule/ModuleMain.kt b/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/mockmodule/ModuleMain.kt new file mode 100644 index 000000000..c18a216da --- /dev/null +++ b/simplecloud-launcher/src/test/kotlin/eu/thesimplecloud/mockmodule/ModuleMain.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.mockmodule + +import eu.thesimplecloud.api.external.ICloudModule + +class ModuleMain : ICloudModule { + override fun onEnable() { + } + + override fun onDisable() { + } +} \ No newline at end of file diff --git a/simplecloud-modules/build.gradle b/simplecloud-modules/build.gradle new file mode 100644 index 000000000..096565827 --- /dev/null +++ b/simplecloud-modules/build.gradle @@ -0,0 +1,22 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + diff --git a/simplecloud-modules/simplecloud-module-chat-tab/build.gradle b/simplecloud-modules/simplecloud-module-chat-tab/build.gradle new file mode 100644 index 000000000..cec2382d9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/build.gradle @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Chat+Tab.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-plugin")) + compileOnly(project(":simplecloud-launcher")) + compileOnly(project(":simplecloud-modules:simplecloud-module-permission")) + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + compileOnly 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT' + compileOnly 'net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT' + // The full Spigot server with no shadowing. Requires mavenLocal. + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind + compileOnly 'com.velocitypowered:velocity-api:3.1.1' + annotationProcessor 'com.velocitypowered:velocity-api:3.1.1' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/PrefixModule.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/PrefixModule.kt new file mode 100644 index 000000000..f996915c5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/PrefixModule.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.prefix.manager.config.ChatTabModuleConfigPersistence +import eu.thesimplecloud.module.prefix.manager.command.ChatTabCommand + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 12:51 + */ +class PrefixModule : ICloudModule { + + override fun onEnable() { + val chatTabConfig = ChatTabModuleConfigPersistence.load() + ChatTabModuleConfigPersistence.save(chatTabConfig) + + CloudAPI.instance.getGlobalPropertyHolder().setProperty("prefix-config", chatTabConfig) + Launcher.instance.commandManager.registerCommand(this, ChatTabCommand()) + } + + override fun onDisable() { + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/command/ChatTabCommand.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/command/ChatTabCommand.kt new file mode 100644 index 000000000..3102c7af3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/command/ChatTabCommand.kt @@ -0,0 +1,51 @@ +package eu.thesimplecloud.module.prefix.manager.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.ServiceGroupCommandSuggestionProvider +import eu.thesimplecloud.module.prefix.manager.config.ChatTabConfig +import java.util.* + +@Command(name = "chat-tab", CommandType.CONSOLE_AND_INGAME, "cloud.module.chat-tab") +class ChatTabCommand : ICommandHandler { + + @CommandSubPath("set ", "Sets the delay for the given group") + fun executeSetDelayWithGroup( + commandSender: ICommandSender, + @CommandArgument("group", ServiceGroupCommandSuggestionProvider::class) group: String, + @CommandArgument("delay") delay: String + ) { + + if (CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(group) == null) { + commandSender.sendProperty("module.chat-tab.command.chat-tab.group-not-exist") + return + } + + val config = CloudAPI.instance.getGlobalPropertyHolder().getProperty("prefix-config")?.getValue() ?: return + config.delay[group] = delay.toLongOrNull() ?: 0L + config.update() + + commandSender.sendProperty("module.chat-tab.command.chat-tab.delay-set-success", group, delay) + } + + @CommandSubPath("set ", "Sets the delay for the current group you're online on") + fun executeSetDelayWithPlayerGroup( + commandSender: ICommandSender, + @CommandArgument("delay") delay: String + ) { + + if (commandSender !is ICloudPlayer) { + commandSender.sendProperty("module.chat-tab.command.chat-tab.no-player") + return + } + + executeSetDelayWithGroup(commandSender, commandSender.getConnectedServer()!!.getGroupName(), delay) + } +} + diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabConfig.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabConfig.kt new file mode 100644 index 000000000..a44f4591a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabConfig.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.manager.config + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 17:01 + * @author Frederick Baier + */ +class ChatTabConfig( + val chatFormat: String = "%PLAYER% §8» §7%MESSAGE%", + val informationList: List = listOf(TablistInformation()), + val disabledServerGroups: List = emptyList(), + val delay: MutableMap = mutableMapOf( + Pair("Lobby", 0L) + ) +) { + + fun update() { + property = CloudAPI.instance.getGlobalPropertyHolder().setProperty("prefix-config", this) + ChatTabModuleConfigPersistence.save(this) + } + + companion object { + + @Volatile + private var property: IProperty? = null + + fun getConfig(): ChatTabConfig { + if (this.property == null) { + this.property = + CloudAPI.instance.getGlobalPropertyHolder().requestProperty("prefix-config") + .getBlocking() + } + return this.property!!.getValue() + } + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabModuleConfigPersistence.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabModuleConfigPersistence.kt new file mode 100644 index 000000000..902f9369a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/ChatTabModuleConfigPersistence.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.manager.config + +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 17:11 + * @author Frederick Baier + */ +object ChatTabModuleConfigPersistence { + + private val configFile = File("modules/chat+tablist/config.json") + + fun save(chatTabConfig: ChatTabConfig) { + JsonLib.fromObject(chatTabConfig).saveAsFile(configFile) + } + + fun load(): ChatTabConfig { + if (!configFile.exists()) return createDefaultConfig() + return JsonLib.fromJsonFile(configFile)!!.getObject(ChatTabConfig::class.java) + } + + private fun createDefaultConfig(): ChatTabConfig { + return ChatTabConfig() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/TablistInformation.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/TablistInformation.kt new file mode 100644 index 000000000..e35e0cecc --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/manager/config/TablistInformation.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.manager.config + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 13:38 + */ +data class TablistInformation( + val groupName: String = "default", + val color: String = "GREEN", + val prefix: String = "§7", + val suffix: String = "", + val priority: Int = 99 +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/bungee/BungeePluginMain.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/bungee/BungeePluginMain.kt new file mode 100644 index 000000000..02fbca525 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/bungee/BungeePluginMain.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.bungee + +import net.md_5.bungee.api.plugin.Plugin + +/** + * @author KxmischesDomi | https://github.com/kxmischesdomi + */ +class BungeePluginMain : Plugin() { + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/BukkitPluginMain.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/BukkitPluginMain.kt new file mode 100644 index 000000000..294896d14 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/BukkitPluginMain.kt @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.spigot + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.module.prefix.manager.config.ChatTabConfig +import eu.thesimplecloud.module.prefix.service.spigot.listener.ChatListener +import eu.thesimplecloud.module.prefix.service.spigot.listener.CloudListener +import eu.thesimplecloud.module.prefix.service.spigot.listener.JoinListener +import eu.thesimplecloud.module.prefix.service.tablist.TablistHelper +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import org.bukkit.plugin.java.JavaPlugin + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 13:34 + */ +class BukkitPluginMain : JavaPlugin() { + + override fun onEnable() { + + val groupName = CloudPlugin.instance.thisService().getGroupName() + if (ChatTabConfig.getConfig().disabledServerGroups.contains(groupName)) { + Bukkit.getLogger().info("[SimpleCloud] The Chat+Tab module is deactivated on this service!") + Bukkit.getPluginManager().disablePlugin(this) + return + } + + TablistHelper.load() + + Bukkit.getPluginManager().registerEvents(JoinListener(this), this) + Bukkit.getPluginManager().registerEvents(ChatListener(), this) + + CloudAPI.instance.getEventManager() + .registerListener(CloudAPI.instance.getThisSidesCloudModule(), CloudListener()) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/ChatListener.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/ChatListener.kt new file mode 100644 index 000000000..ed77979e3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/ChatListener.kt @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.spigot.listener + +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.prefix.manager.config.ChatTabConfig +import eu.thesimplecloud.module.prefix.manager.config.TablistInformation +import eu.thesimplecloud.module.prefix.service.tablist.TablistHelper +import org.bukkit.ChatColor +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.AsyncPlayerChatEvent + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 15:36 + */ +class ChatListener : Listener { + + @EventHandler + fun handleJoin(event: AsyncPlayerChatEvent) { + val player = event.player + event.message = event.message.replace("%", "%%") + + val permissionPlayer = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(player.uniqueId) ?: return + val canWriteColored = event.player.hasPermission("cloud.module.chat.color") + val tablistInformation = TablistHelper.getTablistInformationByUUID(player.uniqueId) ?: return + val format = ChatColor.translateAlternateColorCodes('&', ChatTabConfig.getConfig().chatFormat) + .replace("%PLAYER%", buildPrompt(tablistInformation)) + .replace("%NAME%", event.player.name) + .replace("%PRIORITY%", tablistInformation.priority.toString()) + .replace("%PREFIX%", ChatColor.translateAlternateColorCodes('&', tablistInformation.prefix)) + .replace("%SUFFIX%", ChatColor.translateAlternateColorCodes('&', tablistInformation.suffix)) + .replace("%COLOR%", tablistInformation.color) + .replace("%COLOR_CODE%", ChatColor.valueOf(tablistInformation.color).toString()) + .replace( + "%MESSAGE%", + if (canWriteColored) ChatColor.translateAlternateColorCodes('&', event.message) else "%2\$s" + ) + .replace("%GROUP%", permissionPlayer.getHighestPermissionGroup().getName()) + + event.format = format + } + + private fun buildPrompt(information: TablistInformation): String { + return information.prefix + ChatColor.valueOf(information.color).toString() + "%1\$s" + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/CloudListener.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/CloudListener.kt new file mode 100644 index 000000000..fb8f90cb8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/CloudListener.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.spigot.listener + +import eu.thesimplecloud.api.event.sync.`object`.GlobalPropertyUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.module.permission.event.player.PermissionPlayerUpdatedEvent +import eu.thesimplecloud.module.prefix.service.tablist.TablistHelper +import org.bukkit.Bukkit + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 16:24 + */ +class CloudListener : IListener { + + @CloudEventHandler + fun handlePermissionUpdate(event: PermissionPlayerUpdatedEvent) { + val player = Bukkit.getPlayer(event.player.getUniqueId()) ?: return + TablistHelper.updateScoreboardForAllPlayers() + } + + @CloudEventHandler + fun handlePropertyChange(event: GlobalPropertyUpdatedEvent) { + if (event.propertyName == "prefix-config") { + TablistHelper.load() + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/JoinListener.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/JoinListener.kt new file mode 100644 index 000000000..c7de13444 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/spigot/listener/JoinListener.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.spigot.listener + +import eu.thesimplecloud.module.prefix.manager.config.ChatTabConfig +import eu.thesimplecloud.module.prefix.service.spigot.BukkitPluginMain +import eu.thesimplecloud.module.prefix.service.tablist.TablistHelper +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerJoinEvent + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 15:36 + */ +class JoinListener(val plugin: BukkitPluginMain) : Listener { + + @EventHandler + fun handleJoin(event: PlayerJoinEvent) { + + Bukkit.getScheduler().runTaskLater(plugin, Runnable { + TablistHelper.updateScoreboardForAllPlayers() + }, ChatTabConfig.getConfig().delay[CloudPlugin.instance.thisService().getGroupName()] ?: 0L) + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/ProxyTablistHelper.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/ProxyTablistHelper.kt new file mode 100644 index 000000000..d5b42b568 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/ProxyTablistHelper.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.tablist + +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.prefix.manager.config.ChatTabConfig +import eu.thesimplecloud.module.prefix.manager.config.TablistInformation +import java.util.* + +/** + * @author KxmischesDomi | https://github.com/kxmischesdomi + */ +object ProxyTablistHelper { + + fun getTablistInformationByUUID(uuid: UUID): TablistInformation? { + val permissionPlayer = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(uuid) ?: return null + + val informationList = ChatTabConfig.getConfig().informationList + val tablistInformation = informationList.sortedBy { it.priority }.first { + permissionPlayer.hasPermissionGroup(it.groupName) + } + + return tablistInformation + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/TablistHelper.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/TablistHelper.kt new file mode 100644 index 000000000..2356559f9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/tablist/TablistHelper.kt @@ -0,0 +1,111 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.tablist + +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.prefix.manager.config.ChatTabConfig +import eu.thesimplecloud.module.prefix.manager.config.TablistInformation +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import org.bukkit.scoreboard.Scoreboard +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.12.2020 + * Time: 15:11 + */ +object TablistHelper { + + fun load() { + val scoreboard = Bukkit.getScoreboardManager()?.mainScoreboard ?: return + + initScoreboard(scoreboard) + + Bukkit.getOnlinePlayers().forEach { + updateScoreboardForPlayer(it) + } + } + + private fun initScoreboard(scoreboard: Scoreboard) { + ChatTabConfig.getConfig().informationList.forEach { + val team = scoreboard.getTeam(it.priority.toString()) ?: scoreboard.registerNewTeam(it.priority.toString()) + + val chatColor = ChatColor.valueOf(it.color) + + team.prefix = ChatColor.translateAlternateColorCodes('&', it.prefix) + chatColor.toString() + team.suffix = ChatColor.translateAlternateColorCodes('&', it.suffix) + + try { + team.color = chatColor + } catch (_: NoSuchMethodException) { + } catch (_: NoSuchMethodError) { + } + } + } + + fun updateScoreboardForAllPlayers() { + Bukkit.getOnlinePlayers().forEach { + updateScoreboardForPlayer(it) + } + } + + fun updateScoreboardForPlayer(player: Player) { + val scoreboard = player.scoreboard + initScoreboard(scoreboard) + Bukkit.getOnlinePlayers().forEach { setPlayerInScoreboard(it, scoreboard) } + } + + private fun setPlayerInScoreboard(player: Player, scoreboard: Scoreboard) { + + scoreboard.teams.forEach { + it.removeEntry(player.name) + } + + val tablistInformation = getTablistInformationByPlayer(player) ?: return + val teamName = tablistInformation.priority.toString() + val team = scoreboard.getTeam(teamName) ?: return + + team.addEntry(player.name) + } + + fun getTablistInformationByPlayer(player: Player): TablistInformation? { + return getTablistInformationByUUID(player.uniqueId) + } + + fun getTablistInformationByUUID(uuid: UUID): TablistInformation? { + val permissionPlayer = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(uuid) + ?: return null + + val informationList = ChatTabConfig.getConfig().informationList + val tablistInformation = informationList.sortedBy { it.priority }.first { + permissionPlayer.hasPermissionGroup(it.groupName) + } + + return tablistInformation + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/velocity/VelocityPluginMain.kt b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/velocity/VelocityPluginMain.kt new file mode 100644 index 000000000..a31d2dc5a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/kotlin/eu/thesimplecloud/module/prefix/service/velocity/VelocityPluginMain.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.prefix.service.velocity + +import com.google.inject.Inject +import com.velocitypowered.api.plugin.Dependency +import com.velocitypowered.api.plugin.Plugin +import com.velocitypowered.api.proxy.ProxyServer + +/** + * @author KxmischesDomi | https://github.com/kxmischesdomi + */ +@Plugin(id = "simplecloud_prefix", dependencies = [Dependency(id = "simplecloud_plugin")]) +class VelocityPluginMain @Inject constructor(val proxyServer: ProxyServer) { + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/bungee.yml b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/bungee.yml new file mode 100644 index 000000000..d265b763d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/bungee.yml @@ -0,0 +1,6 @@ +name: SimpleCloud-Chat-Tab +version: 1.0 +author: KxmischesDomi +depend: [ SimpleCloud-Plugin ] + +main: eu.thesimplecloud.module.prefix.service.bungee.BungeePluginMain \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/de.json new file mode 100644 index 000000000..8ba284441 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/de.json @@ -0,0 +1,6 @@ +{ + "module.chat-tab.command.chat-tab.group-not-exist": "§cDie Gruppe wurde nicht gefunden.", + "module.chat-tab.command.chat-tab.delay-set-success": "§7Setze die Verzögerung für %SERVICE% auf %DELAY% ticks.", + "module.chat-tab.command.chat-tab.no-player": "§cHierfür musst du ein Spieler sein.", + "module.chat-tab.command.chat-tab.get-group-failed": "§cKonnte die Gruppe nicht finden, auf dem du online bist." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/en.json new file mode 100644 index 000000000..31cdd0fb5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/languages/en.json @@ -0,0 +1,6 @@ +{ + "module.chat-tab.command.chat-tab.group-not-exist": "§cGroup not found.", + "module.chat-tab.command.chat-tab.delay-set-success": "§7Set the delay for %SERVICE% to %DELAY% ticks.", + "module.chat-tab.command.chat-tab.no-player": "§cYou have to be a player to do this.", + "module.chat-tab.command.chat-tab.get-group-failed": "§cCouldn't find the group you're online on." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/module.json new file mode 100644 index 000000000..403466e4e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Chat+Tab", + "author": "Fllip", + "mainClass": "eu.thesimplecloud.module.prefix.manager.PrefixModule", + "moduleCopyType": "ALL", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/plugin.yml b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/plugin.yml new file mode 100644 index 000000000..81e8fa542 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/plugin.yml @@ -0,0 +1,7 @@ +name: SimpleCloud-Chat-Tab +version: 1.0 +author: Fllip + +main: eu.thesimplecloud.module.prefix.service.spigot.BukkitPluginMain + +depend: [ SimpleCloud-Plugin ] diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/updater.json new file mode 100644 index 000000000..e3c52737b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-chat-tab", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/velocity-plugin.json b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/velocity-plugin.json new file mode 100644 index 000000000..99c619797 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-chat-tab/src/main/resources/velocity-plugin.json @@ -0,0 +1,9 @@ +{ + "id": "simplecloud_chat_tab", + "name": "SimpleCloud-Chat-Tab", + "version": "1.0", + "authors": [ + "KxmischesDomi" + ], + "main": "eu.thesimplecloud.module.prefix.service.velocity.VelocityPluginMain" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/build.gradle b/simplecloud-modules/simplecloud-module-cloudflare/build.gradle new file mode 100644 index 000000000..918c061ce --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/build.gradle @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-CloudFlare.jar") +} + +dependencies { + api 'com.github.robinbraemer:cloudflareapi:1.3.3' + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-plugin")) + compileOnly(project(":simplecloud-launcher")) + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/CloudFlareModule.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/CloudFlareModule.kt new file mode 100644 index 000000000..50bf385f1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/CloudFlareModule.kt @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.cloudflare.config.domain.DomainConfigLoader +import eu.thesimplecloud.module.cloudflare.config.proxy.ProxyConfig +import eu.thesimplecloud.module.cloudflare.config.proxy.ProxyConfigLoader +import eu.thesimplecloud.module.cloudflare.domain.CloudFlareDomainHelper +import eu.thesimplecloud.module.cloudflare.listener.CloudFlareSingleGroupListener + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 27.02.2020 + * Time: 17:31 + */ +class CloudFlareModule : ICloudModule { + + private val domainConfigs = DomainConfigLoader().loadAll() + private val proxyConfigs = ProxyConfigLoader().loadAll() + private val domainHelpers = domainConfigs.map { CloudFlareDomainHelper(it) } + + override fun onEnable() { + proxyConfigs.forEach { + Launcher.instance.consoleSender.sendProperty("module.cloudflare.proxy-config.loaded", it.targetProxyGroup) + } + + domainHelpers.forEach { cloudFlareHelper -> + val config = cloudFlareHelper.config + if (config.email == "me@example.com") return@forEach + cloudFlareHelper.isCloudFlareConfiguredCorrectly().thenAccept { + if (it) { + registerAllRunningServices(cloudFlareHelper) + CloudAPI.instance.getEventManager() + .registerListener(this, CloudFlareSingleGroupListener(cloudFlareHelper, proxyConfigs)) + cloudFlareHelper.createARecordsForWrappersIfNotExist( + CloudAPI.instance.getWrapperManager().getAllCachedObjects() + ) + Launcher.instance.consoleSender.sendProperty("module.cloudflare.domain.active", config.domain) + } else { + Launcher.instance.consoleSender.sendProperty("module.cloudflare.domain.invalid", config.domain) + } + } + } + } + + private fun registerAllRunningServices(cloudFlareHelper: CloudFlareDomainHelper) { + val proxyConfigs = getAllProxyConfigsByDomain(cloudFlareHelper.config.domain) + proxyConfigs.forEach { registerAllServicesByProxyConfig(cloudFlareHelper, it) } + } + + private fun registerAllServicesByProxyConfig(cloudFlareHelper: CloudFlareDomainHelper, proxyConfig: ProxyConfig) { + val group = + CloudAPI.instance.getCloudServiceGroupManager().getProxyGroupByName(proxyConfig.targetProxyGroup) ?: return + group.getAllServices().filter { it.isOnline() }.forEach { cloudFlareHelper.createSRVRecord(it, proxyConfig) } + } + + private fun getAllProxyConfigsByDomain(domain: String): List { + return this.proxyConfigs.filter { it.domain == domain } + } + + override fun onDisable() { + domainHelpers.forEach { it.deleteAllSRVRecordsAndWait() } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfig.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfig.kt new file mode 100644 index 000000000..afcc141df --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfig.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare.config.domain + +import eu.thesimplecloud.api.utils.Nameable + +/** + * Created by IntelliJ IDEA. + * Date: 15.12.2020 + * Time: 20:51 + * @author Frederick Baier + */ +class DomainConfig( + val domain: String = "example.com", + val email: String = "me@example.com", + val apiToken: String = "", + val zoneId: String = "" +) : Nameable { + override fun getName(): String { + return this.domain + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfigLoader.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfigLoader.kt new file mode 100644 index 000000000..0614fffb8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/domain/DomainConfigLoader.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare.config.domain + +import eu.thesimplecloud.api.config.AbstractMultipleConfigLoader +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 14.12.2020 + * Time: 17:43 + * @author Frederick Baier + */ +class DomainConfigLoader : AbstractMultipleConfigLoader( + DomainConfig::class.java, + File("modules/cloudflare/domains/"), + listOf(DomainConfig()), + true +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfig.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfig.kt new file mode 100644 index 000000000..28a4b6387 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfig.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare.config.proxy + +import eu.thesimplecloud.api.utils.Nameable + +/** + * Created by IntelliJ IDEA. + * Date: 15.12.2020 + * Time: 20:52 + * @author Frederick Baier + */ +class ProxyConfig( + val targetProxyGroup: String = "Proxy", + val domain: String = "example.com", + val subDomain: String = "@" +) : Nameable { + override fun getName(): String { + return this.targetProxyGroup + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfigLoader.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfigLoader.kt new file mode 100644 index 000000000..16905de18 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/config/proxy/ProxyConfigLoader.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare.config.proxy + +import eu.thesimplecloud.api.config.AbstractMultipleConfigLoader +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 14.12.2020 + * Time: 17:43 + * @author Frederick Baier + */ +class ProxyConfigLoader : AbstractMultipleConfigLoader( + ProxyConfig::class.java, + File("modules/cloudflare/proxies/"), + listOf(ProxyConfig()), + true +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/domain/CloudFlareDomainHelper.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/domain/CloudFlareDomainHelper.kt new file mode 100644 index 000000000..164854d14 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/domain/CloudFlareDomainHelper.kt @@ -0,0 +1,168 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare.domain + +import eu.roboflax.cloudflare.CloudflareAccess +import eu.roboflax.cloudflare.CloudflareRequest +import eu.roboflax.cloudflare.constants.Category +import eu.roboflax.cloudflare.objects.dns.DNSRecord +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.combineAllPromises +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.cloudflare.config.domain.DomainConfig +import eu.thesimplecloud.module.cloudflare.config.proxy.ProxyConfig +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentHashMap + +/** + * Created by IntelliJ IDEA. + * Date: 13.12.2020 + * Time: 22:42 + * @author Frederick Baier + */ + +class CloudFlareDomainHelper( + val config: DomainConfig +) { + + private val cfAccess = CloudflareAccess(config.apiToken, config.email) + + private val serviceToDNSId = ConcurrentHashMap() + + fun isCloudFlareConfiguredCorrectly(): CompletableFuture { + val request = CloudflareRequest(Category.SSL_VERIFICATION, cfAccess) + .identifiers(config.zoneId) + val future = request.sendAsync() + return future.thenApply { it.errors.isEmpty() } + } + + fun createARecordsForWrappersIfNotExist(wrappers: List) { + val request = CloudflareRequest(Category.LIST_DNS_RECORDS, cfAccess) + .identifiers(config.zoneId) + + val records: List = request.asObjectList(DNSRecord::class.java).`object` + wrappers.forEach { wrapper -> + checkARecord(wrapper, records) + } + } + + private fun checkARecord(wrapper: IWrapperInfo, records: List) { + val wrapperRecord = + records.firstOrNull { it.name.equals(getFullDomainByWrapper(wrapper), true) && it.type == "A" } + if (wrapperRecord == null) { + createARecord(wrapper) + return + } + if (wrapperRecord.content != wrapper.getHost()) { + deleteRecord(wrapperRecord.id) + createARecord(wrapper) + } + } + + fun deleteAllSRVRecordsAndWait() { + val clonedKeys = HashSet(this.serviceToDNSId.keys) + clonedKeys.map { deleteSRVRecord(it) }.combineAllPromises().syncUninterruptibly() + } + + fun deleteSRVRecord(service: ICloudService): ICommunicationPromise { + val id = this.serviceToDNSId[service] ?: return CommunicationPromise.UNIT_PROMISE + this.serviceToDNSId.remove(service) + return deleteRecord(id) + } + + fun deleteRecord(id: String): ICommunicationPromise { + return CommunicationPromise.runAsync { + val request = CloudflareRequest(Category.DELETE_DNS_RECORD, cfAccess) + .identifiers(config.zoneId, id) + request.send() + return@runAsync + } + } + + fun createSRVRecord(service: ICloudService, proxyConfig: ProxyConfig): ICommunicationPromise { + return CommunicationPromise.runAsync { + val request = CloudflareRequest(Category.CREATE_DNS_RECORD, cfAccess) + .identifiers(config.zoneId) + .body(createSRVRecordBody(service, proxyConfig).jsonElement) + val response = request.asObject(DNSRecord::class.java) + if (response.errors.isNotEmpty()) { + Launcher.instance.logger.warning("Error creating SRV record:") + Launcher.instance.logger.warning(response.errors.toString()) + } else { + val id = response.`object`.id + serviceToDNSId[service] = id + } + } + } + + private fun createARecord(wrapper: IWrapperInfo) { + val request = CloudflareRequest(Category.CREATE_DNS_RECORD, cfAccess) + .identifiers(config.zoneId) + .body(createARecordBody(wrapper).jsonElement) + val response = request.send() + if (response.errors.isNotEmpty()) { + Launcher.instance.logger.warning("Error creating A record:") + Launcher.instance.logger.warning(response.errors.toString()) + } + } + + private fun createARecordBody(wrapper: IWrapperInfo): JsonLib { + return JsonLib.empty() + .append("type", "A") + .append("ttl", 1) + .append("proxied", false) + .append("name", getFullDomainByWrapper(wrapper)) + .append("content", wrapper.getHost()) + + } + + + private fun createSRVRecordBody(service: ICloudService, proxyConfig: ProxyConfig): JsonLib { + return JsonLib.empty() + .append("type", "SRV") + .append("ttl", 1) + .append("proxied", false) + .append( + "data", JsonLib.empty() + .append("service", "_minecraft") + .append("proto", "_tcp") + .append("name", proxyConfig.subDomain) + .append("priority", 0) + .append("weight", 0) + .append("port", service.getPort()) + .append("target", getFullDomainByWrapper(service.getWrapper())) + ) + } + + private fun getFullDomainByWrapper(wrapper: IWrapperInfo): String { + return "${wrapper.getName()}.${config.domain}" + } +} + + + + diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/listener/CloudFlareSingleGroupListener.kt b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/listener/CloudFlareSingleGroupListener.kt new file mode 100644 index 000000000..9ca1b829d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/kotlin/eu/thesimplecloud/module/cloudflare/listener/CloudFlareSingleGroupListener.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.cloudflare.listener + +import eu.thesimplecloud.api.event.service.CloudServiceStartedEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.module.cloudflare.config.proxy.ProxyConfig +import eu.thesimplecloud.module.cloudflare.domain.CloudFlareDomainHelper + +/** + * Created by IntelliJ IDEA. + * Date: 14.12.2020 + * Time: 17:47 + * @author Frederick Baier + */ +class CloudFlareSingleGroupListener( + private val cloudFlareHelper: CloudFlareDomainHelper, + private val allProxyConfigs: Collection +) : IListener { + + private val config = cloudFlareHelper.config + + @CloudEventHandler + fun handleServiceStarted(event: CloudServiceStartedEvent) { + val cloudService = event.cloudService + val proxyConfig = getProxyConfigByService(cloudService) ?: return + if (proxyConfig.domain != this.config.domain) return + if (cloudService.isProxy()) { + cloudFlareHelper.createSRVRecord(cloudService, proxyConfig) + } + } + + @CloudEventHandler + fun handleServiceStarted(event: CloudServiceUnregisteredEvent) { + val cloudService = event.cloudService + if (cloudService.isProxy()) { + cloudFlareHelper.deleteSRVRecord(cloudService) + } + } + + private fun getProxyConfigByService(service: ICloudService): ProxyConfig? { + return this.allProxyConfigs.firstOrNull { it.targetProxyGroup == service.getGroupName() } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/de.json new file mode 100644 index 000000000..ea3db890a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/de.json @@ -0,0 +1,5 @@ +{ + "module.cloudflare.proxy-config.loaded": "CloudFlare-Config für proxy %PROXY% geladen", + "module.cloudflare.domain.active": "Das CloudFlare Modul ist für die Domain %DOMAIN% aktiv", + "module.cloudflare.domain.invalid": "The CloudFlare Module is not configured correctly for domain %DOMAIN%" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/en.json new file mode 100644 index 000000000..4adab31f5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/languages/en.json @@ -0,0 +1,5 @@ +{ + "module.cloudflare.proxy-config.loaded": "Loaded CloudFlare config for proxy %PROXY%", + "module.cloudflare.domain.active": "The CloudFlare Module is active for domain %DOMAIN%", + "module.cloudflare.domain.invalid": "The CloudFlare Module is not configured correctly for domain %DOMAIN%" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/module.json new file mode 100644 index 000000000..0f6059f51 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/module.json @@ -0,0 +1,19 @@ +{ + "name": "SimpleCloud-CloudFlare", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.cloudflare.CloudFlareModule", + "moduleCopyType": "NONE", + "repositories": [ + "https://jitpack.io/", + "https://repo.maven.apache.org/maven2/" + ], + "dependencies": [ + { + "groupId": "com.github.robinbraemer", + "artifactId": "cloudflareapi", + "version": "1.3.3" + } + ], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/updater.json new file mode 100644 index 000000000..0bce2a1ae --- /dev/null +++ b/simplecloud-modules/simplecloud-module-cloudflare/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-cloudflare", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/build.gradle b/simplecloud-modules/simplecloud-module-hubcommand/build.gradle new file mode 100644 index 000000000..ad579be08 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/build.gradle @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-HubCommand.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-launcher")) + compileOnly 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommand.kt b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommand.kt new file mode 100644 index 000000000..8e97f8bb1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommand.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.hubcommand + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.hubcommand.config.HubCommandConfig + + +@Command("hub", CommandType.INGAME, aliases = ["lobby", "leave", "l"]) +class HubCommand(private val config: HubCommandConfig) : ICommandHandler { + + @CommandSubPath + fun handleCommand(sender: ICommandSender, args: Array) { + val player = sender as ICloudPlayer + if (player.getConnectedServer()?.isLobby() == true) { + if (config.alreadyLobbyMessage.isNotBlank()) { + player.sendMessage(config.alreadyLobbyMessage) + } + return + } + + if (config.sendingToLobbyMessage.isNotBlank()) { + player.sendMessage(config.sendingToLobbyMessage) + } + player.sendToLobby() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommandModule.kt b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommandModule.kt new file mode 100644 index 000000000..29e0ea7c3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/HubCommandModule.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.hubcommand + +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.hubcommand.config.HubCommandConfigLoader + +class HubCommandModule : ICloudModule { + + override fun onEnable() { + val config = HubCommandConfigLoader().loadConfig() + Launcher.instance.commandManager.registerCommand(this, HubCommand(config)) + } + + override fun onDisable() { + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfig.kt b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfig.kt new file mode 100644 index 000000000..63e313827 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfig.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.hubcommand.config + +/** + * Created by IntelliJ IDEA. + * Date: 06.12.2020 + * Time: 19:08 + * @author Frederick Baier + */ +class HubCommandConfig( + val alreadyLobbyMessage: String = "§cYou are already on a lobby server", + val sendingToLobbyMessage: String = "§7Connecting to a lobby server..." +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfigLoader.kt b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfigLoader.kt new file mode 100644 index 000000000..d409f8075 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/src/main/kotlin/eu/thesimplecloud/module/hubcommand/config/HubCommandConfigLoader.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.hubcommand.config + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 06.12.2020 + * Time: 19:07 + * @author Frederick Baier + */ +class HubCommandConfigLoader : AbstractJsonLibConfigLoader( + HubCommandConfig::class.java, + File("modules/hub/config.json"), + { HubCommandConfig() }, + true +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/module.json new file mode 100644 index 000000000..0560e813d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-HubCommand", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.hubcommand.HubCommandModule", + "moduleCopyType": "NONE", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/updater.json new file mode 100644 index 000000000..17b3ce13c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-hubcommand/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-hubcommand", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/build.gradle b/simplecloud-modules/simplecloud-module-internalwrapper/build.gradle new file mode 100644 index 000000000..83e0767bb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/build.gradle @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-InternalWrapper.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-launcher")) + compileOnly(project(":simplecloud-runner")) +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/InternalWrapperModule.kt b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/InternalWrapperModule.kt new file mode 100644 index 000000000..4e33decc0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/InternalWrapperModule.kt @@ -0,0 +1,109 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.internalwrapper + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.internalwrapper.setup.InternalWrapperMemorySetup +import eu.thesimplecloud.runner.RunnerFileProvider +import java.io.BufferedReader +import java.io.File +import java.io.IOException +import java.io.InputStreamReader +import java.util.concurrent.TimeUnit +import kotlin.concurrent.thread + +class InternalWrapperModule : ICloudModule { + + private var process: Process? = null + private var commandExecutable: ICommandExecutable? = null + + override fun onEnable() { + val wrapperManager = CloudAPI.instance.getWrapperManager() + val config = Launcher.instance.launcherConfig + + if (wrapperManager.getWrapperByHost(config.host) == null) { + Launcher.instance.setupManager.queueSetup(InternalWrapperMemorySetup(config)) + Launcher.instance.setupManager.waitForAllSetups() + } + + thread(start = true, isDaemon = false) { + Launcher.instance.consoleSender.sendProperty("module.internalwrapper.starting") + val processBuilder = ProcessBuilder( + "java", + "-jar", + RunnerFileProvider.RUNNER_FILE.path, + "--start-application=WRAPPER", + "--disable-auto-updater" + ) + processBuilder.directory(File(".")) + val process = processBuilder.start() + this.process = process + val bufferedReader = BufferedReader(InputStreamReader(process.inputStream)) + val commandExecutable = getCommandExecutable(process) + this.commandExecutable = commandExecutable + while (process.isAlive) { + val readLine = bufferedReader.readLine() ?: continue + Launcher.instance.screenManager.addScreenMessage(commandExecutable, readLine) + } + Launcher.instance.screenManager.unregisterScreen(commandExecutable.getName()) + } + } + + private fun getCommandExecutable(process: Process): ICommandExecutable { + return object : ICommandExecutable { + + override fun getName(): String = "InternalWrapperConsole" + + override fun executeCommand(command: String) { + val command = command + "\n" + try { + if (process.outputStream != null) { + process.outputStream?.write(command.toByteArray()) + process.outputStream?.flush() + } + } catch (e: IOException) { + Launcher.instance.consoleSender.sendMessage("[InternalWrapper] Outputstream is closed.") + } + + } + + } + } + + override fun onDisable() { + if (process?.isAlive == true) { + this.commandExecutable?.executeCommand("stop") + Launcher.instance.scheduler.schedule({ + if (process?.isAlive == true) + process?.destroyForcibly() + }, 13, TimeUnit.SECONDS) + process?.waitFor() + } + } + + override fun isReloadable(): Boolean = false + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/setup/InternalWrapperMemorySetup.kt b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/setup/InternalWrapperMemorySetup.kt new file mode 100644 index 000000000..35fd9d5d4 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/kotlin/eu/thesimplecloud/module/internalwrapper/setup/InternalWrapperMemorySetup.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.internalwrapper.setup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperInfo +import eu.thesimplecloud.launcher.config.launcher.LauncherConfig +import eu.thesimplecloud.launcher.console.setup.ISetup +import eu.thesimplecloud.launcher.console.setup.annotations.SetupCancelled +import eu.thesimplecloud.launcher.console.setup.annotations.SetupFinished +import eu.thesimplecloud.launcher.console.setup.annotations.SetupQuestion +import eu.thesimplecloud.launcher.startup.Launcher + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 17.06.2020 + * Time: 12:06 + */ +class InternalWrapperMemorySetup(private val config: LauncherConfig) : ISetup { + + private var memory: Int = 2048 + + @SetupQuestion(0, "internalwrapper.setup.memory.question.name") + fun memorySetup(memory: Int): Boolean { + this.memory = memory + Launcher.instance.consoleSender.sendPropertyInSetup("internalwrapper.setup.memory.question.memory.success") + return true + } + + @SetupFinished + @SetupCancelled + fun finishedOrCancelled() { + val wrapperInfo = DefaultWrapperInfo("InternalWrapper", config.host, 2, this.memory) + CloudAPI.instance.getWrapperManager().update(wrapperInfo) + Launcher.instance.consoleSender.sendProperty("internalwrapper.setup.memory.finished") + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/de.json new file mode 100644 index 000000000..1f4f7e537 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/de.json @@ -0,0 +1,3 @@ +{ + "module.internalwrapper.starting": "InternalWrapper wird gestartet..." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/en.json new file mode 100644 index 000000000..3165efc31 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/languages/en.json @@ -0,0 +1,3 @@ +{ + "module.internalwrapper.starting": "Starting internal wrapper..." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/module.json new file mode 100644 index 000000000..64ecf1136 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-InternalWrapper", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.internalwrapper.InternalWrapperModule", + "moduleCopyType": "NONE", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/updater.json new file mode 100644 index 000000000..4ecf2f852 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-internalwrapper/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-internalwrapper", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/build.gradle b/simplecloud-modules/simplecloud-module-notify/build.gradle new file mode 100644 index 000000000..8fe994a25 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/build.gradle @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Notify.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-plugin")) + compileOnly(project(":simplecloud-launcher")) + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + compileOnly 'net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/CloudListener.kt b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/CloudListener.kt new file mode 100644 index 000000000..b3cead543 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/CloudListener.kt @@ -0,0 +1,106 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.notify + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.service.CloudServiceRegisteredEvent +import eu.thesimplecloud.api.event.service.CloudServiceStartedEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.player.text.CloudText +import eu.thesimplecloud.api.service.ICloudService + +import java.math.BigDecimal +import java.math.RoundingMode + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 13.04.2020 + * Time: 17:03 + */ +class CloudListener(private val module: NotifyModule) : IListener { + + private lateinit var message: String + private lateinit var cloudText: CloudText + + private val permission = "cloud.module.notify.messages" + + @CloudEventHandler + fun on(event: CloudServiceRegisteredEvent) { + setText(module.config.serviceStartingMessage) + sendCloudMessage(event.cloudService, false) + } + + @CloudEventHandler + fun on(event: CloudServiceStartedEvent) { + setText(module.config.serviceStartedMessage) + val cpuUsage = (event.cloudService.getWrapper().getCpuUsage() * 100).toString() + val decimal = BigDecimal(cpuUsage).setScale(2, RoundingMode.HALF_EVEN) + event.cloudService.getWrapperName() + ?.let { getMessage().replace("%WRAPPER%", it).replace("%CPUUSAGE%", "$decimal%") }?.let { + setText(it) + } + sendCloudMessage(event.cloudService, true) + } + + @CloudEventHandler + fun on(event: CloudServiceUnregisteredEvent) { + setText(module.config.serviceStoppedMessage) + val cpuUsage = (event.cloudService.getWrapper().getCpuUsage() * 100).toString() + val decimal = BigDecimal(cpuUsage).setScale(2, RoundingMode.HALF_EVEN) + event.cloudService.getWrapperName() + ?.let { getMessage().replace("%WRAPPER%", it).replace("%CPUUSAGE%", "$decimal%") }?.let { + setText(it) + } + sendCloudMessage(event.cloudService, false) + } + + private fun setText(message: String) { + this.message = message + } + + private fun getMessage(): String { + return this.message + } + + private fun sendCloudMessage(service: ICloudService, addClick: Boolean) { + + val replacedMessage = getMessage().replace("%SERVICE%", service.getName()) + .replace("%DISPLAYNAME%", service.getDisplayName()) + this.cloudText = CloudText(replacedMessage) + + if (addClick) { + cloudText.addHover(module.config.hoverMessage) + cloudText.addClickEvent(CloudText.ClickEventType.RUN_COMMAND, "/server " + service.getName()) + } + CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().forEach { cloudPlayer -> + cloudPlayer.hasPermission(permission).then { + if (it) { + cloudPlayer.sendMessage(cloudText) + } + } + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/NotifyModule.kt b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/NotifyModule.kt new file mode 100644 index 000000000..65736e88d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/NotifyModule.kt @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.notify + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.notify.config.Config +import eu.thesimplecloud.module.notify.config.DefaultConfig +import java.io.File + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 13.04.2020 + * Time: 16:26 + */ +class NotifyModule : ICloudModule { + + private val configFile = File("modules/notify", "config.json") + lateinit var config: Config + + override fun onEnable() { + loadConfig() + CloudAPI.instance.getEventManager().registerListener(this, CloudListener(this)) + } + + override fun onDisable() { + } + + fun loadConfig() { + if (!configFile.exists()) { + val config = DefaultConfig.get() + saveConfig(config) + this.config = config + } + + val config = JsonLib.fromJsonFile(configFile)!!.getObject(Config::class.java) + this.config = config + } + + fun saveConfig(config: Config) { + JsonLib.fromObject(config).saveAsFile(configFile) + } + + fun saveConfig() { + saveConfig(config) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/Config.kt b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/Config.kt new file mode 100644 index 000000000..a9659c276 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/Config.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.notify.config + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 13.04.2020 + * Time: 16:27 + */ +data class Config( + val serviceStartingMessage: String, + val serviceStartedMessage: String, + val serviceStoppedMessage: String, + val hoverMessage: String +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/DefaultConfig.kt b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/DefaultConfig.kt new file mode 100644 index 000000000..6d771b1e5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/src/main/kotlin/eu/thesimplecloud/module/notify/config/DefaultConfig.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.notify.config + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 13.04.2020 + * Time: 16:25 + */ +class DefaultConfig { + companion object { + fun get(): Config { + return Config( + "§8[§e»§8] §f%DISPLAYNAME%", + "§8[§a»§8] §f%DISPLAYNAME% §8(§7%WRAPPER%§8)", + "§8[§c«§8] §f%DISPLAYNAME% §8(§7%WRAPPER%§8)", + "§7§oClick to connect" + ) + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-notify/src/main/resources/module.json new file mode 100644 index 000000000..f1e834ce9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Notify", + "author": "Fllip", + "mainClass": "eu.thesimplecloud.module.notify.NotifyModule", + "moduleCopyType": "NONE", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-notify/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-notify/src/main/resources/updater.json new file mode 100644 index 000000000..806d5e97e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-notify/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-notify", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/build.gradle b/simplecloud-modules/simplecloud-module-npc/build.gradle new file mode 100644 index 000000000..e8ce56532 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/build.gradle @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-NPC.jar") +} + +dependencies { + compileOnly project(":simplecloud-base") + compileOnly project(":simplecloud-api") + compileOnly project(":simplecloud-plugin") + compileOnly project(":simplecloud-launcher") + + compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT' + + api 'com.github.juliarn.NPC-Lib:npc-lib-bukkit:3.0.0-beta4' + api 'com.github.cryptomorin:XSeries:9.2.0' + api 'com.squareup.okhttp3:okhttp:4.10.0' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/InventorySettingsConfig.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/InventorySettingsConfig.kt new file mode 100644 index 000000000..2bd1ed0a9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/InventorySettingsConfig.kt @@ -0,0 +1,11 @@ +package eu.thesimplecloud.module.npc.lib.config + +data class InventorySettingsConfig( + val inventory: MutableMap, + val rows: Int = 5, + val inventoryName: String = "§8» §7%TARGET_GROUP% §8«", + val onlineService: String = "GREEN_BANNER", + val fullService: String = "ORANGE_BANNER", + val itemName: String = "§8» §7%SERVICE_NAME%", + val lore: List = listOf("§a%ONLINE_PLAYERS%§8/§2%MAX_PLAYERS% §7Players", "§7%MOTD%") +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfig.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfig.kt new file mode 100644 index 000000000..dfe8e5251 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfig.kt @@ -0,0 +1,12 @@ +package eu.thesimplecloud.module.npc.lib.config + +import eu.thesimplecloud.api.CloudAPI + +class NPCModuleConfig( + val npcsConfig: NPCsConfig, + val inventorySettingsConfig: InventorySettingsConfig +) { + fun update() { + CloudAPI.instance.getGlobalPropertyHolder().setProperty("npc-config", this) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfigHandler.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfigHandler.kt new file mode 100644 index 000000000..71d57abe9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCModuleConfigHandler.kt @@ -0,0 +1,50 @@ +package eu.thesimplecloud.module.npc.lib.config + +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +class NPCModuleConfigHandler { + + private val npcFile = File("modules/npc/npcs.json") + private val inventoryFile = File("modules/npc/inventory.json") + + fun save(config: NPCModuleConfig) { + JsonLib.fromObject(config.npcsConfig).saveAsFile(this.npcFile) + JsonLib.fromObject(config.inventorySettingsConfig).saveAsFile(this.inventoryFile) + } + + fun load(): NPCModuleConfig { + if (!this.npcFile.exists()) return this.createConfig() + val npCsConfig = JsonLib.fromJsonFile(this.npcFile)!!.getObject(NPCsConfig::class.java) + val inventorySettingsConfig = + JsonLib.fromJsonFile(this.inventoryFile)!!.getObject(InventorySettingsConfig::class.java) + return NPCModuleConfig(npCsConfig, inventorySettingsConfig) + } + + private fun createConfig(): NPCModuleConfig { + return NPCModuleConfig( + NPCsConfig(mutableListOf()), InventorySettingsConfig( + mutableMapOf( + Pair(0, "BLACK_STAINED_GLASS_PANE"), + Pair(1, "BLACK_STAINED_GLASS_PANE"), + Pair(2, "BLACK_STAINED_GLASS_PANE"), + Pair(3, "BLACK_STAINED_GLASS_PANE"), + Pair(4, "BLACK_STAINED_GLASS_PANE"), + Pair(5, "BLACK_STAINED_GLASS_PANE"), + Pair(6, "BLACK_STAINED_GLASS_PANE"), + Pair(7, "BLACK_STAINED_GLASS_PANE"), + Pair(8, "BLACK_STAINED_GLASS_PANE"), + + Pair(36, "BLACK_STAINED_GLASS_PANE"), + Pair(37, "BLACK_STAINED_GLASS_PANE"), + Pair(38, "BLACK_STAINED_GLASS_PANE"), + Pair(39, "BLACK_STAINED_GLASS_PANE"), + Pair(40, "BLACK_STAINED_GLASS_PANE"), + Pair(41, "BLACK_STAINED_GLASS_PANE"), + Pair(42, "BLACK_STAINED_GLASS_PANE"), + Pair(43, "BLACK_STAINED_GLASS_PANE"), + Pair(44, "BLACK_STAINED_GLASS_PANE") + ) + )) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCsConfig.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCsConfig.kt new file mode 100644 index 000000000..cf989e16d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/NPCsConfig.kt @@ -0,0 +1,14 @@ +package eu.thesimplecloud.module.npc.lib.config + +import eu.thesimplecloud.module.npc.lib.config.npc.CloudNPCData +import eu.thesimplecloud.plugin.startup.CloudPlugin + +data class NPCsConfig( + val npcs: MutableList, +) { + + fun existNpcWithId(id: String): Boolean { + return this.npcs.firstOrNull { it.id == id } != null + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/CloudNPCData.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/CloudNPCData.kt new file mode 100644 index 000000000..07aaf8bde --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/CloudNPCData.kt @@ -0,0 +1,17 @@ +package eu.thesimplecloud.module.npc.lib.config.npc + +import eu.thesimplecloud.module.npc.lib.config.npc.action.NPCAction +import eu.thesimplecloud.module.npc.lib.config.npc.settings.NPCSettings + +data class CloudNPCData( + var displayName: String, + val id: String, + val isMob: Boolean, + val createdInThisGroup: String?, + var targetGroup: String, + var locationData: LocationData, + val npcAction: NPCAction, + val npcItem: NPCItem, + val npcSettings: NPCSettings, + var lines: List +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/LocationData.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/LocationData.kt new file mode 100644 index 000000000..3eb9eda45 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/LocationData.kt @@ -0,0 +1,11 @@ +package eu.thesimplecloud.module.npc.lib.config.npc + +data class LocationData( + var locationGroup: String, + val world: String, + val x: Double, + val y: Double, + val z: Double, + val yaw: Float = 0F, + val pitch: Float = 90F +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/NPCItem.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/NPCItem.kt new file mode 100644 index 000000000..fe2ed0818 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/NPCItem.kt @@ -0,0 +1,6 @@ +package eu.thesimplecloud.module.npc.lib.config.npc + +data class NPCItem( + var rightHand: String?, + var leftHand: String? +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/SkinData.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/SkinData.kt new file mode 100644 index 000000000..3fb97585c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/SkinData.kt @@ -0,0 +1,6 @@ +package eu.thesimplecloud.module.npc.lib.config.npc + +data class SkinData( + var value: String, + var signature: String +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/Action.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/Action.kt new file mode 100644 index 000000000..79fdb76d8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/Action.kt @@ -0,0 +1,7 @@ +package eu.thesimplecloud.module.npc.lib.config.npc.action + +enum class Action { + QUICK_JOIN, + OPEN_INVENTORY, + RUN_COMMAND +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/NPCAction.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/NPCAction.kt new file mode 100644 index 000000000..9ba43d669 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/action/NPCAction.kt @@ -0,0 +1,3 @@ +package eu.thesimplecloud.module.npc.lib.config.npc.action + +data class NPCAction(var leftClick: Action = Action.QUICK_JOIN, var rightClick: Action = Action.OPEN_INVENTORY) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/MobNPCSettings.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/MobNPCSettings.kt new file mode 100644 index 000000000..9e11f319b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/MobNPCSettings.kt @@ -0,0 +1,6 @@ +package eu.thesimplecloud.module.npc.lib.config.npc.settings + +data class MobNPCSettings( + var mobType: String, + var runCommandName: String? +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/NPCSettings.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/NPCSettings.kt new file mode 100644 index 000000000..b4286b49b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/NPCSettings.kt @@ -0,0 +1,8 @@ +package eu.thesimplecloud.module.npc.lib.config.npc.settings + +data class NPCSettings( + var glowing: Boolean = false, + var onFire: Boolean = false, + val mobNPCSettings: MobNPCSettings, + val playerNPCData: PlayerNPCSettings +) diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/PlayerNPCSettings.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/PlayerNPCSettings.kt new file mode 100644 index 000000000..72ba74093 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/config/npc/settings/PlayerNPCSettings.kt @@ -0,0 +1,11 @@ +package eu.thesimplecloud.module.npc.lib.config.npc.settings + +import eu.thesimplecloud.module.npc.lib.config.npc.SkinData + +data class PlayerNPCSettings( + var skinData: SkinData, + var flyingWithElytra: Boolean = false, + var lookAtPlayer: Boolean = true, + var hitWhenPlayerHits: Boolean = false, + var sneakWhenPlayerSneaks: Boolean = false +) diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/extension/String.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/extension/String.kt new file mode 100644 index 000000000..82022ec0e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/extension/String.kt @@ -0,0 +1,28 @@ +package eu.thesimplecloud.module.npc.lib.extension + +fun String.translateColorCodesFromString(): String { + var string = this + string = string.replace("&0".toRegex(), "§0") + string = string.replace("&1".toRegex(), "§1") + string = string.replace("&2".toRegex(), "§2") + string = string.replace("&3".toRegex(), "§3") + string = string.replace("&4".toRegex(), "§4") + string = string.replace("&5".toRegex(), "§5") + string = string.replace("&6".toRegex(), "§6") + string = string.replace("&7".toRegex(), "§7") + string = string.replace("&8".toRegex(), "§8") + string = string.replace("&9".toRegex(), "§9") + string = string.replace("&a".toRegex(), "§a") + string = string.replace("&b".toRegex(), "§b") + string = string.replace("&c".toRegex(), "§c") + string = string.replace("&d".toRegex(), "§d") + string = string.replace("&e".toRegex(), "§e") + string = string.replace("&f".toRegex(), "§f") + string = string.replace("&k".toRegex(), "§k") + string = string.replace("&m".toRegex(), "§m") + string = string.replace("&n".toRegex(), "§n") + string = string.replace("&l".toRegex(), "§l") + string = string.replace("&o".toRegex(), "§o") + string = string.replace("&r".toRegex(), "§r") + return string +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MaterialType.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MaterialType.kt new file mode 100644 index 000000000..671507405 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MaterialType.kt @@ -0,0 +1,5 @@ +package eu.thesimplecloud.module.npc.lib.type + +data class MaterialType( + val types: MutableList +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MobType.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MobType.kt new file mode 100644 index 000000000..1e72b1659 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/lib/type/MobType.kt @@ -0,0 +1,5 @@ +package eu.thesimplecloud.module.npc.lib.type + +data class MobType( + val types: MutableList +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/NPCModule.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/NPCModule.kt new file mode 100644 index 000000000..a96a4e6f4 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/NPCModule.kt @@ -0,0 +1,79 @@ +package eu.thesimplecloud.module.npc.module + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.sync.`object`.GlobalPropertyUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.npc.lib.config.NPCModuleConfig +import eu.thesimplecloud.module.npc.lib.config.NPCModuleConfigHandler +import eu.thesimplecloud.module.npc.lib.type.MaterialType +import eu.thesimplecloud.module.npc.lib.type.MobType +import eu.thesimplecloud.module.npc.module.command.CloudNPCCommand +import eu.thesimplecloud.module.npc.module.command.CreateNpcCommand +import eu.thesimplecloud.module.npc.module.command.EditGeneralNpcCommand +import eu.thesimplecloud.module.npc.module.skin.SkinHandler + +class NPCModule: ICloudModule { + + val npcModuleConfigHandler = NPCModuleConfigHandler() + val skinHandler = SkinHandler() + + override fun onEnable() { + instance = this + + Launcher.instance.commandManager.registerCommand(this, CloudNPCCommand(this)) + Launcher.instance.commandManager.registerCommand(this, CreateNpcCommand()) + Launcher.instance.commandManager.registerCommand(this, EditGeneralNpcCommand()) + + val npcListConfig = this.npcModuleConfigHandler.load() + this.npcModuleConfigHandler.save(npcListConfig) + + CloudAPI.instance.getGlobalPropertyHolder().setProperty("npc-config", npcListConfig) + + CloudAPI.instance.getEventManager().registerListener(this, object : IListener { + + @CloudEventHandler + fun handleUpdate(event: GlobalPropertyUpdatedEvent) { + if (event.propertyName == "npc-config") { + val property = event.property as IProperty + npcModuleConfigHandler.save(property.getValue()) + } + } + + }) + } + + override fun onDisable() { + + } + + override fun isReloadable(): Boolean { + return false + } + + fun getMobCollection(): MobType? { + val globalPropertyHolder = CloudAPI.instance.getGlobalPropertyHolder() + if (globalPropertyHolder.hasProperty("npc-type-list")) { + val property = globalPropertyHolder.getProperty("npc-type-list") + return property?.getValue() + } + return null + } + + + fun getMaterialCollection(): MaterialType? { + val globalPropertyHolder = CloudAPI.instance.getGlobalPropertyHolder() + if (globalPropertyHolder.hasProperty("npc-material-list")) { + val property = globalPropertyHolder.getProperty("npc-material-list") + return property?.getValue() + } + return null + } + + companion object { + lateinit var instance: NPCModule + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CloudNPCCommand.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CloudNPCCommand.kt new file mode 100644 index 000000000..0ecacc44e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CloudNPCCommand.kt @@ -0,0 +1,237 @@ +package eu.thesimplecloud.module.npc.module.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.npc.lib.config.npc.* +import eu.thesimplecloud.module.npc.lib.config.npc.action.Action +import eu.thesimplecloud.module.npc.module.NPCModule +import eu.thesimplecloud.module.npc.module.command.provider.* + +@Command("cloudnpc", CommandType.INGAME, "cloud.module.npc", ["npc", "npcs", "cloudnpcs"]) +class CloudNPCCommand( + private val npcModule: NPCModule +): ICommandHandler { + + @CommandSubPath("reload", "Reloads the npc module") + fun handleReload(sender: ICommandSender) { + val config = this.npcModule.npcModuleConfigHandler.load() + config.update() + sender.sendProperty("manager.command.npc.reload") + } + + @CommandSubPath("delete ", "Edit the target group of npc.") + fun handleDelete( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + config.npcsConfig.npcs.removeIf { it.id.lowercase() == id.lowercase() } + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.delete.successfully") + } + + + @CommandSubPath("edit player toggle lookAtPlayer", "Edit the mode of lookAtPlayer.") + fun handleEditToggleLookAtPlayer( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDPlayerCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.playerNPCData.lookAtPlayer = !cloudNPCData.npcSettings.playerNPCData.lookAtPlayer + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.toggle.lookAtPlayer.successfully") + } + + @CommandSubPath("edit player toggle hitWhenPlayerHits", "Edit the mode of hitWhenPlayerHits.") + fun handleEditToggleHitWhenPlayerHits( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDPlayerCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.playerNPCData.hitWhenPlayerHits = !cloudNPCData.npcSettings.playerNPCData.hitWhenPlayerHits + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.toggle.hitWhenPlayerHits.successfully") + } + + @CommandSubPath("edit player toggle sneakWhenPlayerSneaks", "Edit the mode of sneakWhenPlayerSneaks.") + fun handleEditToggleSneakWhenPlayerSneaks( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDPlayerCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.playerNPCData.sneakWhenPlayerSneaks = !cloudNPCData.npcSettings.playerNPCData.sneakWhenPlayerSneaks + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.toggle.sneakWhenPlayerSneaks.successfully") + } + + @CommandSubPath("edit player toggle flyingWithElytra", "Edit the mode of flyingWithElytra.") + fun handleEditToggleSneakFlyingWithElytra( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDPlayerCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.playerNPCData.flyingWithElytra = !cloudNPCData.npcSettings.playerNPCData.flyingWithElytra + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.toggle.flyingWithElytra.successfully") + } + + @CommandSubPath("edit player setSkinByMineskinID ", "Edit the skin of npc.") + fun handleEditSkinByMineskinID( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDPlayerCommandSuggestionProvider::class) id: String, + @CommandArgument("mineskinID") mineskinID: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + this.npcModule.skinHandler.getSkinConfigByID(mineskinID).thenAccept { + if (it != null) { + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.playerNPCData.skinData.value = it.value + cloudNPCData.npcSettings.playerNPCData.skinData.signature = it.signature + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.skin.mineskin.successfully") + } else { + player.sendProperty("manager.command.npc.edit.skin.mineskin.failed") + } + } + } + + @CommandSubPath("edit player setSkinByName ", "Edit the skin of npc.") + fun handleEditSkinByName( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDPlayerCommandSuggestionProvider::class) id: String, + @CommandArgument("name") name: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + this.npcModule.skinHandler.getSkinConfigByName(name).thenAccept { + if (it != null) { + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.playerNPCData.skinData.value = it.value + cloudNPCData.npcSettings.playerNPCData.skinData.signature = it.signature + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.skin.mineskin.successfully") + } else { + player.sendProperty("manager.command.npc.edit.skin.mineskin.failed") + } + } + } + + @CommandSubPath("edit mob setMobType ", "Edit the type of mob.") + fun handleEditMobType( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDMobCommandSuggestionProvider::class) id: String, + @CommandArgument("type", CloudNPCMobTypeCommandSuggestionProvider::class) type: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModule.npcModuleConfigHandler.load() + + if (config.npcsConfig.npcs.none { it.id.lowercase() == id.lowercase() }) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + + if (!cloudNPCData.isMob) { + player.sendProperty("manager.command.npc.is.not.mob") + return + } + + if (this.npcModule.getMobCollection()?.types?.contains(type.uppercase()) != true) { + player.sendProperty("manager.command.npc.could.not.find.type") + return + } + cloudNPCData.npcSettings.mobNPCSettings.mobType = type.uppercase() + + config.update() + this.npcModule.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.mob.type.successfully") + } + + @CommandSubPath("list", "List of npcs.") + fun handleList(sender: ICommandSender) { + val config = this.npcModule.npcModuleConfigHandler.load() + sender.sendProperty("manager.command.npc.list.header", config.npcsConfig.npcs.size.toString()) + config.npcsConfig.npcs.forEach { + sender.sendProperty("manager.command.npc.list.entry", it.id, it.locationData.locationGroup ,it.targetGroup) + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CreateNpcCommand.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CreateNpcCommand.kt new file mode 100644 index 000000000..ee76f52a3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/CreateNpcCommand.kt @@ -0,0 +1,134 @@ +package eu.thesimplecloud.module.npc.module.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.npc.lib.config.npc.CloudNPCData +import eu.thesimplecloud.module.npc.lib.config.npc.LocationData +import eu.thesimplecloud.module.npc.lib.config.npc.NPCItem +import eu.thesimplecloud.module.npc.lib.config.npc.SkinData +import eu.thesimplecloud.module.npc.lib.config.npc.action.NPCAction +import eu.thesimplecloud.module.npc.lib.config.npc.settings.MobNPCSettings +import eu.thesimplecloud.module.npc.lib.config.npc.settings.NPCSettings +import eu.thesimplecloud.module.npc.lib.config.npc.settings.PlayerNPCSettings +import eu.thesimplecloud.module.npc.module.NPCModule +import eu.thesimplecloud.module.npc.module.command.provider.CloudNPCMobTypeCommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.command.provider.ServicesWithoutProxiesCommandSuggestionProvider + +/** + * Created by MrManHD + * Class create at 22.06.2023 23:19 + */ + +@Command("cloudnpc", CommandType.INGAME, "cloud.module.npc", ["npc", "npcs", "cloudnpcs"]) +class CreateNpcCommand : ICommandHandler { + + private val npcModuleConfigHandler = NPCModule.instance.npcModuleConfigHandler + + @CommandSubPath("create player ", "Create a npc.") + fun executeCreatePlayer( + sender: ICommandSender, + @CommandArgument("id") id: String, + @CommandArgument("targetService", ServicesWithoutProxiesCommandSuggestionProvider::class) targetService: String, + @CommandArgument("displayName") displayName: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.create.failed.id.already.exist") + return + } + + if (cantBeCreatedOnThisService(targetService)) { + player.sendProperty("manager.command.npc.failed.group.not.found") + return + } + + val skinData = SkinData( + "ewogICJ0aW1lc3RhbXAiIDogMTYyNDUyNjI0NjM2MywKICAicHJvZmlsZUlkIiA6ICIwNjlhNzlmNDQ0ZTk0NzI2YTViZWZjYTkwZTM4YWFmNSIsCiAgInByb2ZpbGVOYW1lIiA6ICJOb3RjaCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS8yOTIwMDlhNDkyNWI1OGYwMmM3N2RhZGMzZWNlZjA3ZWE0Yzc0NzJmNjRlMGZkYzMyY2U1NTIyNDg5MzYyNjgwIgogICAgfQogIH0KfQ==", + "K76X+5wYgbcKhUxr5ZJuF4MXquYNPM5ypUf6DdNz2k0+XaJlobLVVdETe2LotlHyj6ABoU3//8mGZnfwhdj2BiulOErpB6cQR4pMmIrW6T3TLCt4L8d9juQy7xy7Dw9sQngXWm2h3Cazm+205qa0apnvA/i+IGv+WeutP52kfGhJBAN7uBUQaut0NWBfFPL8Jo7DhwBvWf/KWVpcT9UcVQuS/dVP/VE0rrTTSf3x2/jGI0ksBEdOz5lROARCHwOA1sRDvP1nQHhZD1Uekj4Bmo6rsAjJCrzr++nK2IcaPMv1uTLv0sbsGe4JF884rqWHYzs7/Cc5lGv8FNy+QjHmTcISfjnlxwJIkI48KOmAjuaova+tU1gBHRFHqJR186Vw8gtIGHusitFr6rUuutODaHyJ1C9VnItyk5RF3eznsh+uUHSkT9NOCTAhx11UhaFjlIHgqHG3rRVmeFWyEKHE8Pk2yEAlROGPedp+oYEwMFbM97Q+og7W/RtSH+kYl9vNwpLrQEG2F0bQUtulwQrWzk8T2fKgPHncZIDS2YvQjrrHjjlG0bLbiakHGvRrMrLbrVtmQrKjOjLuc5j4M/quMoZpFz98q4uftCmNOyN9ZmoEjgFv5fOdsJDGJawSaug9VEieCWhuuPnXPx19GpT1TRzGRjDW9DqO08kNeCcRxq0=" + ) + + createNewNpc(player, displayName, id, targetService, skinData) + } + + @CommandSubPath("create mob ", "Create a npc.") + fun executeCreateMob( + sender: ICommandSender, + @CommandArgument("type", CloudNPCMobTypeCommandSuggestionProvider::class) type: String, + @CommandArgument("id") id: String, + @CommandArgument("targetService", ServicesWithoutProxiesCommandSuggestionProvider::class) targetService: String, + @CommandArgument("displayName") displayName: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.create.failed.id.already.exist") + return + } + + if (cantBeCreatedOnThisService(targetService)) { + player.sendProperty("manager.command.npc.failed.group.not.found") + return + } + + if (NPCModule.instance.getMobCollection()?.types?.contains(type.uppercase()) != true) { + player.sendProperty("manager.command.npc.could.not.find.type") + return + } + + createNewNpc(player, displayName, id, targetService, mobType = type.uppercase()) + } + + private fun cantBeCreatedOnThisService(name: String): Boolean { + val cloudServiceGroupManager = CloudAPI.instance.getCloudServiceGroupManager() + val cloudServiceManager = CloudAPI.instance.getCloudServiceManager() + return cloudServiceGroupManager.getServiceGroupByName(name) == null + && cloudServiceManager.getCloudServiceByName(name) == null + } + + private fun createNewNpc( + player: ICloudPlayer, + displayName: String, + id: String, + targetServiceGroup: String, + skinData: SkinData = SkinData("", ""), + mobType: String = "" + ) { + val config = this.npcModuleConfigHandler.load() + player.getLocation().addResultListener { + val npcSettings = NPCSettings( + mobNPCSettings = MobNPCSettings(mobType, ""), + playerNPCData = PlayerNPCSettings(skinData) + ) + + val cloudNPCData = CloudNPCData( + displayName, + id, + mobType != "", + player.getConnectedServerName(), + targetServiceGroup, + LocationData(it.groupName, it.worldName, it.x, it.y, it.z, it.yaw, it.pitch), + NPCAction(), + NPCItem(null, null), + npcSettings, + listOf("§8» §7Online §b%PLAYERS_ONLINE% §8«", "§8» §7%DISPLAYNAME% §8«") + ) + + config.npcsConfig.npcs.add(cloudNPCData) + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.create.successfully") + }.addFailureListener { + player.sendProperty("manager.command.npc.create.failed.unknown.location") + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/EditGeneralNpcCommand.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/EditGeneralNpcCommand.kt new file mode 100644 index 000000000..d2a52d317 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/EditGeneralNpcCommand.kt @@ -0,0 +1,280 @@ +package eu.thesimplecloud.module.npc.module.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.npc.lib.config.npc.LocationData +import eu.thesimplecloud.module.npc.lib.config.npc.action.Action +import eu.thesimplecloud.module.npc.module.NPCModule +import eu.thesimplecloud.module.npc.module.command.provider.CloudNPCActionCommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.command.provider.CloudNPCIDCommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.command.provider.CloudNPCItemListCommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.command.provider.ServicesWithoutProxiesCommandSuggestionProvider + +/** + * Created by MrManHD + * Class create at 23.06.2023 13:20 + */ + +@Command("cloudnpc", CommandType.INGAME, "cloud.module.npc", ["npc", "npcs", "cloudnpcs"]) +class EditGeneralNpcCommand : ICommandHandler { + + private val npcModuleConfigHandler = NPCModule.instance.npcModuleConfigHandler + + @CommandSubPath("edit general setDisplayname ", "Edit the display name of npc.") + fun executeEditDisplayName( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("displayname") displayname: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.displayName = displayname + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.display.name.successfully") + } + + @CommandSubPath("edit general setLocation", "Edit the location name of npc.") + fun executeEditLocation( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + player.getLocation().addResultListener { location -> + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.locationData = LocationData(location.groupName, location.worldName, location.x, location.y,location.z, location.yaw, location.pitch) + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.location.successfully") + }.addFailureListener { + player.sendProperty("manager.command.npc.edit.location.failed") + } + } + + @CommandSubPath("edit general toggle glowing", "Edit the mode of glowing.") + fun executeEditGlowing( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.glowing = !cloudNPCData.npcSettings.glowing + + config.update() + this.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.toggle.glowing.successfully") + } + + @CommandSubPath("edit general toggle fire", "Edit the mode of fire.") + fun executeEditFire( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.onFire = !cloudNPCData.npcSettings.onFire + + config.update() + this.npcModuleConfigHandler.save(config) + + player.sendProperty("manager.command.npc.edit.toggle.fire.successfully") + } + + @CommandSubPath("edit general setAction leftClick ", "Edit the action of mob.") + fun executeEditLeftAction( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("action", CloudNPCActionCommandSuggestionProvider::class) action: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + + if (!Action.values().map { it.name }.contains(action.uppercase())) { + player.sendProperty("manager.command.npc.could.not.find.action") + return + } + cloudNPCData.npcAction.leftClick = Action.valueOf(action) + + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.action.left.click.successfully") + } + + @CommandSubPath("edit general setRunCommand ", "Edit the run command of mob.") + fun executeEditRunCommand( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("commandName") commandName: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.npcSettings.mobNPCSettings.runCommandName = commandName + + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.run-command.successfully") + } + + @CommandSubPath("edit general setAction rightClick ", "Edit the action of mob.") + fun executeEditRightAction( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("action", CloudNPCActionCommandSuggestionProvider::class) action: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + + if (!Action.values().map { it.name }.contains(action.uppercase())) { + player.sendProperty("manager.command.npc.could.not.find.action") + return + } + cloudNPCData.npcAction.rightClick = Action.valueOf(action) + + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.action.right.click.successfully") + } + + @CommandSubPath("edit general setItem left ", "Edit the item on the left hand.") + fun executeEditLeftItem( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("material", CloudNPCItemListCommandSuggestionProvider::class) type: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + + if (NPCModule.instance.getMaterialCollection()?.types?.contains(type.uppercase()) != true) { + player.sendProperty("manager.command.npc.could.not.find.material") + return + } + cloudNPCData.npcItem.leftHand = type.uppercase() + + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.item.left.successfully") + } + + @CommandSubPath("edit general setItem right ", "Edit the item on the right hand.") + fun executeEditRightItem( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("material", CloudNPCItemListCommandSuggestionProvider::class) type: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + + if (NPCModule.instance.getMaterialCollection()?.types?.contains(type.uppercase()) != true) { + player.sendProperty("manager.command.npc.could.not.find.material") + return + } + cloudNPCData.npcItem.rightHand = type.uppercase() + + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.item.right.successfully") + } + + @CommandSubPath("edit general setTargetGroup ", "Edit the target group of npc.") + fun executeEditTargetGroup( + sender: ICommandSender, + @CommandArgument("id", CloudNPCIDCommandSuggestionProvider::class) id: String, + @CommandArgument("targetService", ServicesWithoutProxiesCommandSuggestionProvider::class) targetService: String + ) { + val player = sender as ICloudPlayer + val config = this.npcModuleConfigHandler.load() + + if (!config.npcsConfig.existNpcWithId(id)) { + player.sendProperty("manager.command.npc.id.not.found.") + return + } + + if (cantBeCreatedOnThisService(targetService)) { + player.sendProperty("manager.command.npc.failed.group.not.found") + return + } + + val cloudNPCData = config.npcsConfig.npcs.first { it.id.lowercase() == id.lowercase() } + cloudNPCData.targetGroup = targetService + config.update() + this.npcModuleConfigHandler.save(config) + player.sendProperty("manager.command.npc.edit.target.group.successfully") + } + + private fun cantBeCreatedOnThisService(name: String): Boolean { + val cloudServiceGroupManager = CloudAPI.instance.getCloudServiceGroupManager() + val cloudServiceManager = CloudAPI.instance.getCloudServiceManager() + return cloudServiceGroupManager.getServiceGroupByName(name) == null + && cloudServiceManager.getCloudServiceByName(name) == null + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCActionCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCActionCommandSuggestionProvider.kt new file mode 100644 index 000000000..3333ae781 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCActionCommandSuggestionProvider.kt @@ -0,0 +1,11 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.npc.lib.config.npc.action.Action + +class CloudNPCActionCommandSuggestionProvider: ICommandSuggestionProvider { + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return Action.values().map { it.name } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDCommandSuggestionProvider.kt new file mode 100644 index 000000000..1e8ab90bf --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDCommandSuggestionProvider.kt @@ -0,0 +1,12 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.NPCModule + +class CloudNPCIDCommandSuggestionProvider: ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return NPCModule.instance.npcModuleConfigHandler.load().npcsConfig.npcs.map { it.id } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDMobCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDMobCommandSuggestionProvider.kt new file mode 100644 index 000000000..0df4612ae --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDMobCommandSuggestionProvider.kt @@ -0,0 +1,12 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.NPCModule + +class CloudNPCIDMobCommandSuggestionProvider: ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return NPCModule.instance.npcModuleConfigHandler.load().npcsConfig.npcs.filter { it.isMob }.map { it.id } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDPlayerCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDPlayerCommandSuggestionProvider.kt new file mode 100644 index 000000000..1695581f9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCIDPlayerCommandSuggestionProvider.kt @@ -0,0 +1,12 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.npc.module.NPCModule + +class CloudNPCIDPlayerCommandSuggestionProvider: ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return NPCModule.instance.npcModuleConfigHandler.load().npcsConfig.npcs.filter { !it.isMob }.map { it.id } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCItemListCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCItemListCommandSuggestionProvider.kt new file mode 100644 index 000000000..16d675534 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCItemListCommandSuggestionProvider.kt @@ -0,0 +1,18 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.npc.lib.type.MaterialType +import eu.thesimplecloud.module.npc.module.NPCModule + +class CloudNPCItemListCommandSuggestionProvider: ICommandSuggestionProvider { + + private var types: MaterialType? = null + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + if (this.types == null) + this.types = NPCModule.instance.getMaterialCollection() + + return this.types!!.types + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCMobTypeCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCMobTypeCommandSuggestionProvider.kt new file mode 100644 index 000000000..c0fe69b67 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/CloudNPCMobTypeCommandSuggestionProvider.kt @@ -0,0 +1,21 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.npc.lib.type.MobType +import eu.thesimplecloud.module.npc.module.NPCModule + +class CloudNPCMobTypeCommandSuggestionProvider: ICommandSuggestionProvider { + + private var types: MobType? = null + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + if (this.types == null) + this.types = NPCModule.instance.getMobCollection() + + if (this.types == null) + return emptyList() + + return this.types!!.types + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/ServicesWithoutProxiesCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/ServicesWithoutProxiesCommandSuggestionProvider.kt new file mode 100644 index 000000000..f25719840 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/command/provider/ServicesWithoutProxiesCommandSuggestionProvider.kt @@ -0,0 +1,26 @@ +package eu.thesimplecloud.module.npc.module.command.provider + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider + +/** + * Created by MrManHD + * Class create at 19.06.2023 23:11 + */ + +class ServicesWithoutProxiesCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + val mutableList = CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + .filter { it.getServiceType() != ServiceType.PROXY } + .map { it.getName() }.toMutableList() + val elements = CloudAPI.instance.getCloudServiceManager().getAllCachedObjects() + .filter { !it.isProxy() } + .map { it.getName() } + mutableList.addAll(elements) + return mutableList + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/skin/SkinHandler.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/skin/SkinHandler.kt new file mode 100644 index 000000000..7e2985b7d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/module/skin/SkinHandler.kt @@ -0,0 +1,135 @@ +package eu.thesimplecloud.module.npc.module.skin + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.util.* +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import java.util.concurrent.Executors + + +class SkinHandler() { + + private val requestExecutor: Executor + private val okHttpClient: OkHttpClient + + private val endpointGetSkinByID = "https://api.mineskin.org/get/uuid/%s" + private val endpointGetUUIDByName = "https://api.mineskin.org/validate/name/%s" + private val endpointGetSkinByUUID = "https://sessionserver.mojang.com/session/minecraft/profile/%s?unsigned=false" + + init { + requestExecutor = Executors.newSingleThreadExecutor() + okHttpClient = OkHttpClient() + } + + fun getSkinConfigByID(id: String): CompletableFuture { + return CompletableFuture.supplyAsync({ + try { + val endpoint = String.format(endpointGetSkinByID, id) + + val request: Request = Request.Builder() + .addHeader("Content-Type", "application/json") + .url(endpoint) + .get().build() + + val response: Response = okHttpClient.newCall(request).execute() + assert(response.body != null) + + val result: String = response.body!!.string() + + val jsonElement: JsonElement = JsonParser.parseString(result) + val jsonObject: JsonObject = jsonElement.asJsonObject + + if (jsonObject.getAsJsonObject("data") == null) + return@supplyAsync null + + val texture: JsonObject = jsonObject.getAsJsonObject("data").getAsJsonObject("texture") + + return@supplyAsync SkinConfig( + texture.get("value").asString, + texture.get("signature").asString + ) + } catch (exception: Exception) { + exception.printStackTrace() + return@supplyAsync null + } + }, requestExecutor) + } + + fun getSkinConfigByName(name: String): CompletableFuture { + return CompletableFuture.supplyAsync({ + try { + val uuid = this.getUUIDFromName(name) ?: return@supplyAsync null + + val endpoint = String.format(endpointGetSkinByUUID, uuid.toString()) + + val request: Request = Request.Builder() + .addHeader("Content-Type", "application/json") + .url(endpoint) + .get().build() + + val response: Response = okHttpClient.newCall(request).execute() + assert(response.body != null) + + val result: String = response.body!!.string() + + val jsonElement: JsonElement = JsonParser.parseString(result) + val jsonObject: JsonObject = jsonElement.asJsonObject + + if (jsonObject.getAsJsonArray("properties") == null) + return@supplyAsync null + + val properties = jsonObject.getAsJsonArray("properties") + val firstProperty = properties[0].asJsonObject + + val skinValue = firstProperty["value"].asString + val signature = firstProperty["signature"].asString + + return@supplyAsync SkinConfig( + skinValue, + signature + ) + } catch (exception: Exception) { + exception.printStackTrace() + return@supplyAsync null + } + }, requestExecutor) + } + + private fun getUUIDFromName(name: String): UUID? { + val endpoint = String.format(endpointGetUUIDByName, name) + + val request: Request = Request.Builder() + .addHeader("Content-Type", "application/json") + .url(endpoint) + .get().build() + + val response: Response = okHttpClient.newCall(request).execute() + assert(response.body != null) + + val result: String = response.body!!.string() + + val jsonElement: JsonElement = JsonParser.parseString(result) + val jsonObject: JsonObject = jsonElement.asJsonObject + + if (!jsonObject.get("valid").asBoolean) + return null + + val string = jsonObject.get("uuid").asString + val formattedUuid = string.replace( + "(.{8})(.{4})(.{4})(.{4})(.{12})".toRegex(), "$1-$2-$3-$4-$5" + ) + + return UUID.fromString(formattedUuid) + } + + + class SkinConfig( + val value: String, + val signature: String + ) {} +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/NPCPlugin.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/NPCPlugin.kt new file mode 100644 index 000000000..25c2c5bc4 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/NPCPlugin.kt @@ -0,0 +1,64 @@ +package eu.thesimplecloud.module.npc.plugin + +import com.cryptomorin.xseries.XMaterial +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.module.npc.lib.config.NPCModuleConfig +import eu.thesimplecloud.module.npc.lib.type.MaterialType +import eu.thesimplecloud.module.npc.lib.type.MobType +import eu.thesimplecloud.module.npc.plugin.inventory.InventoryHandler +import eu.thesimplecloud.module.npc.plugin.listener.CloudListener +import eu.thesimplecloud.module.npc.plugin.listener.InventoryListener +import eu.thesimplecloud.module.npc.plugin.listener.PlayerConnectionListener +import eu.thesimplecloud.module.npc.plugin.npc.ServerNPCHandler +import org.bukkit.Bukkit +import org.bukkit.entity.EntityType +import org.bukkit.plugin.java.JavaPlugin + +class NPCPlugin: JavaPlugin() { + + var serverNPCHandler: ServerNPCHandler? = null + val inventoryHandler = InventoryHandler(this) + + override fun onEnable() { + instance = this + + this.serverNPCHandler = ServerNPCHandler(this) + + CloudAPI.instance.getEventManager().registerListener(CloudAPI.instance.getThisSidesCloudModule(), CloudListener(this)) + val globalPropertyHolder = CloudAPI.instance.getGlobalPropertyHolder() + globalPropertyHolder.requestProperty("npc-config") + + val pluginManager = Bukkit.getPluginManager() + pluginManager.registerEvents(PlayerConnectionListener(this), this) + pluginManager.registerEvents(InventoryListener(this), this) + + if (!globalPropertyHolder.hasProperty("npc-type-list")) { + globalPropertyHolder.setProperty("npc-type-list", MobType( + EntityType.values() + .filter { it.isSpawnable } + .filter { it.isAlive } + .map { it.name }.toMutableList()) + ) + } + + if (!globalPropertyHolder.hasProperty("npc-material-list")) { + globalPropertyHolder.setProperty("npc-material-list", MaterialType( + XMaterial.values().filter { it.isSupported }.map { it.name }.toMutableList()) + ) + } + + Bukkit.getScheduler().runTaskTimerAsynchronously(this, Runnable { + this.serverNPCHandler!!.serverNPC.forEach { + it.value.handleHologramUpdating(it.value.config.targetGroup) + } + }, 20, 20) + } + + override fun onDisable() { + this.serverNPCHandler?.deleteNPCs() + } + + companion object { + lateinit var instance: NPCPlugin + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryData.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryData.kt new file mode 100644 index 000000000..6978d293b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryData.kt @@ -0,0 +1,10 @@ +package eu.thesimplecloud.module.npc.plugin.inventory + +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack + +data class InventoryData( + val group: String, + val inventory: Inventory, + val items: MutableMap = mutableMapOf() +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryHandler.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryHandler.kt new file mode 100644 index 000000000..c75a3cfed --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/inventory/InventoryHandler.kt @@ -0,0 +1,111 @@ +package eu.thesimplecloud.module.npc.plugin.inventory + +import com.cryptomorin.xseries.XMaterial +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.module.npc.lib.config.NPCModuleConfig +import eu.thesimplecloud.module.npc.lib.extension.translateColorCodesFromString +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import org.bukkit.Bukkit +import org.bukkit.Material +import org.bukkit.Sound +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack +import java.util.UUID +import java.util.concurrent.TimeUnit + +class InventoryHandler( + private val npcPlugin: NPCPlugin +) { + + private val cache: MutableMap = mutableMapOf() + val inventories: MutableList = mutableListOf() + + fun open(player: Player, group: String) { + if (this.cache.contains(player.uniqueId)) { + if (this.cache[player.uniqueId]!! > System.currentTimeMillis()) + return + } + this.cache[player.uniqueId] = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(1) + + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(group) + if (serviceGroup == null) { + Bukkit.getLogger().warning("[SimpleCloud-NPC] The inventory is not supported for CloudServices!") + return + } + + val config = this.npcPlugin.serverNPCHandler!!.config + val inventory = Bukkit.createInventory(player, + 9 * config.inventorySettingsConfig.rows, + config.inventorySettingsConfig.inventoryName + .replace("%TARGET_GROUP%", serviceGroup.getName()) + .replace("%TEMPLATE_NAME%", serviceGroup.getTemplateName()) + .replace("%MAX_PLAYERS%", "${serviceGroup.getMaxPlayers()}") + .translateColorCodesFromString()) + val inventoryData = InventoryData(group, inventory) + + config.inventorySettingsConfig.inventory.forEach { (slot, material) -> + val xMaterial = XMaterial.valueOf(material) + val itemStack = xMaterial.parseItem() + if (itemStack != null) { + val itemMeta = itemStack.itemMeta!! + itemMeta.setDisplayName(" ") + itemStack.itemMeta = itemMeta + inventory.setItem(slot, itemStack) + } + } + + serviceGroup.getAllServices().filter { it.isOnline() }.forEach { service -> + val itemStack = this.getMaterial(service, config) + val itemMeta = itemStack.itemMeta!! + itemMeta.setDisplayName(config.inventorySettingsConfig.itemName + .replace("%SERVICE_NAME%", service.getName()) + .replace("%TEMPLATE_NAME%", service.getTemplateName()) + .replace("%WRAPPER_NAME%", service.getWrapper().getName()) + .replace("%DISPLAYNAME%", service.getDisplayName()) + .replace("%ONLINE_PLAYERS%", "${service.getOnlineCount()}") + .replace("%HOST%", service.getHost()) + .replace("%PORT%", "${service.getPort()}") + .replace("%STATE%", service.getState().name) + .replace("%NUMBER%", "${service.getServiceNumber()}") + .replace("%MAX_PLAYERS%", "${service.getMaxPlayers()}") + .replace("%MOTD%", service.getMOTD()) + .translateColorCodesFromString()) + + config.inventorySettingsConfig.lore + .forEach { + val lore = itemMeta.lore ?: mutableListOf() + lore.add(it + .replace("%SERVICE_NAME%", service.getName()) + .replace("%TEMPLATE_NAME%", service.getTemplateName()) + .replace("%WRAPPER_NAME%", service.getWrapper().getName()) + .replace("%DISPLAYNAME%", service.getDisplayName()) + .replace("%ONLINE_PLAYERS%", "${service.getOnlineCount()}") + .replace("%HOST%", service.getHost()) + .replace("%PORT%", "${service.getPort()}") + .replace("%STATE%", service.getState().name) + .replace("%NUMBER%", "${service.getServiceNumber()}") + .replace("%MAX_PLAYERS%", "${service.getMaxPlayers()}") + .replace("%MOTD%", service.getMOTD()) + .translateColorCodesFromString() + ) + itemMeta.lore = lore + } + itemStack.itemMeta = itemMeta + inventory.addItem(itemStack) + inventoryData.items[itemStack] = service.getName() + } + + player.openInventory(inventory) + player.playSound(player.location, Sound.BLOCK_CHEST_OPEN, 0.8F, 0.8F) + this.inventories.add(inventoryData) + } + + private fun getMaterial(service: ICloudService, config: NPCModuleConfig): ItemStack { + return if (service.isFull()) { + XMaterial.valueOf(config.inventorySettingsConfig.fullService).parseItem()!! + } else { + XMaterial.valueOf(config.inventorySettingsConfig.onlineService).parseItem()!! + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/CloudListener.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/CloudListener.kt new file mode 100644 index 000000000..05d9a6f80 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/CloudListener.kt @@ -0,0 +1,33 @@ +package eu.thesimplecloud.module.npc.plugin.listener + +import eu.thesimplecloud.api.event.sync.`object`.GlobalPropertyUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.module.npc.lib.config.NPCModuleConfig +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import org.bukkit.Bukkit + +class CloudListener( + private val npcPlugin: NPCPlugin +): IListener { + + @CloudEventHandler + fun handleUpdate(event: GlobalPropertyUpdatedEvent) { + if (event.propertyName == "npc-config") { + val property = event.property as IProperty + Bukkit.getScheduler().runTask(this.npcPlugin, Runnable { + updateNPCs(property.getValue()) + }) + } + } + + private fun updateNPCs(config: NPCModuleConfig) { + this.npcPlugin.serverNPCHandler!!.deleteNPCs() + + this.npcPlugin.serverNPCHandler!!.config = config + + this.npcPlugin.serverNPCHandler!!.createNPCs() + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/InventoryListener.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/InventoryListener.kt new file mode 100644 index 000000000..73549dd82 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/InventoryListener.kt @@ -0,0 +1,49 @@ +package eu.thesimplecloud.module.npc.plugin.listener + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.InventoryInteractEvent + +class InventoryListener( + private val npcPlugin: NPCPlugin +): Listener { + + @EventHandler + fun onClick(event: InventoryInteractEvent) { + val inventory = event.inventory + this.npcPlugin.inventoryHandler.inventories.find { it.inventory == inventory } ?: return + event.isCancelled = true + } + + @EventHandler + fun onClick(event: InventoryClickEvent) { + val inventory = event.inventory + val player = event.whoClicked as Player + val inventoryData = this.npcPlugin.inventoryHandler.inventories.find { it.inventory == inventory } ?: return + + event.isCancelled = true + val currentItem = event.currentItem ?: return + + val service = inventoryData.items[currentItem] ?: return + val iCloudService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(service) + val cloudPlayer = player.getCloudPlayer() + + if (iCloudService == null) { + cloudPlayer.sendProperty("service.interact.service.not.available") + return + } + + if (iCloudService.getState() == ServiceState.INVISIBLE) { + cloudPlayer.sendProperty("service.interact.service.in.game") + return + } + + cloudPlayer.connect(iCloudService) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/PlayerConnectionListener.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/PlayerConnectionListener.kt new file mode 100644 index 000000000..486564084 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/listener/PlayerConnectionListener.kt @@ -0,0 +1,43 @@ +package eu.thesimplecloud.module.npc.plugin.listener + +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import eu.thesimplecloud.module.npc.plugin.npc.type.PlayerNPC +import org.bukkit.Bukkit +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerToggleSneakEvent + +class PlayerConnectionListener( + private val npcPlugin: NPCPlugin +): Listener { + + @EventHandler + fun onJoin(event: PlayerJoinEvent) { + this.npcPlugin.serverNPCHandler!!.serverNPC.forEach { (_, serverNPC) -> + if (!serverNPC.config.isMob) { + val playerNPC: PlayerNPC = serverNPC as PlayerNPC + + Bukkit.getOnlinePlayers().forEach { + this.npcPlugin.serverNPCHandler!!.updateScoreboardTeam(it.scoreboard, playerNPC.npc.profile().name()) + } + } + } + } + + @EventHandler + fun onToggleSneak(event: PlayerToggleSneakEvent) { + Bukkit.getScheduler().runTaskTimerAsynchronously(this.npcPlugin, + Runnable { + this.npcPlugin.serverNPCHandler!!.serverNPC.forEach { (_, serverNPC) -> + run { + if (!serverNPC.config.isMob) { + val playerNPC: PlayerNPC = serverNPC as PlayerNPC + playerNPC.updateNPCStatus() + } + } + } + }, 1, 1 + ) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/ServerNPCHandler.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/ServerNPCHandler.kt new file mode 100644 index 000000000..b8fd00b46 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/ServerNPCHandler.kt @@ -0,0 +1,83 @@ +package eu.thesimplecloud.module.npc.plugin.npc + +import com.github.juliarn.npclib.api.Platform +import com.github.juliarn.npclib.bukkit.BukkitPlatform +import com.github.juliarn.npclib.bukkit.BukkitWorldAccessor +import eu.thesimplecloud.module.npc.lib.config.NPCModuleConfig +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import eu.thesimplecloud.module.npc.plugin.npc.type.AbstractServerNPC +import eu.thesimplecloud.module.npc.plugin.npc.type.MobNPC +import eu.thesimplecloud.module.npc.plugin.npc.type.PlayerNPC +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import org.bukkit.World +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack +import org.bukkit.plugin.Plugin +import org.bukkit.scoreboard.Scoreboard +import org.bukkit.scoreboard.Team + +class ServerNPCHandler( + val npcPlugin: NPCPlugin +) { + + lateinit var config: NPCModuleConfig + + val platform: Platform = BukkitPlatform.bukkitNpcPlatformBuilder() + .extension(this.npcPlugin) + .debug(true) + .worldAccessor(BukkitWorldAccessor.nameBasedAccessor()) + .actionController { } + .build() + + val serverNPC: MutableMap = mutableMapOf() + + fun createNPCs() { + config.npcsConfig.npcs + .filter { isRightService(it.createdInThisGroup) } + .forEach { npcInformation -> + val npc = if (npcInformation.isMob) { + MobNPC(this, npcInformation) + } else { + PlayerNPC(this, npcInformation) + } + + npc.onSetup() + npc.spawnHolograms() + + this.serverNPC[npcInformation.id] = npc + + if (!npcInformation.isMob) { + val playerNPC = npc as PlayerNPC + Bukkit.getOnlinePlayers().forEach { + updateScoreboardTeam(it.scoreboard, playerNPC.npc.profile().name()) + } + } + } + } + + fun deleteNPCs() { + this.serverNPC.forEach { (_, npc) -> + run { + npc.onRemove() + npc.deleteHolograms() + } + } + this.serverNPC.clear() + } + + fun updateScoreboardTeam(scoreboard: Scoreboard, npcName: String) { + var team = scoreboard.getTeam("simpleCloudNpc") + ?: scoreboard.registerNewTeam("simpleCloudNpc") + team.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER) + team.addEntry(npcName) + } + + private fun isRightService(serviceName: String?): Boolean { + if (serviceName == null) + return true + val thisService = CloudPlugin.instance.thisService() + return thisService.getName() == serviceName + || thisService.getGroupName() == serviceName + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/AbstractServerNPC.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/AbstractServerNPC.kt new file mode 100644 index 000000000..d15fa4616 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/AbstractServerNPC.kt @@ -0,0 +1,147 @@ +package eu.thesimplecloud.module.npc.plugin.npc.type + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.module.npc.lib.config.npc.CloudNPCData +import eu.thesimplecloud.module.npc.lib.config.npc.action.Action +import eu.thesimplecloud.module.npc.lib.extension.translateColorCodesFromString +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import eu.thesimplecloud.module.npc.plugin.npc.ServerNPCHandler +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import eu.thesimplecloud.plugin.extension.syncBukkit +import eu.thesimplecloud.plugin.server.CloudSpigotPlugin +import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.entity.ArmorStand +import org.bukkit.entity.Player +import org.bukkit.metadata.FixedMetadataValue + +abstract class AbstractServerNPC( + val serverNPCHandler: ServerNPCHandler, + val config: CloudNPCData +): ServerNPC { + + lateinit var npcLocation: Location + + private val holograms: MutableList = mutableListOf() + + fun spawnHolograms() { + val locationData = this.config.locationData + + val location = Location( + Bukkit.getWorld(locationData.world), + locationData.x, + (locationData.y + this.getEntityHigh()) - 0.3, + locationData.z + ) + + repeat(this.config.lines.size) { + val armorStand = location.world?.spawn(location.add(0.0, 0.3, 0.0), ArmorStand::class.java) + armorStand?.setGravity(false) + armorStand?.isMarker = true + armorStand?.isInvulnerable = true + armorStand?.isCustomNameVisible = true + armorStand?.customName = "Loading" + armorStand?.isVisible = false + + if (armorStand != null) { + this.holograms.add(armorStand) + } else { + println("Can not spawn hologram for the npc ${this.config.id}") + } + } + handleHologramUpdating(this.config.targetGroup) + } + + fun handleHologramUpdating(serviceName: String) { + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager() + .getServiceGroupByName(serviceName) + serviceGroup?.let { updateHolograms(it.getOnlinePlayerCount(), it.getOnlineServiceCount(), it.getTemplateName()) } + + val cloudService = CloudAPI.instance.getCloudServiceManager() + .getCloudServiceByName(serviceName) + cloudService?.let { updateHolograms(it.getOnlineCount(), 1, it.getTemplateName()) } + } + + private fun updateHolograms(onlinePlayersCount: Int, servicesOnlineCount: Int, templateName: String) { + var i = 0 + this.holograms.forEach { armorStand -> + armorStand.customName = this.config.lines[i] + .replace("%PLAYERS_ONLINE%", onlinePlayersCount.toString()) + .replace("%SERVICES_ONLINE%", servicesOnlineCount.toString()) + .replace("%DISPLAYNAME%", this.config.displayName) + .replace("%SERVICE%", this.config.targetGroup) + .replace("%TEMPLATE%", templateName) + .translateColorCodesFromString() + i++ + } + } + + fun deleteHolograms() { + this.holograms.forEach { + it.remove() + } + } + + fun handlingInteract(player: Player, rightClicked: Boolean) { + val action = this.config.npcAction + if (rightClicked) { + handleClickInteract(player, action.rightClick) + } else { + handleClickInteract(player, action.leftClick) + } + } + + private fun handleClickInteract(player: Player, clickAction: Action){ + when (clickAction) { + Action.QUICK_JOIN -> handleQuickJoin(player) + Action.OPEN_INVENTORY -> handleInventory(player) + Action.RUN_COMMAND -> handleRunCommand(player) + } + } + + private fun handleRunCommand(player: Player) { + val runCommandName = this.config.npcSettings.mobNPCSettings.runCommandName ?: return + Bukkit.getScheduler().runTask(NPCPlugin.instance, kotlinx.coroutines.Runnable { + Bukkit.dispatchCommand(player, runCommandName) + }) + } + + private fun handleQuickJoin(player: Player) { + val serviceName = this.config.targetGroup + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager() + .getServiceGroupByName(serviceName) + serviceGroup?.let { handleGroupQuickJoin(player, it) } + + val cloudService = CloudAPI.instance.getCloudServiceManager() + .getCloudServiceByName(serviceName) + cloudService?.let { handleServiceQuickJoin(player, it) } + } + + private fun handleServiceQuickJoin(player: Player, cloudService: ICloudService) { + val cloudPlayer = player.getCloudPlayer() + cloudPlayer.connect(cloudService) + } + + private fun handleGroupQuickJoin(player: Player, serviceGroup: ICloudServiceGroup) { + val cloudPlayer = player.getCloudPlayer() + val randomService = serviceGroup.getAllServices() + .filter { it.getState() == ServiceState.VISIBLE } + .firstOrNull { !it.isFull() } + + if (randomService == null) { + cloudPlayer.sendProperty("service.interact.no.free.service.found") + return + } + cloudPlayer.connect(randomService) + } + + private fun handleInventory(player: Player) { + Bukkit.getScheduler().runTask(this.serverNPCHandler.npcPlugin, Runnable { + NPCPlugin.instance.inventoryHandler.open(player, this.config.targetGroup) + }) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/MobNPC.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/MobNPC.kt new file mode 100644 index 000000000..656c29a23 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/MobNPC.kt @@ -0,0 +1,123 @@ +package eu.thesimplecloud.module.npc.plugin.npc.type + +import com.cryptomorin.xseries.XMaterial +import eu.thesimplecloud.module.npc.lib.config.npc.CloudNPCData +import eu.thesimplecloud.module.npc.plugin.NPCPlugin +import eu.thesimplecloud.module.npc.plugin.npc.ServerNPCHandler +import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.entity.Entity +import org.bukkit.entity.EntityType +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.player.PlayerInteractAtEntityEvent +import org.bukkit.event.vehicle.VehicleEnterEvent +import org.bukkit.inventory.EquipmentSlot +import java.util.* + +class MobNPC( + serverNPCHandler: ServerNPCHandler, + config: CloudNPCData +) : AbstractServerNPC(serverNPCHandler, config), Listener { + + private lateinit var entity: Entity + private lateinit var uniqueId: UUID + + init { + Bukkit.getPluginManager().registerEvents(this, NPCPlugin.instance) + } + + override fun onSetup() { + val location = this.config.locationData + this.npcLocation = Location(Bukkit.getWorld(location.world), location.x, location.y, location.z, location.yaw, location.pitch) + println("Create NPC as mob " + this.config.id) + this.entity = this.npcLocation.world?.spawnEntity(this.npcLocation, EntityType.valueOf(this.config.npcSettings.mobNPCSettings.mobType))!! + + this.entity.setGravity(false) + this.entity.isCustomNameVisible = false + this.entity.isSilent = true + if (this.entity is LivingEntity) + (this.entity as LivingEntity).setAI(false) + + this.uniqueId = this.entity.uniqueId + + this.entity.isGlowing = this.config.npcSettings.glowing + + this.entity.isVisualFire = this.config.npcSettings.onFire + + this.handleItemForEntity() + } + + override fun onRemove() { + this.entity.remove() + } + + private fun handleItemForEntity() { + if (this.entity is LivingEntity) { + (this.entity as LivingEntity).equipment?.setItem( + EquipmentSlot.HAND, + this.config.npcItem.rightHand?.let { XMaterial.valueOf(it).parseItem() }) + } + if (this.entity is LivingEntity) { + (this.entity as LivingEntity).equipment?.setItem( + EquipmentSlot.OFF_HAND, + this.config.npcItem.leftHand?.let { XMaterial.valueOf(it).parseItem() }) + } + } + + @EventHandler + fun onPlayerInteractAtEntity(event: PlayerInteractAtEntityEvent) { + val player = event.player + val rightClicked = event.rightClicked + + if (rightClicked.uniqueId != this.uniqueId) + return + + event.isCancelled = true + this.handlingInteract(player, true) + } + + @EventHandler + fun onEntityDamageByEntity(event: EntityDamageByEntityEvent) { + val damage = event.damager + val entity = event.entity + + if (this.uniqueId != entity.uniqueId) + return + + if (damage !is Player) + return + + event.isCancelled = true + this.handlingInteract(damage, false) + } + + @EventHandler + fun onDamage(event: EntityDamageEvent) { + val uuid = event.entity.uniqueId + + if (this.uniqueId == uuid) { + event.isCancelled = true + return + } + } + + @EventHandler + fun onVehicleEnter(event: VehicleEnterEvent) { + val uuid = event.vehicle.uniqueId + + if (this.uniqueId == uuid) { + event.isCancelled = true + return + } + } + + override fun getEntityHigh(): Double { + return this.entity.height + } +} + diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/PlayerNPC.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/PlayerNPC.kt new file mode 100644 index 000000000..211f6ab4a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/PlayerNPC.kt @@ -0,0 +1,116 @@ +package eu.thesimplecloud.module.npc.plugin.npc.type + +import com.cryptomorin.xseries.XMaterial +import com.github.juliarn.npclib.api.Npc +import com.github.juliarn.npclib.api.event.InteractNpcEvent +import com.github.juliarn.npclib.api.event.ShowNpcEvent +import com.github.juliarn.npclib.api.profile.Profile +import com.github.juliarn.npclib.api.profile.ProfileProperty +import com.github.juliarn.npclib.api.protocol.enums.EntityStatus +import com.github.juliarn.npclib.api.protocol.enums.ItemSlot +import com.github.juliarn.npclib.api.protocol.meta.EntityMetadataFactory +import com.github.juliarn.npclib.bukkit.util.BukkitPlatformUtil +import com.github.juliarn.npclib.common.event.DefaultAttackNpcEvent +import com.github.juliarn.npclib.common.event.DefaultInteractNpcEvent +import eu.thesimplecloud.module.npc.lib.config.npc.CloudNPCData +import eu.thesimplecloud.module.npc.plugin.npc.ServerNPCHandler +import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.World +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack +import org.bukkit.plugin.Plugin +import java.util.* + +class PlayerNPC( + serverNPCHandler: ServerNPCHandler, + config: CloudNPCData +) : AbstractServerNPC(serverNPCHandler, config) { + + lateinit var npc: Npc + + override fun onSetup() { + val location = this.config.locationData + this.npcLocation = Location(Bukkit.getWorld(location.world), location.x, location.y, location.z, location.yaw, location.pitch) + + val position = BukkitPlatformUtil.positionFromBukkitLegacy(this.npcLocation) + val textures = ProfileProperty.property( + "textures", + this.config.npcSettings.playerNPCData.skinData.value, + this.config.npcSettings.playerNPCData.skinData.signature + ) + + this.npc = this.serverNPCHandler.platform.newNpcBuilder() + .position(position) + .flag(Npc.LOOK_AT_PLAYER, this.config.npcSettings.playerNPCData.lookAtPlayer) + .flag(Npc.HIT_WHEN_PLAYER_HITS, this.config.npcSettings.playerNPCData.hitWhenPlayerHits) + .flag(Npc.SNEAK_WHEN_PLAYER_SNEAKS, this.config.npcSettings.playerNPCData.sneakWhenPlayerSneaks) + .profile( + Profile.resolved( + "SP-NPC-" + Random().nextInt(9999999), + UUID.randomUUID(), + mutableSetOf(textures) + ) + ) + .buildAndTrack() + + this.serverNPCHandler.platform.eventBus().subscribe(DefaultInteractNpcEvent::class.java, this::onDefaultInteractNpc) + this.serverNPCHandler.platform.eventBus().subscribe(DefaultAttackNpcEvent::class.java, this::onDefaultAttackNpc) + this.serverNPCHandler.platform.eventBus().subscribe(ShowNpcEvent.Post::class.java, this::onShowNpc) + } + + override fun onRemove() { + this.npc.unlink() + } + + fun updateNPCStatus() { + val entityStatuses: MutableList = ArrayList() + if (this.config.npcSettings.glowing) entityStatuses.add(EntityStatus.GLOWING) + if (this.config.npcSettings.playerNPCData.flyingWithElytra) entityStatuses.add(EntityStatus.FLYING_WITH_ELYTRA) + if (this.config.npcSettings.onFire) entityStatuses.add(EntityStatus.ON_FIRE) + val packetFactory = npc.platform().packetFactory() + packetFactory.createEntityMetaPacket( + entityStatuses, + EntityMetadataFactory.entityStatusMetaFactory() + ).scheduleForTracked(npc) + } + + private fun onShowNpc(event: ShowNpcEvent.Post) { + val packetFactory = npc.platform().packetFactory() + packetFactory.createEntityMetaPacket(true, EntityMetadataFactory.skinLayerMetaFactory()).scheduleForTracked(npc) + this.updateNPCStatus() + + if (config.npcItem.rightHand != null) + packetFactory.createEquipmentPacket(ItemSlot.MAIN_HAND, XMaterial.valueOf(config.npcItem.rightHand!!).parseItem()!!) + .scheduleForTracked(npc) + + if (config.npcItem.leftHand != null) + packetFactory.createEquipmentPacket(ItemSlot.OFF_HAND, XMaterial.valueOf(config.npcItem.leftHand!!).parseItem()!!) + .scheduleForTracked(npc) + } + + private fun onDefaultInteractNpc(event: DefaultInteractNpcEvent) { + val player = event.player() + val targetNpc = event.npc() + + if (event.hand() == InteractNpcEvent.Hand.OFF_HAND) + return + if (this.npc.entityId() != targetNpc.entityId()) + return + + this.handlingInteract(player, true) + } + + private fun onDefaultAttackNpc(event: DefaultAttackNpcEvent) { + val player = event.player() + val targetNpc = event.npc() + + if (this.npc.entityId() != targetNpc.entityId()) + return + this.handlingInteract(player, false) + } + + override fun getEntityHigh(): Double { + return 1.85 + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/ServerNPC.kt b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/ServerNPC.kt new file mode 100644 index 000000000..15803a93b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/kotlin/eu/thesimplecloud/module/npc/plugin/npc/type/ServerNPC.kt @@ -0,0 +1,10 @@ +package eu.thesimplecloud.module.npc.plugin.npc.type + +interface ServerNPC { + + fun onSetup() + + fun onRemove() + + fun getEntityHigh(): Double +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/de.json new file mode 100644 index 000000000..48e9733c5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/de.json @@ -0,0 +1,35 @@ +{ + "manager.command.npc.failed.group.not.found": "§7Dieser Service konnte nicht gefunden werden!", + "manager.command.npc.id.not.found.": "§7Dieser NPC konnte nicht gefunden werden.", + "manager.command.npc.is.not.mob": "§7Dieser NPC ist kein Mob.", + "manager.command.npc.could.not.find.type": "§7Es konnte kein passender Mob gefunden werden.", + "manager.command.npc.could.not.find.action": "§7Es konnte keine passende Action gefunden werden.", + "manager.command.npc.reload": "§7NPC-Modul neu laden", + "manager.command.npc.create.failed.id.already.exist": "§7Es gibt bereits einen NPC mit dieser ID.", + "manager.command.npc.create.failed.unknown.location": "§7Deine aktuelle Serverposition konnte nicht geladen werden.", + "manager.command.npc.create.successfully": "§7Du hast diesen NPC erfolgreich erstellt.", + "manager.command.npc.list.header": "§8(§b%SIZE%§8) §7NPCs gefunden:", + "manager.command.npc.list.entry": "§7ID: §b%id% §8| §7Gruppe: §b%groupName% §8| §7Gerichtete Gruppe: §b%targetGroup%", + "manager.command.npc.edit.target.group.successfully": "§7Du hast die Zielgruppe des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.display.name.successfully": "§7Du hast den Namen des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.location.successfully": "§7Du hast die Position des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.location.failed": "§7Deine aktuelle Serverposition konnte nicht geladen werden.", + "manager.command.npc.edit.mob.type.successfully": "§7Du hast den Mob des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.item.left.successfully": "§7Du hast den linken Gegenstand des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.item.right.successfully": "§7Du hast den rechten Gegenstand des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.action.left.click.successfully": "§7Du hast die linke Action des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.action.right.click.successfully": "§7Du hast die rechte Action des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.toggle.glowing.successfully": "§7Du hast das Leuchten des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.toggle.fire.successfully": "§7Du hast das Feuer des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.run-command.successfully": "§7Du hast den Befehl erfolgreich bearbeitet.", + "manager.command.npc.edit.toggle.lookAtPlayer.successfully": "§7Du hast den lookAtPlayer des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.toggle.hitWhenPlayerHits.successfully": "§7Du hast hitWhenPlayerHits des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.toggle.sneakWhenPlayerSneaks.successfully": "§7Du hast sneakWhenPlayerSneaks des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.toggle.flyingWithElytra.successfully": "§7Du hast flyingWithElytra des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.skin.mineskin.successfully": "§7Du hast den Skin des NPCs erfolgreich bearbeitet.", + "manager.command.npc.edit.skin.mineskin.failed": "§7Es gab einen Fehler beim Laden des Skins.", + "manager.command.npc.delete.successfully": "§7Du hast den NPC erfolgreich entfernt.", + "service.interact.service.not.available": "$7Dieser Service ist zu diesem Zeitpunkt nicht mehr verfügbar.", + "service.interact.service.in.game": "§7Dieser Service ist derzeit im Spiel.", + "service.interact.no.free.service.found": "§7Derzeit stehen keine freien Services zur Verfügung." +} diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/en.json new file mode 100644 index 000000000..8b024dc56 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/resources/languages/en.json @@ -0,0 +1,35 @@ +{ + "manager.command.npc.failed.group.not.found": "§7This service could not be found!", + "manager.command.npc.id.not.found.": "§7This NPC could not be found.", + "manager.command.npc.is.not.mob": "§7This NPC is not a mob.", + "manager.command.npc.could.not.find.type": "§7Could not find a suitable mob.", + "manager.command.npc.could.not.find.action": "§7Could not find a suitable action.", + "manager.command.npc.reload": "§7NPC module reload", + "manager.command.npc.create.failed.id.already.exist": "§7There is already an NPC with this ID.", + "manager.command.npc.create.failed.unknown.location": "§7Your current server position could not be loaded.", + "manager.command.npc.create.successfully": "§7You have successfully created this NPC.", + "manager.command.npc.list.header": "§8(§b%SIZE%§8) §7NPCs found:", + "manager.command.npc.list.entry": "§7ID: §b%id% §8| §7Group: §b%groupName% §8| §7Directed Group: §b%targetGroup%", + "manager.command.npc.edit.target.group.successfully": "§7You have successfully edited the NPC's target group.", + "manager.command.npc.edit.display.name.successfully": "§7You have successfully edited the NPC's name.", + "manager.command.npc.edit.location.successfully": "§7You have successfully edited the NPC's position.", + "manager.command.npc.edit.location.failed": "§7Your current server position could not be loaded.", + "manager.command.npc.edit.mob.type.successfully": "§7You have successfully edited the NPC's mob type.", + "manager.command.npc.edit.item.left.successfully": "§7You have successfully edited the NPC's left item.", + "manager.command.npc.edit.item.right.successfully": "§7You have successfully edited the NPC's right item.", + "manager.command.npc.edit.action.left.click.successfully": "§7You have successfully edited the NPC's left-click action.", + "manager.command.npc.edit.action.right.click.successfully": "§7You have successfully edited the NPC's right-click action.", + "manager.command.npc.edit.toggle.glowing.successfully": "§7You have successfully edited the NPC's glowing state.", + "manager.command.npc.edit.toggle.fire.successfully": "§7You have successfully edited the NPC's fire state.", + "manager.command.npc.edit.run-command.successfully": "§7You have successfully edited the command.", + "manager.command.npc.edit.toggle.lookAtPlayer.successfully": "§7You have successfully edited the NPC's lookAtPlayer state.", + "manager.command.npc.edit.toggle.hitWhenPlayerHits.successfully": "§7You have successfully edited the NPC's hitWhenPlayerHits state.", + "manager.command.npc.edit.toggle.sneakWhenPlayerSneaks.successfully": "§7You have successfully edited the NPC's sneakWhenPlayerSneaks state.", + "manager.command.npc.edit.toggle.flyingWithElytra.successfully": "§7You have successfully edited the NPC's flyingWithElytra state.", + "manager.command.npc.edit.skin.mineskin.successfully": "§7You have successfully edited the NPC's skin.", + "manager.command.npc.edit.skin.mineskin.failed": "§7There was an error loading the skin.", + "manager.command.npc.delete.successfully": "§7The NPC was successfully removed.", + "service.interact.service.not.available": "$7This service is not available at this time.", + "service.interact.service.in.game": "§7This service is currently in-game.", + "service.interact.no.free.service.found": "§7Currently, there are no free services available." +} diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-npc/src/main/resources/module.json new file mode 100644 index 000000000..a6e05a755 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-NPC", + "author": "D151l", + "mainClass": "eu.thesimplecloud.module.npc.module.NPCModule", + "moduleCopyType": "LOBBY", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/resources/plugin.yml b/simplecloud-modules/simplecloud-module-npc/src/main/resources/plugin.yml new file mode 100644 index 000000000..e226a7dbb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/resources/plugin.yml @@ -0,0 +1,9 @@ +name: SimpleCloud-NPC +version: 1.0 +author: D151l + +main: eu.thesimplecloud.module.npc.plugin.NPCPlugin + +depend: [ SimpleCloud-Plugin ] + +api-version: 1.13 \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-npc/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-npc/src/main/resources/updater.json new file mode 100644 index 000000000..8b397262b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-npc/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-npc", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} diff --git a/simplecloud-modules/simplecloud-module-permission/build.gradle b/simplecloud-modules/simplecloud-module-permission/build.gradle new file mode 100644 index 000000000..3c0c6f3fe --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/build.gradle @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Permission.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-plugin")) + compileOnly(project(":simplecloud-launcher")) + compileOnly group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.6.1' + + compileOnly 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT' + // The full Spigot server with no shadowing. Requires mavenLocal. + compileOnly 'net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT' + // The full Spigot server with no shadowing. Requires mavenLocal. + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind + compileOnly 'com.velocitypowered:velocity-api:3.1.1' + annotationProcessor 'com.velocitypowered:velocity-api:3.1.1' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/IPermissionPool.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/IPermissionPool.kt new file mode 100644 index 000000000..f90b59eea --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/IPermissionPool.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission + +import eu.thesimplecloud.module.permission.group.manager.IPermissionGroupManager +import eu.thesimplecloud.module.permission.player.manager.IPermissionPlayerManager + +interface IPermissionPool { + + /** + * Returns the [IPermissionGroupManager] + */ + fun getPermissionGroupManager(): IPermissionGroupManager + + /** + * Returns the [IPermissionPlayerManager] + */ + fun getPermissionPlayerManager(): IPermissionPlayerManager + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionCheckListener.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionCheckListener.kt new file mode 100644 index 000000000..2dc1e6af0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionCheckListener.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission + +import eu.thesimplecloud.api.event.player.permission.CloudPlayerPermissionCheckEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.module.permission.player.PermissionPlayer + +class PermissionCheckListener : IListener { + + @CloudEventHandler + fun on(event: CloudPlayerPermissionCheckEvent) { + val cloudPlayer = event.cloudPlayer + val permissionPlayer = cloudPlayer.getProperty(PermissionPlayer.PROPERTY_NAME)!!.getValue() + event.setHasPermission(permissionPlayer.hasPermission(event.permission)) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPlayerUpdatedEventCaller.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPlayerUpdatedEventCaller.kt new file mode 100644 index 000000000..391b91c11 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPlayerUpdatedEventCaller.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.player.CloudPlayerUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.module.permission.event.player.PermissionPlayerUpdatedEvent +import eu.thesimplecloud.module.permission.player.getPermissionPlayerSafe + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:28 + * @author Frederick Baier + */ +class PermissionPlayerUpdatedEventCaller : IListener { + + @CloudEventHandler + fun handlePlayerUpdated(event: CloudPlayerUpdatedEvent) { + val permissionPlayer = event.cloudPlayer.getPermissionPlayerSafe() ?: return + CloudAPI.instance.getEventManager().call(PermissionPlayerUpdatedEvent(permissionPlayer)) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPool.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPool.kt new file mode 100644 index 000000000..3ca889ba3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/PermissionPool.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.module.permission.group.manager.IPermissionGroupManager +import eu.thesimplecloud.module.permission.group.manager.PermissionGroupManager +import eu.thesimplecloud.module.permission.manager.PermissionModule +import eu.thesimplecloud.module.permission.packet.PacketOutGetDefaultGroupName +import eu.thesimplecloud.module.permission.player.manager.IPermissionPlayerManager +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class PermissionPool(private val permissionGroupManager: PermissionGroupManager) : IPermissionPool { + + private val permissionPlayerManager = object : IPermissionPlayerManager {} + + init { + instance = this + CloudAPI.instance.getSynchronizedObjectListManager().registerSynchronizedObjectList(permissionGroupManager) + val cloudModule = if (CloudAPI.instance.isManager()) { + PermissionModule.instance + } else { + CloudPlugin.instance + } + CloudAPI.instance.getEventManager().registerListener(cloudModule, PermissionCheckListener()) + CloudAPI.instance.getEventManager().registerListener(cloudModule, PermissionPlayerUpdatedEventCaller()) + + if (!CloudAPI.instance.isManager()) { + CloudPlugin.instance.communicationClient.getConnection().sendQuery(PacketOutGetDefaultGroupName()) + .then { permissionGroupManager.setDefaultPermissionGroup(it) }.syncUninterruptibly() + } + } + + + override fun getPermissionGroupManager(): IPermissionGroupManager = this.permissionGroupManager + + override fun getPermissionPlayerManager(): IPermissionPlayerManager = this.permissionPlayerManager + + companion object { + @JvmStatic + lateinit var instance: PermissionPool + private set + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/IPermissionEntity.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/IPermissionEntity.kt new file mode 100644 index 000000000..ffa96616c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/IPermissionEntity.kt @@ -0,0 +1,79 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.entity + +import eu.thesimplecloud.module.permission.permission.Permission + +interface IPermissionEntity { + + /** + * Returns whether the group has the specified [permission] + */ + fun hasPermission(permission: String): Boolean { + if (permission.isBlank()) return true + val permissionObj = getNotExpiredPermissionByMatch(permission) ?: return hasAllRights() + return permissionObj.active + } + + fun getNotExpiredPermissionByMatch(permission: String): Permission? { + val notExpiredPermissions = getAllNotExpiredPermissions() + return notExpiredPermissions.firstOrNull { it.matches(permission) } + } + + /** + * Returns the permission object of the specified [permission] + */ + fun getPermissionByName(permission: String): Permission? = + getPermissions().firstOrNull { it.permissionString == permission } + + /** + * Returns all permissions of this entity + */ + fun getPermissions(): Collection + + /** + * Adds the specified [permission] to the list + */ + fun addPermission(permission: Permission) + + /** + * Removes the permission object found by the specified [permissionString] + */ + fun removePermission(permissionString: String) + + /** + * Removes all permissions from this entity + */ + fun clearAllPermission() + + /** + * Returns all not expired permissions + */ + fun getAllNotExpiredPermissions(): Collection = getPermissions().filter { !it.isExpired() } + + /** + * Returns whether this + */ + fun hasAllRights(): Boolean = getAllNotExpiredPermissions().any { it.permissionString == "*" } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/PermissionEntity.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/PermissionEntity.kt new file mode 100644 index 000000000..ad7b788d3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/entity/PermissionEntity.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.entity + +import eu.thesimplecloud.module.permission.permission.Permission +import java.util.concurrent.CopyOnWriteArrayList + +open class PermissionEntity : IPermissionEntity { + + private val permissions = CopyOnWriteArrayList() + + override fun getPermissions(): Collection = this.permissions + + override fun addPermission(permission: Permission) { + removePermission(permission.permissionString) + //if (getPermissionByName(permission.permissionString) != null) throw IllegalStateException("Permission already added") + this.permissions.add(permission) + } + + override fun removePermission(permissionString: String) { + this.permissions.remove(getPermissionByName(permissionString)) + } + + override fun clearAllPermission() { + this.permissions.clear() + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupDeletedEvent.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupDeletedEvent.kt new file mode 100644 index 000000000..f5d34ed43 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupDeletedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.event.group + +import eu.thesimplecloud.module.permission.group.IPermissionGroup + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:23 + * @author Frederick Baier + */ +class PermissionGroupDeletedEvent(player: IPermissionGroup) : PermissionGroupEvent(player) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupEvent.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupEvent.kt new file mode 100644 index 000000000..8a8fbb805 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupEvent.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.event.group + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.module.permission.group.IPermissionGroup + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:21 + * @author Frederick Baier + */ +open class PermissionGroupEvent( + val player: IPermissionGroup +) : IEvent \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupUpdatedEvent.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupUpdatedEvent.kt new file mode 100644 index 000000000..661ec25ef --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/group/PermissionGroupUpdatedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.event.group + +import eu.thesimplecloud.module.permission.group.IPermissionGroup + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:23 + * @author Frederick Baier + */ +class PermissionGroupUpdatedEvent(player: IPermissionGroup) : PermissionGroupEvent(player) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerEvent.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerEvent.kt new file mode 100644 index 000000000..0d126263c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerEvent.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.event.player + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.module.permission.player.IPermissionPlayer + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:21 + * @author Frederick Baier + */ +open class PermissionPlayerEvent( + val player: IPermissionPlayer +) : IEvent \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerUpdatedEvent.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerUpdatedEvent.kt new file mode 100644 index 000000000..74163a425 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/event/player/PermissionPlayerUpdatedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.event.player + +import eu.thesimplecloud.module.permission.player.IPermissionPlayer + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 18:23 + * @author Frederick Baier + */ +class PermissionPlayerUpdatedEvent(player: IPermissionPlayer) : PermissionPlayerEvent(player) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/IPermissionGroup.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/IPermissionGroup.kt new file mode 100644 index 000000000..c9017c316 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/IPermissionGroup.kt @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.group + +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.entity.IPermissionEntity + +interface IPermissionGroup : IPermissionEntity, Nameable { + + /** + * Adds a permission group to inherit from. + * Returns false if this group is already inheriting from the specified one. + */ + fun addInheritedPermissionGroup(permissionGroup: IPermissionGroup): Boolean + + /** + * Removes a permission group from the inheritance. + * Returns whether this groups was inheriting from the specified [permissionGroup] + */ + fun removeInheritedPermissionGroup(permissionGroup: IPermissionGroup): Boolean + + /** + * Returns the names of all permission groups this group inherits from. + */ + fun getAllInheritedPermissionGroupNames(): List + + /** + * Returns all permission groups this group inherits from. + */ + fun getAllInheritedPermissionGroups(): List = getAllInheritedPermissionGroupNames().mapNotNull { + PermissionPool.instance.getPermissionGroupManager().getPermissionGroupByName(it) + } + + /** + * Returns the priority of this group + * It is used to determine the highest [IPermissionGroup] + */ + fun getPriority(): Int + + override fun hasPermission(permission: String): Boolean { + return super.hasPermission(permission) || getAllInheritedPermissionGroups().any { it.hasPermission(permission) } + } + + /** + * Updates this group + */ + fun update() + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/PermissionGroup.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/PermissionGroup.kt new file mode 100644 index 000000000..ff5bb7e95 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/PermissionGroup.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.group + +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.entity.PermissionEntity + +class PermissionGroup( + private val name: String, + private val priority: Int +) : PermissionEntity(), IPermissionGroup { + + private val inheritedPermissionGroups = ArrayList() + + + override fun getName(): String = this.name + + override fun addInheritedPermissionGroup(permissionGroup: IPermissionGroup): Boolean { + if (this.inheritedPermissionGroups.contains(permissionGroup.getName())) return false + this.inheritedPermissionGroups.add(permissionGroup.getName()) + return true + } + + override fun removeInheritedPermissionGroup(permissionGroup: IPermissionGroup): Boolean { + if (!this.inheritedPermissionGroups.contains(permissionGroup.getName())) return false + this.inheritedPermissionGroups.remove(permissionGroup.getName()) + return true + } + + override fun getAllInheritedPermissionGroupNames(): List = this.inheritedPermissionGroups + + override fun getPriority(): Int { + return this.priority + } + + override fun update() { + PermissionPool.instance.getPermissionGroupManager().update(this) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/IPermissionGroupManager.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/IPermissionGroupManager.kt new file mode 100644 index 000000000..57a1840af --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/IPermissionGroupManager.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.group.manager + +import eu.thesimplecloud.module.permission.group.IPermissionGroup +import eu.thesimplecloud.module.permission.group.PermissionGroup + +interface IPermissionGroupManager { + + /** + * Returns all registered permission groups. + */ + fun getAllPermissionGroups(): Collection + + /** + * Returns the [IPermissionGroup] found by the specified [name] + */ + fun getPermissionGroupByName(name: String): IPermissionGroup? + + /** + * Returns the name of the default permission group + */ + fun getDefaultPermissionGroupName(): String + + /** + * Returns the default [IPermissionGroup] + */ + fun getDefaultPermissionGroup(): IPermissionGroup = getPermissionGroupByName(getDefaultPermissionGroupName())!! + + /** + * Updates the specified [IPermissionGroup] + */ + fun update(permissionGroup: PermissionGroup) + + /** + * Deletes the specified [IPermissionGroup] + */ + fun delete(permissionGroup: IPermissionGroup) + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/PermissionGroupManager.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/PermissionGroupManager.kt new file mode 100644 index 000000000..63478f23e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/group/manager/PermissionGroupManager.kt @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.group.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.sync.list.AbstractSynchronizedObjectList +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.module.permission.event.group.PermissionGroupUpdatedEvent +import eu.thesimplecloud.module.permission.group.IPermissionGroup +import eu.thesimplecloud.module.permission.group.PermissionGroup +import eu.thesimplecloud.module.permission.manager.PermissionModule +import java.util.concurrent.CopyOnWriteArrayList + +class PermissionGroupManager( + list: List = emptyList() +) : AbstractSynchronizedObjectList( + CopyOnWriteArrayList(list.map { Property(it) }) +), IPermissionGroupManager { + + @Volatile + private var defaultPermissionGroupName = "default" + + override fun getIdentificationName(): String = "simplecloud-module-permission" + + override fun getCachedObjectByUpdateValue(value: PermissionGroup): IProperty? { + return this.values.firstOrNull { it.getValue().getName() == value.getName() } + } + + override fun getAllPermissionGroups(): Collection = this.values.map { it.getValue() } + + override fun getPermissionGroupByName(name: String): IPermissionGroup? = + this.values.firstOrNull { it.getValue().getName() == name }?.getValue() + + override fun getDefaultPermissionGroupName(): String = this.defaultPermissionGroupName + + override fun update(permissionGroup: PermissionGroup) { + update(Property(permissionGroup), false) + } + + override fun delete(permissionGroup: IPermissionGroup) { + getCachedObjectByUpdateValue(permissionGroup as PermissionGroup)?.let { super.remove(it, false) } + CloudAPI.instance.getEventManager().call(PermissionGroupUpdatedEvent(permissionGroup)) + if (CloudAPI.instance.isManager()) { + PermissionModule.instance.updateGroupsFile() + } + } + + override fun update(property: IProperty, fromPacket: Boolean): ICommunicationPromise { + val returnValue = super.update(property, fromPacket) + CloudAPI.instance.getEventManager().call(PermissionGroupUpdatedEvent(property.getValue())) + if (CloudAPI.instance.isManager()) { + PermissionModule.instance.updateGroupsFile() + } + return returnValue + } + + fun setDefaultPermissionGroup(groupName: String) { + this.defaultPermissionGroupName = groupName + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/CloudListener.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/CloudListener.kt new file mode 100644 index 000000000..69bf97e35 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/CloudListener.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager + +import eu.thesimplecloud.api.event.player.CloudPlayerUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.module.permission.player.PermissionPlayer + +class CloudListener : IListener { + + @CloudEventHandler + fun on(event: CloudPlayerUpdatedEvent) { + val cloudPlayer = event.cloudPlayer + if (!cloudPlayer.hasProperty(PermissionPlayer.PROPERTY_NAME)) { + cloudPlayer.setProperty( + PermissionPlayer.PROPERTY_NAME, + PermissionPlayer(cloudPlayer.getName(), cloudPlayer.getUniqueId()) + ) + } + + val permissionPlayer = cloudPlayer.getProperty(PermissionPlayer.PROPERTY_NAME)!!.getValue() + if (permissionPlayer.getName() != cloudPlayer.getName()) { + permissionPlayer.setName(cloudPlayer.getName()) + permissionPlayer.update().awaitUninterruptibly() + } + val expiredPermissions = permissionPlayer.getPermissions().filter { it.isExpired() } + expiredPermissions.forEach { permissionPlayer.removePermission(it.permissionString) } + val expiredGroups = permissionPlayer.getPermissionGroupInfoList().filter { it.isExpired() } + expiredGroups.forEach { permissionPlayer.removePermissionGroup(it.permissionGroupName) } + if (expiredPermissions.isNotEmpty() || expiredGroups.isNotEmpty()) { + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionFilesPriorityUpdater.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionFilesPriorityUpdater.kt new file mode 100644 index 000000000..692878b9e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionFilesPriorityUpdater.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager + +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +class PermissionFilesPriorityUpdater { + + private val groupsDir = File("modules/permissions/groups/") + + fun updateFilesIfNecessary() { + if (!groupsDir.exists()) return + val files = groupsDir.listFiles()!! + if (files.isEmpty()) return + if (isOutdatedConfig(files[0])) { + files.forEach { updateFile(it) } + } + } + + private fun updateFile(file: File) { + val jsonLib = JsonLib.fromJsonFile(file)!! + jsonLib.append("priority", 0) + jsonLib.saveAsFile(file) + } + + private fun isOutdatedConfig(file: File): Boolean { + val jsonLib = JsonLib.fromJsonFile(file)!! + return jsonLib.getInt("priority") == null + } + +} diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionModule.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionModule.kt new file mode 100644 index 000000000..67d92b86a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/PermissionModule.kt @@ -0,0 +1,91 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.player.OfflineCloudPlayer +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.group.PermissionGroup +import eu.thesimplecloud.module.permission.group.manager.PermissionGroupManager +import eu.thesimplecloud.module.permission.manager.command.PermissionCommand +import eu.thesimplecloud.module.permission.manager.config.PermissionGroupConfigsLoader +import eu.thesimplecloud.module.permission.manager.config.PermissionModuleConfigLoader +import eu.thesimplecloud.module.permission.packet.PacketInGetDefaultGroupName +import eu.thesimplecloud.module.permission.player.IPermissionPlayer +import eu.thesimplecloud.module.permission.player.PermissionPlayer + +class PermissionModule : ICloudModule { + companion object { + + @JvmStatic + @Volatile + lateinit var instance: PermissionModule + private set + + } + + private lateinit var permissionGroupManager: PermissionGroupManager + + private val permissionGroupConfigsLoader = PermissionGroupConfigsLoader() + + init { + instance = this + } + + override fun onEnable() { + PermissionFilesPriorityUpdater().updateFilesIfNecessary() + val config = PermissionModuleConfigLoader().loadConfig() + val groups = this.permissionGroupConfigsLoader.loadAll() + + this.permissionGroupManager = PermissionGroupManager(groups.toList()) + this.permissionGroupManager.setDefaultPermissionGroup(config.defaultPermissionGroupName) + PermissionPool(this.permissionGroupManager) + CloudAPI.instance.getEventManager().registerListener(this, CloudListener()) + Launcher.instance.commandManager.registerCommand(this, PermissionCommand()) + Manager.instance.communicationServer.getPacketManager().registerPacket(PacketInGetDefaultGroupName::class.java) + } + + override fun onDisable() { + } + + fun updateGroupsFile() { + val permissionGroups = this.permissionGroupManager.getAllPermissionGroups() as List + permissionGroups.forEach { this.permissionGroupConfigsLoader.save(it) } + } + + fun updatePermissionPlayer(permissionPlayer: IPermissionPlayer) { + val offlineCloudPlayerHandler = Manager.instance.offlineCloudPlayerHandler + val cloudPlayer = permissionPlayer.getOfflineCloudPlayer().getBlockingOrNull() + if (cloudPlayer?.isOnline() == true) { + permissionPlayer.update() + offlineCloudPlayerHandler.saveCloudPlayer(cloudPlayer.toOfflinePlayer() as OfflineCloudPlayer) + } else { + val offlinePlayer = offlineCloudPlayerHandler.getOfflinePlayer(permissionPlayer.getName()) ?: return + offlinePlayer.setProperty(PermissionPlayer.PROPERTY_NAME, permissionPlayer) + offlineCloudPlayerHandler.saveCloudPlayer(offlinePlayer as OfflineCloudPlayer) + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionCommand.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionCommand.kt new file mode 100644 index 000000000..2c66f2103 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionCommand.kt @@ -0,0 +1,467 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.launcher.console.command.provider.CloudPlayerCommandSuggestionProvider +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.group.PermissionGroup +import eu.thesimplecloud.module.permission.manager.PermissionModule +import eu.thesimplecloud.module.permission.permission.Permission +import eu.thesimplecloud.module.permission.player.IPermissionPlayer +import eu.thesimplecloud.module.permission.player.PlayerPermissionGroupInfo +import eu.thesimplecloud.module.permission.player.getPermissionPlayer +import java.util.concurrent.TimeUnit + +@Command("perms", CommandType.CONSOLE_AND_INGAME, "cloud.module.permission") +class PermissionCommand : ICommandHandler { + + + @CommandSubPath("user ", "Shows information about a user") + fun on( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String + ) { + val permissionPlayer = getPermissionPlayerByName(user) + if (permissionPlayer == null) { + commandSender.sendProperty("module.permission.command.perms.user-not-exist") + return + } + commandSender.sendMessage("User ${permissionPlayer.getName()}:") + commandSender.sendMessage("Highest Group: ${permissionPlayer.getHighestPermissionGroup().getName()}") + commandSender.sendMessage("Groups: ${permissionPlayer.getAllNotExpiredPermissionGroups().map { it.getName() }}") + val playerPermissions = permissionPlayer.getPermissions() + if (playerPermissions.isNotEmpty()) + commandSender.sendMessage("Permissions:") + playerPermissions.forEach { + commandSender.sendMessage("- ${it.permissionString} : ${it.active}") + } + } + + private fun getPermissionPlayerByName(name: String): IPermissionPlayer? { + val offlinePlayer = + CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(name).awaitUninterruptibly().getNow() + ?: return null + return offlinePlayer.getPermissionPlayer() + } + + + @CommandSubPath("user group add ", "Adds a group to a user lifetime") + fun onAdd( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("group", PermissionGroupCommandSuggestionProvider::class) group: String + ) { + this.onAdd(commandSender, user, group, "lifetime") + } + + + @CommandSubPath("user group add ", "Adds a group to a user") + fun onAdd( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("group", PermissionGroupCommandSuggestionProvider::class) group: String, + @CommandArgument("days") days: String + ) { + val permissionPlayer = getPermissionPlayerByName(user) + if (permissionPlayer == null) { + commandSender.sendProperty("module.permission.command.perms.user-not-exist") + return + } + val permissionGroup = PermissionPool.instance.getPermissionGroupManager().getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + val isInt = try { + days.toInt() + true + } catch (ex: Exception) { + false + } + if (days.equals("lifetime", true)) { + permissionPlayer.addPermissionGroup(PlayerPermissionGroupInfo(group, -1)) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + commandSender.sendProperty( + "module.permission.command.perms.user.group.added.lifetime", + permissionGroup.getName(), + permissionPlayer.getName() + ) + return + } + if (!isInt) { + commandSender.sendProperty("module.permission.command.perms.user.day-invalid") + return + } + permissionPlayer.addPermissionGroup( + PlayerPermissionGroupInfo( + group, + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(days.toLong()) + ) + ) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + commandSender.sendProperty( + "module.permission.command.perms.user.group.added.days", + permissionGroup.getName(), + days, + permissionPlayer.getName() + ) + } + + @CommandSubPath("user group remove ", "Removes a group from a user") + fun on( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("group", PermissionGroupCommandSuggestionProvider::class) group: String + ) { + val permissionPlayer = getPermissionPlayerByName(user) + if (permissionPlayer == null) { + commandSender.sendProperty("module.permission.command.perms.user-not-exist") + return + } + val permissionGroup = PermissionPool.instance.getPermissionGroupManager().getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.user.group-not-exist") + return + } + permissionPlayer.removePermissionGroup(permissionGroup.getName()) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + commandSender.sendProperty( + "module.permission.command.perms.user.group.removed", + permissionGroup.getName(), + permissionPlayer.getName() + ) + } + + @CommandSubPath("user group set ", "Adds a permission to a user") + fun handleGroupSet( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("group", PermissionGroupCommandSuggestionProvider::class) group: String + ) { + val permissionPlayer = getPermissionPlayerByName(user) + if (permissionPlayer == null) { + commandSender.sendProperty("module.permission.command.perms.user-not-exist") + return + } + val permissionGroup = PermissionPool.instance.getPermissionGroupManager().getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.user.group-not-exist") + return + } + permissionPlayer.clearGroups() + permissionPlayer.addPermissionGroup(PlayerPermissionGroupInfo(permissionGroup.getName(), -1)) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + commandSender.sendProperty( + "module.permission.command.perms.user.group.set", + permissionGroup.getName(), + permissionPlayer.getName() + ) + } + + @CommandSubPath("user permission add ", "Adds a permission to a user") + fun onPermission( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("permission") permission: String, + @CommandArgument("days") days: String, + @CommandArgument("active") active: String + ) { + val permissionPlayer = getPermissionPlayerByName(user) + if (permissionPlayer == null) { + commandSender.sendProperty("module.permission.command.perms.user-not-exist") + return + } + + val isInt = try { + days.toInt() + true + } catch (ex: Exception) { + false + } + if (days.equals("lifetime", true)) { + permissionPlayer.addPermission(Permission(permission, -1, active.toBoolean())) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + commandSender.sendProperty( + "module.permission.command.perms.user.permission.added.lifetime", + permission, + permissionPlayer.getName() + ) + return + } + if (!isInt) { + commandSender.sendProperty("module.permission.command.perms.user.day-invalid") + return + } + commandSender.sendProperty( + "module.permission.command.perms.user.group.added.days", + permission, + days, + permissionPlayer.getName() + ) + permissionPlayer.addPermission( + Permission( + permission, + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(days.toLong()), + active.toBoolean() + ) + ) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + } + + @CommandSubPath("user permission add ", "Adds a permission to a user") + fun onPermission( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("permission") permission: String, + @CommandArgument("days") days: String + ) { + onPermission(commandSender, user, permission, days, true.toString()) + } + + @CommandSubPath("user permission remove ", "Removes a permission from a user") + fun onPermission( + commandSender: ICommandSender, + @CommandArgument("user", CloudPlayerCommandSuggestionProvider::class) user: String, + @CommandArgument("permission") permission: String + ) { + val permissionPlayer = getPermissionPlayerByName(user) + if (permissionPlayer == null) { + commandSender.sendProperty("module.permission.command.perms.user-not-exist") + return + } + if (permissionPlayer.getPermissionByName(permission) == null) { + commandSender.sendProperty("module.permission.command.perms.user.permission.already-removed") + return + } + permissionPlayer.removePermission(permission) + PermissionModule.instance.updatePermissionPlayer(permissionPlayer) + commandSender.sendProperty("module.permission.command.perms.user.permission.removed", permission) + } + + //groups + + fun getPermissionGroupByName(name: String) = + PermissionPool.instance.getPermissionGroupManager().getPermissionGroupByName(name) + + @CommandSubPath("groups", "Shows all permission groups") + fun handleGroup(commandSender: ICommandSender) { + commandSender.sendMessage("§7Permission-Groups:") + PermissionPool.instance.getPermissionGroupManager().getAllPermissionGroups().forEach { + commandSender.sendMessage("§8- §e" + it.getName()) + } + } + + @CommandSubPath("group create", "Creates a permission group") + fun handleGroupCreate(commandSender: ICommandSender, @CommandArgument("group") group: String) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup != null) { + commandSender.sendProperty("module.permission.command.perms.group-already-exist") + return + } + PermissionGroup(group, 0).update() + commandSender.sendProperty("module.permission.command.perms.group.created", group) + } + + @CommandSubPath("group delete", "Deletes a permission group") + fun handleGroupDelete(commandSender: ICommandSender, @CommandArgument("group") group: String) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + PermissionPool.instance.getPermissionGroupManager().delete(permissionGroup) + commandSender.sendProperty("module.permission.command.perms.group.deleted", group) + } + + @CommandSubPath("group ", "Shows information about a group") + fun handleGroup( + commandSender: ICommandSender, + @CommandArgument("group", PermissionGroupCommandSuggestionProvider::class) group: String + ) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + commandSender.sendMessage("Group: " + permissionGroup.getName()) + permissionGroup.getPermissions().forEach { + commandSender.sendMessage("- ${it.permissionString} : ${it.active}") + } + } + + @CommandSubPath("group permission add ", "Adds a permission to a group") + fun handleGroupPermissionAdd( + commandSender: ICommandSender, + @CommandArgument( + "group", + PermissionGroupCommandSuggestionProvider::class + ) group: String, + @CommandArgument("permission") permission: String, + @CommandArgument("active") active: String + ) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + permissionGroup.addPermission(Permission(permission, -1, active.toBoolean())) + permissionGroup as PermissionGroup + permissionGroup.update() + commandSender.sendProperty( + "module.permission.command.perms.group.permission-added", + permission, + permissionGroup.getName() + ) + } + + @CommandSubPath("group permission add ", "Adds a permission to a group") + fun handleGroupPermissionAdd( + commandSender: ICommandSender, + @CommandArgument( + "group", + PermissionGroupCommandSuggestionProvider::class + ) group: String, + @CommandArgument("permission") permission: String + ) { + handleGroupPermissionAdd(commandSender, group, permission, true.toString()) + } + + @CommandSubPath("group permission remove ", "Removes a permission from a group") + fun handleGroupPermissionRemove( + commandSender: ICommandSender, + @CommandArgument( + "group", + PermissionGroupCommandSuggestionProvider::class + ) group: String, + @CommandArgument("permission") permission: String + ) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + if (!permissionGroup.hasPermission(permission)) { + commandSender.sendProperty("module.permission.command.perms.group.permission.already-removed") + return + } + permissionGroup.removePermission(permission) + permissionGroup as PermissionGroup + permissionGroup.update() + commandSender.sendProperty("module.permission.command.perms.group.permission.removed", permission) + } + + @CommandSubPath("group inheritance add ", "Inherits the group from the other group") + fun handleInheritanceAdd( + commandSender: ICommandSender, + @CommandArgument("group", PermissionGroupCommandSuggestionProvider::class) group: String, + @CommandArgument( + "otherGroup", + PermissionGroupCommandSuggestionProvider::class + ) otherGroup: String + ) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + val otherPermissionGroup = getPermissionGroupByName(otherGroup) + if (otherPermissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.other-group.not-exist") + return + } + if (otherPermissionGroup == permissionGroup) { + commandSender.sendProperty("module.permission.command.perms.inheritance.self-error") + return + } + if (otherPermissionGroup.getAllInheritedPermissionGroups().contains(permissionGroup)) { + commandSender.sendProperty("module.permission.command.perms.inheritance.recursive-error") + return + } + if (permissionGroup.addInheritedPermissionGroup(otherPermissionGroup)) { + commandSender.sendProperty( + "module.permission.command.perms.inheritance.add.success", + permissionGroup.getName(), + otherPermissionGroup.getName() + ) + } else { + commandSender.sendProperty( + "module.permission.command.perms.inheritance.add.failure", + permissionGroup.getName(), + otherPermissionGroup.getName() + ) + } + permissionGroup as PermissionGroup + permissionGroup.update() + } + + @CommandSubPath( + "group inheritance remove ", + "Removes the inheritance from the group to the other group" + ) + fun handleInheritanceRemove( + commandSender: ICommandSender, + @CommandArgument( + "group", + PermissionGroupCommandSuggestionProvider::class + ) group: String, + @CommandArgument( + "otherGroup", + PermissionGroupCommandSuggestionProvider::class + ) otherGroup: String + ) { + val permissionGroup = getPermissionGroupByName(group) + if (permissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.group-not-exist") + return + } + val otherPermissionGroup = getPermissionGroupByName(otherGroup) + if (otherPermissionGroup == null) { + commandSender.sendProperty("module.permission.command.perms.other-group.not-exist") + return + } + + if (permissionGroup.removeInheritedPermissionGroup(otherPermissionGroup)) { + commandSender.sendProperty( + "module.permission.command.perms.inheritance.remove.success", + permissionGroup.getName(), + otherPermissionGroup.getName() + ) + } else { + commandSender.sendProperty( + "module.permission.command.perms.inheritance.remove.failure", + permissionGroup.getName(), + otherPermissionGroup.getName() + ) + } + permissionGroup as PermissionGroup + permissionGroup.update() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionGroupCommandSuggestionProvider.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionGroupCommandSuggestionProvider.kt new file mode 100644 index 000000000..ef1e517ce --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/command/PermissionGroupCommandSuggestionProvider.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager.command + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.provider.ICommandSuggestionProvider +import eu.thesimplecloud.module.permission.PermissionPool + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 18:39 + */ +class PermissionGroupCommandSuggestionProvider : ICommandSuggestionProvider { + + override fun getSuggestions(sender: ICommandSender, fullCommand: String, lastArgument: String): List { + return PermissionPool.instance.getPermissionGroupManager().getAllPermissionGroups().map { it.getName() } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionGroupConfigsLoader.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionGroupConfigsLoader.kt new file mode 100644 index 000000000..f6184c70a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionGroupConfigsLoader.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager.config + +import eu.thesimplecloud.api.config.AbstractMultipleConfigLoader +import eu.thesimplecloud.module.permission.group.PermissionGroup +import eu.thesimplecloud.module.permission.permission.Permission +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 12.12.2020 + * Time: 11:29 + * @author Frederick Baier + */ +class PermissionGroupConfigsLoader : AbstractMultipleConfigLoader( + PermissionGroup::class.java, + File("modules/permissions/groups/"), + getDefaultGroups(), + true +) { + + companion object { + fun getDefaultGroups(): List { + val adminGroup = PermissionGroup("Admin", 100) + adminGroup.addPermission(Permission("*", -1, true)) + val defaultGroup = PermissionGroup("default", 0) + return listOf(adminGroup, defaultGroup) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfig.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfig.kt new file mode 100644 index 000000000..9fb1cd326 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfig.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager.config + +/** + * Created by IntelliJ IDEA. + * Date: 21.06.2020 + * Time: 16:18 + * @author Frederick Baier + */ + +class PermissionModuleConfig( + val defaultPermissionGroupName: String = "default" +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfigLoader.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfigLoader.kt new file mode 100644 index 000000000..a4c6f0f04 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/manager/config/PermissionModuleConfigLoader.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.manager.config + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 12.12.2020 + * Time: 11:26 + * @author Frederick Baier + */ +class PermissionModuleConfigLoader : AbstractJsonLibConfigLoader( + PermissionModuleConfig::class.java, + File("modules/permissions/config.json"), + { PermissionModuleConfig() }, + true +) { +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketInGetDefaultGroupName.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketInGetDefaultGroupName.kt new file mode 100644 index 000000000..7d8472133 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketInGetDefaultGroupName.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.packet + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.module.permission.PermissionPool + +/** + * Created by IntelliJ IDEA. + * Date: 12.12.2020 + * Time: 12:36 + * @author Frederick Baier + */ +class PacketInGetDefaultGroupName : ObjectPacket() { + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return success(PermissionPool.instance.getPermissionGroupManager().getDefaultPermissionGroupName()) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketOutGetDefaultGroupName.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketOutGetDefaultGroupName.kt new file mode 100644 index 000000000..6a552b705 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/packet/PacketOutGetDefaultGroupName.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.packet + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +/** + * Created by IntelliJ IDEA. + * Date: 12.12.2020 + * Time: 12:23 + * @author Frederick Baier + */ +class PacketOutGetDefaultGroupName() : ObjectPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return unit() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/permission/Permission.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/permission/Permission.kt new file mode 100644 index 000000000..d1af75fe5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/permission/Permission.kt @@ -0,0 +1,73 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.permission + + +data class Permission(val permissionString: String, val timeoutTimestamp: Long, val active: Boolean) { + + fun isExpired(): Boolean = (System.currentTimeMillis() > timeoutTimestamp) && timeoutTimestamp != -1L + + + fun matches(permission: String): Boolean { + return if (isExpired()) { + false + } else { + return matchesPermission(permission) + } + } + + private fun matchesPermission(permission: String): Boolean { + val endsWithStar = this.permissionString.endsWith(".*") + return if (endsWithStar) { + matchesWithStarAtTheEnd(permission) + } else { + isPermissionToCheckEqualToThisPermission(permission) + } + } + + private fun isPermissionToCheckEqualToThisPermission(permission: String): Boolean { + return permission == this.permissionString + } + + private fun matchesWithStarAtTheEnd(permission: String): Boolean { + val checkPermissionComponents = permission.split(".") + val thisPermissionComponents = this.permissionString.split(".") + + val isPermissionToCheckLongEnough = checkPermissionComponents.size >= thisPermissionComponents.size + return if (isPermissionToCheckLongEnough) { + areAllPermissionComponentsEqual(checkPermissionComponents, thisPermissionComponents) + } else { + false + } + } + + private fun areAllPermissionComponentsEqual( + checkPermissionComponents: List, + thisPermissionComponents: List + ): Boolean { + val thisPermissionComponentsWithoutStar = thisPermissionComponents.dropLast(1) + val checkComponentsWithLimit = checkPermissionComponents.take(thisPermissionComponentsWithoutStar.size) + return checkComponentsWithLimit == thisPermissionComponentsWithoutStar + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/IPermissionPlayer.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/IPermissionPlayer.kt new file mode 100644 index 000000000..9dee39060 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/IPermissionPlayer.kt @@ -0,0 +1,113 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.IOfflineCloudPlayer +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.entity.IPermissionEntity +import eu.thesimplecloud.module.permission.group.IPermissionGroup +import java.util.* + +interface IPermissionPlayer : IPermissionEntity, Nameable { + + /** + * Returns the uuid of this player + */ + fun getUniqueId(): UUID + + /** + * Returns the highest [IPermissionGroup] of this player + */ + fun getHighestPermissionGroup(): IPermissionGroup { + return getAllNotExpiredPermissionGroups().maxByOrNull { it.getPriority() }!! + } + + /** + * Returns the permission group info list + */ + fun getPermissionGroupInfoList(): Collection + + /** + * Returns the permission group info list + */ + fun getAllNotExpiredPermissionGroupInfoList(): Collection = + getPermissionGroupInfoList().filter { !it.isExpired() } + + /** + * Returns whether this player has the specified permission group. + * (case insensitive) + */ + fun hasPermissionGroup(name: String): Boolean = getPermissionGroupInfoList() + .map { it.permissionGroupName.toLowerCase() } + .contains(name.toLowerCase()) + + /** + * Returns the [IPermissionGroup] of this player + */ + fun getAllNotExpiredPermissionGroups(): List = getAllNotExpiredPermissionGroupInfoList() + .mapNotNull { + PermissionPool.instance.getPermissionGroupManager().getPermissionGroupByName(it.permissionGroupName) + } + + /** + * Returns the [IOfflineCloudPlayer] of this permission player wrapped in a promise + */ + fun getOfflineCloudPlayer(): ICommunicationPromise = + CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(getUniqueId()) + + /** + * Returns a promise that is completed when the operation is done. [ICommunicationPromise.isSuccess] indicates success or failure. + */ + fun update(): ICommunicationPromise + + /** + * Adds a permission group to this player + */ + fun addPermissionGroup(group: PlayerPermissionGroupInfo) + + /** + * Removes a permission group from this player + */ + fun removePermissionGroup(name: String) + + /** + * Clears all groups + */ + fun clearGroups() + + override fun hasPermission(permission: String): Boolean { + val permissionByName = super.getNotExpiredPermissionByMatch(permission) + if (permissionByName != null) return permissionByName.active + + val anyGroupPermission = getAllNotExpiredPermissionGroups().any { it.hasPermission(permission) } + return if (anyGroupPermission) { + true + } else { + hasAllRights() + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/OfflinePlayerExtension.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/OfflinePlayerExtension.kt new file mode 100644 index 000000000..73b8a0113 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/OfflinePlayerExtension.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.player + +import eu.thesimplecloud.api.player.IOfflineCloudPlayer + + +fun IOfflineCloudPlayer.getPermissionPlayer(): IPermissionPlayer { + return this.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue()!! +} + +fun IOfflineCloudPlayer.getPermissionPlayerSafe(): IPermissionPlayer? { + return this.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue() +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PermissionPlayer.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PermissionPlayer.kt new file mode 100644 index 000000000..437e38cce --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PermissionPlayer.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.player + +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.flatten +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.entity.PermissionEntity +import java.util.* +import java.util.concurrent.CopyOnWriteArrayList + +class PermissionPlayer( + @Volatile private var name: String, + private val uniqueId: UUID, + private val permissionGroupInfoList: CopyOnWriteArrayList = CopyOnWriteArrayList() +) : PermissionEntity(), IPermissionPlayer { + + override fun getName(): String = this.name + + override fun getUniqueId(): UUID = this.uniqueId + + override fun getPermissionGroupInfoList(): Collection { + if (!permissionGroupInfoList.map { it.permissionGroupName } + .contains(PermissionPool.instance.getPermissionGroupManager().getDefaultPermissionGroupName())) + permissionGroupInfoList.add( + PlayerPermissionGroupInfo( + PermissionPool.instance.getPermissionGroupManager().getDefaultPermissionGroupName(), -1 + ) + ) + return permissionGroupInfoList + } + + override fun update(): ICommunicationPromise { + return getOfflineCloudPlayer().then { + it.setProperty(PROPERTY_NAME, this) + it.update() + }.flatten() + } + + override fun addPermissionGroup(group: PlayerPermissionGroupInfo) { + removePermissionGroup(group.permissionGroupName) + this.permissionGroupInfoList.add(group) + } + + override fun removePermissionGroup(name: String) { + this.permissionGroupInfoList.removeIf { it.permissionGroupName == name } + } + + override fun clearGroups() { + this.permissionGroupInfoList.clear() + } + + fun setName(name: String) { + this.name = name + } + + companion object { + const val PROPERTY_NAME = "simplecloud-module-permission-player" + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PlayerPermissionGroupInfo.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PlayerPermissionGroupInfo.kt new file mode 100644 index 000000000..c3c6fe8a0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/PlayerPermissionGroupInfo.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.player + +class PlayerPermissionGroupInfo(val permissionGroupName: String, val timeoutTimestamp: Long) { + + fun isExpired(): Boolean = (System.currentTimeMillis() > timeoutTimestamp) && timeoutTimestamp != -1L +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/manager/IPermissionPlayerManager.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/manager/IPermissionPlayerManager.kt new file mode 100644 index 000000000..ffd4f46d0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/player/manager/IPermissionPlayerManager.kt @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.player.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.module.permission.player.IPermissionPlayer +import eu.thesimplecloud.module.permission.player.PermissionPlayer +import java.util.* + +interface IPermissionPlayerManager { + + + /** + * Returns a list of all cached permission players + */ + fun getAllCachedPermissionPlayers(): List = + CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects() + .mapNotNull { it.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue() } + + /** + * Returns the first [IPermissionPlayer] found by the specified [name] + */ + fun getCachedPermissionPlayer(name: String): IPermissionPlayer? = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(name) + ?.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue() + + /** + * Returns the first [IPermissionPlayer] found by the specified [uniqueId] + */ + fun getCachedPermissionPlayer(uniqueId: UUID): IPermissionPlayer? = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + ?.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue() + + /** + * Sends a packet to the manager to get the requested [IPermissionPlayer] and returns its result + */ + fun getPermissionPlayer(name: String): ICommunicationPromise = + CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(name) + .then { it.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue() } + + /** + * Sends a packet to the manager to get the requested [IPermissionPlayer] and returns its result + */ + fun getPermissionPlayer(uniqueId: UUID): ICommunicationPromise = + CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(uniqueId) + .then { it.getProperty(PermissionPlayer.PROPERTY_NAME)?.getValue() } + + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeeListener.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeeListener.kt new file mode 100644 index 000000000..1bf433eb5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeeListener.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.bungee + +import eu.thesimplecloud.module.permission.PermissionPool +import net.md_5.bungee.api.connection.ProxiedPlayer +import net.md_5.bungee.api.event.PermissionCheckEvent +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.event.EventHandler + +class BungeeListener : Listener { + + @EventHandler + fun on(event: PermissionCheckEvent) { + val sender = event.sender + if (sender is ProxiedPlayer) { + val permissionPlayer = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(sender.uniqueId) + if (permissionPlayer == null) { + println("WARNING: PermissionPlayer is NULL (${sender.name})") + return + } + event.setHasPermission(permissionPlayer.hasPermission(event.permission)) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeePluginMain.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeePluginMain.kt new file mode 100644 index 000000000..fa7c02af2 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/bungee/BungeePluginMain.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.bungee + +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.group.manager.PermissionGroupManager +import net.md_5.bungee.api.plugin.Plugin + +class BungeePluginMain : Plugin() { + + override fun onEnable() { + PermissionPool(PermissionGroupManager()) + this.proxy.pluginManager.registerListener(this, BungeeListener()) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/BukkitCloudPermissibleBase.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/BukkitCloudPermissibleBase.kt new file mode 100644 index 000000000..41b2e5e40 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/BukkitCloudPermissibleBase.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.spigot + +import eu.thesimplecloud.module.permission.PermissionPool +import org.bukkit.entity.Player +import org.bukkit.permissions.PermissibleBase +import org.bukkit.permissions.Permission + +class BukkitCloudPermissibleBase(private val player: Player) : PermissibleBase(player) { + + + fun getPermissionPlayer() = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(player.uniqueId) + + override fun isPermissionSet(name: String): Boolean { + return getPermissionPlayer()?.hasPermission(name) ?: false + } + + override fun isPermissionSet(perm: Permission): Boolean { + return getPermissionPlayer()?.hasPermission(perm.name) ?: false + } + + override fun hasPermission(inName: String): Boolean { + if (inName.equals("bukkit.broadcast.user", ignoreCase = true)) { + return true + } + if (getPermissionPlayer() == null) + println("WARNING: PermissionPlayer of " + player.uniqueId + " is null.") + + return getPermissionPlayer()?.hasPermission(inName) ?: false + } + + override fun hasPermission(perm: Permission): Boolean { + return getPermissionPlayer()?.hasPermission(perm.name) ?: false + } + + override fun isOp(): Boolean { + return getPermissionPlayer()?.hasAllRights() ?: false + } + + override fun recalculatePermissions() { + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotListener.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotListener.kt new file mode 100644 index 000000000..71807e62b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotListener.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.spigot + +import eu.thesimplecloud.module.permission.service.spigot.util.ReflectionUtils +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerLoginEvent +import java.lang.reflect.Field + +class SpigotListener : Listener { + + + @EventHandler(priority = EventPriority.LOWEST) + fun on(event: PlayerLoginEvent) { + try { + val clazz: Class<*>? = ReflectionUtils.reflectCraftClazz(".entity.CraftHumanEntity") + var field: Field? = null + if (clazz != null) { + field = clazz.getDeclaredField("perm") + } + if (field == null) { + println("WARNING: Permission field was null") + return + } + field.isAccessible = true + field[event.player] = BukkitCloudPermissibleBase(event.player) + } catch (ex: NoSuchFieldException) { + ex.printStackTrace() + } catch (ex: SecurityException) { + ex.printStackTrace() + } catch (ex: IllegalArgumentException) { + ex.printStackTrace() + } catch (ex: IllegalAccessException) { + ex.printStackTrace() + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotPluginMain.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotPluginMain.kt new file mode 100644 index 000000000..7160642b1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/SpigotPluginMain.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.spigot + + +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.group.manager.PermissionGroupManager +import org.bukkit.plugin.java.JavaPlugin + +class SpigotPluginMain : JavaPlugin() { + + + override fun onEnable() { + PermissionPool(PermissionGroupManager()) + this.server.pluginManager.registerEvents(SpigotListener(), this) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/util/ReflectionUtils.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/util/ReflectionUtils.kt new file mode 100644 index 000000000..ccb868e87 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/spigot/util/ReflectionUtils.kt @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.spigot.util + +import org.bukkit.Bukkit + +class ReflectionUtils { + + companion object { + fun reflectCraftClazz(suffix: String): Class<*>? { + try { + val version = Bukkit.getServer().javaClass.getPackage().name.split(".").toTypedArray()[3] + return Class.forName("org.bukkit.craftbukkit.$version$suffix") + } catch (ex: Exception) { + ex.printStackTrace() + try { + return Class.forName("org.bukkit.craftbukkit$suffix") + } catch (e: ClassNotFoundException) { + e.printStackTrace() + } + } + return null + } + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPermissionProvider.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPermissionProvider.kt new file mode 100644 index 000000000..cb65d7c96 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPermissionProvider.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.velocity + +import com.velocitypowered.api.permission.PermissionFunction +import com.velocitypowered.api.permission.PermissionProvider +import com.velocitypowered.api.permission.PermissionSubject +import com.velocitypowered.api.permission.Tristate +import com.velocitypowered.api.proxy.Player +import eu.thesimplecloud.module.permission.PermissionPool + +class VelocityPermissionProvider : PermissionProvider { + + override fun createFunction(subject: PermissionSubject): PermissionFunction? { + if (subject !is Player) return PermissionFunction.ALWAYS_TRUE + return CloudPermissionFunction(subject) + } + + private class CloudPermissionFunction(private val player: Player) : PermissionFunction { + + + override fun getPermissionValue(permission: String?): Tristate { + if (permission == null) return Tristate.FALSE + val permissionPlayer = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(player.uniqueId) + if (permissionPlayer == null) { + println("WARNING: PermissionPlayer is NULL (${player.username})") + return Tristate.FALSE + } + + return Tristate.fromBoolean(permissionPlayer.hasPermission(permission)) + } + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPluginMain.kt b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPluginMain.kt new file mode 100644 index 000000000..afb46ad85 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/kotlin/eu/thesimplecloud/module/permission/service/velocity/VelocityPluginMain.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.permission.service.velocity + +import com.google.inject.Inject +import com.velocitypowered.api.event.Subscribe +import com.velocitypowered.api.event.permission.PermissionsSetupEvent +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent +import com.velocitypowered.api.plugin.Dependency +import com.velocitypowered.api.plugin.Plugin +import com.velocitypowered.api.proxy.ProxyServer +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.permission.group.manager.PermissionGroupManager + +@Plugin(id = "simplecloud_permission", dependencies = [Dependency(id = "simplecloud_plugin")]) +class VelocityPluginMain @Inject constructor(val proxyServer: ProxyServer) { + + private val permissionProvider = VelocityPermissionProvider() + + @Subscribe + fun on(event: ProxyInitializeEvent) { + PermissionPool(PermissionGroupManager()) + } + + @Subscribe + fun on(event: PermissionsSetupEvent) { + event.provider = this.permissionProvider + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/bungee.yml b/simplecloud-modules/simplecloud-module-permission/src/main/resources/bungee.yml new file mode 100644 index 000000000..5b32451bf --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/bungee.yml @@ -0,0 +1,6 @@ +name: SimpleCloud-Permissions +version: 1.0 +author: Wetterbericht +depend: [ SimpleCloudAPI ] + +main: eu.thesimplecloud.module.permission.service.bungee.BungeePluginMain \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/de.json new file mode 100644 index 000000000..06789775f --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/de.json @@ -0,0 +1,26 @@ +{ + "module.permission.command.perms.group-already-exist": "§cDiese Gruppe existiert bereits.", + "module.permission.command.perms.group-not-exist": "§cDie Gruppe wurde nicht gefunden.", + "module.permission.command.perms.group.created": "§7Die Gruppe §e%GROUP% wurde erstellt.", + "module.permission.command.perms.group.deleted": "§7Die Gruppe §e%GROUP% wurde gelöscht.", + "module.permission.command.perms.group.permission-added": "§7Die Permission %PERMISSION% wurde zur Gruppe %GROUP% hinzugefügt.", + "module.permission.command.perms.group.permission.already-removed": "§cDie Gruppe hat diese Permission nicht.", + "module.permission.command.perms.group.permission.removed": "§7Die Permission §e%PERMISSION% §7wurde entfernt.", + "module.permission.command.perms.inheritance.add.failure": "§cDie Gruppe %GROUP% erbt bereits von %OTHER_GROUP%", + "module.permission.command.perms.inheritance.add.success": "§7Die Gruppe §e%GROUP% §7erbt jetzt von §e%OTHER_GROUP%", + "module.permission.command.perms.inheritance.recursive-error": "§cDie andere Gruppe erbt bereits von dieser Gruppe.", + "module.permission.command.perms.inheritance.remove.failure": "§cDie Gruppe §e%GROUP% §7erbt nicht von §e%OTHER_GROUP%", + "module.permission.command.perms.inheritance.remove.success": "§7Die Gruppe §e%GROUP% §7erbt nun nicht mehr von §e%OTHER_GROUP%", + "module.permission.command.perms.inheritance.self-error": "§cEine Gruppe kann nicht von sich selber erben.", + "module.permission.command.perms.other-group.not-exist": "§cDie andere Gruppe wurde nicht gefunden.", + "module.permission.command.perms.user-not-exist": "§cBenutzer nicht gefunden.", + "module.permission.command.perms.user.day-invalid": "§cDieser Tag ist ungültig.", + "module.permission.command.perms.user.group-not-exist": "§cGruppe nicht gefunden.", + "module.permission.command.perms.user.group.added.days": "§aDie Permission %PERMISSION% wurde für %DAYS% Tage zu Spieler %PLAYER% hinzugefügt.", + "module.permission.command.perms.user.group.added.lifetime": "§aDie Gruppe %GROUP% wurde lebenslänglich zu Spieler %PLAYER% hinzugefügt.", + "module.permission.command.perms.user.group.removed": "§7Die Gruppe §e%GROUP% §7wurde von Spieler %PLAYER% entfernt.", + "module.permission.command.perms.user.group.set": "§7Die Gruppe §e%GROUP% §7wurde Spieler %PLAYER% gesetzt.", + "module.permission.command.perms.user.permission.added.lifetime": "§aDie Permission %PERMISSION% wurde lebenslänglich zu Spieler %PLAYER% hinzugefügt.", + "module.permission.command.perms.user.permission.already-removed": "§cDer Benutzer hat diese Permission nicht.", + "module.permission.command.perms.user.permission.removed": "§7Die Permission §e%PERMISSION% §7wurde entfernt." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/en.json new file mode 100644 index 000000000..98c4b867f --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/languages/en.json @@ -0,0 +1,26 @@ +{ + "module.permission.command.perms.group-already-exist": "§cGroup already exist.", + "module.permission.command.perms.group-not-exist": "§cGroup not found.", + "module.permission.command.perms.group.created": "§7Group §e%GROUP% created.", + "module.permission.command.perms.group.deleted": "§7Group §e%GROUP% deleted.", + "module.permission.command.perms.group.permission-added": "§7Added permission %PERMISSION% to group %GROUP%.", + "module.permission.command.perms.group.permission.already-removed": "§cThe group doesn't have the specified permission.", + "module.permission.command.perms.group.permission.removed": "§7Permission §e%PERMISSION% §7removed.", + "module.permission.command.perms.inheritance.add.failure": "§cGroup %GROUP% is already inheriting from %OTHER_GROUP%", + "module.permission.command.perms.inheritance.add.success": "§7Group §e%GROUP% §7is now inheriting from §e%OTHER_GROUP%", + "module.permission.command.perms.inheritance.recursive-error": "§cThe other group is already inheriting the group.", + "module.permission.command.perms.inheritance.remove.failure": "§cGroup §e%GROUP% §7is not inheriting from §e%OTHER_GROUP%", + "module.permission.command.perms.inheritance.remove.success": "§7Group §e%GROUP% §7is no longer inheriting from §e%OTHER_GROUP%", + "module.permission.command.perms.inheritance.self-error": "§cThe group cannot inherit from itself.", + "module.permission.command.perms.other-group.not-exist": "§cOther group not found.", + "module.permission.command.perms.user-not-exist": "§cUser not found.", + "module.permission.command.perms.user.day-invalid": "§cThe specified day is invalid.", + "module.permission.command.perms.user.group-not-exist": "§cGroup not found.", + "module.permission.command.perms.user.group.added.days": "§aAdded permission %PERMISSION% for %DAYS% days to %PLAYER%", + "module.permission.command.perms.user.group.added.lifetime": "§aAdded group %GROUP% lifetime to %PLAYER%", + "module.permission.command.perms.user.group.removed": "§7Group §e%GROUP% §7removed from %PLAYER%.", + "module.permission.command.perms.user.group.set": "§7Set group §e%GROUP% §7to %PLAYER%.", + "module.permission.command.perms.user.permission.added.lifetime": "§aAdded permission %PERMISSION% lifetime to %PLAYER%", + "module.permission.command.perms.user.permission.already-removed": "§cThe user doesn't have the specified permission.", + "module.permission.command.perms.user.permission.removed": "§7Permission §e%PERMISSION% §7removed." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-permission/src/main/resources/module.json new file mode 100644 index 000000000..8f47a2edc --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Permission", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.permission.manager.PermissionModule", + "moduleCopyType": "ALL", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/plugin.yml b/simplecloud-modules/simplecloud-module-permission/src/main/resources/plugin.yml new file mode 100644 index 000000000..af3e83af4 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/plugin.yml @@ -0,0 +1,11 @@ +name: SimpleCloud-Permission +version: 1.0 +author: Wetterbericht + +main: eu.thesimplecloud.module.permission.service.spigot.SpigotPluginMain + +depend: [ SimpleCloud-Plugin ] + +api-version: 1.13 + +commands: diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-permission/src/main/resources/updater.json new file mode 100644 index 000000000..9e49869ac --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-permission", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/main/resources/velocity-plugin.json b/simplecloud-modules/simplecloud-module-permission/src/main/resources/velocity-plugin.json new file mode 100644 index 000000000..ff39dcbf1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/main/resources/velocity-plugin.json @@ -0,0 +1,9 @@ +{ + "id": "simplecloud_permission", + "name": "SimpleCloud-Permission", + "version": "1.0", + "authors": [ + "Wetterbericht" + ], + "main": "eu.thesimplecloud.module.permission.service.velocity.VelocityPluginMain" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-permission/src/test/kotlin/eu/thesimplecloud/permission/PermissionTest.kt b/simplecloud-modules/simplecloud-module-permission/src/test/kotlin/eu/thesimplecloud/permission/PermissionTest.kt new file mode 100644 index 000000000..791546ec3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-permission/src/test/kotlin/eu/thesimplecloud/permission/PermissionTest.kt @@ -0,0 +1,71 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.permission + +import eu.thesimplecloud.module.permission.permission.Permission +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +/** + * Created by IntelliJ IDEA. + * Date: 24.06.2020 + * Time: 16:49 + * @author Frederick Baier + */ +class PermissionTest { + + @Test + fun testNormalPermission() { + val permission = createNeverTimeoutPermission("permission.test") + assertTrue(permission.matches("permission.test")) + assertFalse(permission.matches("permission.otherTest")) + } + + @Test + fun testStarPermission() { + val permission = createNeverTimeoutPermission("permission.test.*") + assertTrue(permission.matches("permission.test.test")) + assertFalse(permission.matches("permission.test")) + assertFalse(permission.matches("permission.otherTest")) + } + + private fun createNeverTimeoutPermission(permissionString: String): Permission { + return Permission(permissionString, Long.MAX_VALUE, true) + } + + @Test + fun testPermissionNotActive() { + val permission = Permission("permission.test", Long.MAX_VALUE, false) + assertTrue(permission.matches("permission.test")) + assertFalse(permission.matches("permission.otherTest")) + } + + @Test + fun testPermissionExpired() { + val permission = Permission("permission.test", Long.MIN_VALUE, true) + assertFalse(permission.matches("permission.test")) + assertFalse(permission.matches("permission.otherTest")) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/build.gradle b/simplecloud-modules/simplecloud-module-placeholders/build.gradle new file mode 100644 index 000000000..735a4cd96 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/build.gradle @@ -0,0 +1,24 @@ +shadowJar { + archiveFileName.set("SimpleCloud-Placeholders.jar") +} + +repositories { + maven { + url "https://repo.extendedclip.com/content/repositories/placeholderapi/" + } +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-plugin")) + compileOnly(project(":simplecloud-launcher")) + compileOnly(project(":simplecloud-modules:simplecloud-module-permission")) + compileOnly(project(":simplecloud-modules:simplecloud-module-chat-tab")) + + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + compileOnly 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT' + + compileOnly 'me.clip:placeholderapi:2.11.1' + +} diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/manager/PlaceholdersModule.kt b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/manager/PlaceholdersModule.kt new file mode 100644 index 000000000..aa75c2a3b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/manager/PlaceholdersModule.kt @@ -0,0 +1,13 @@ +package eu.thesimplecloud.module.placeholders.manager + +import eu.thesimplecloud.api.external.ICloudModule + +class PlaceholdersModule : ICloudModule { + + override fun onEnable() { + } + + override fun onDisable() { + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/BukkitPluginMain.kt b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/BukkitPluginMain.kt new file mode 100644 index 000000000..20f072666 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/BukkitPluginMain.kt @@ -0,0 +1,28 @@ +package eu.thesimplecloud.module.placeholders.spigot + +import eu.thesimplecloud.module.placeholders.spigot.placeholderapi.PlaceholderHook +import org.bukkit.Bukkit +import org.bukkit.plugin.java.JavaPlugin + +class BukkitPluginMain : JavaPlugin() { + + val replacePermissionModule by lazy { Bukkit.getPluginManager().getPlugin("SimpleCloud-Permission") != null } + val replaceChatTabModule by lazy { Bukkit.getPluginManager().getPlugin("SimpleCloud-Chat-Tab") != null } + + override fun onEnable() { + + if(!replacePermissionModule) { + println("Could not replace placeholders for permission module. Please make sure that the permission module is loaded correctly if you want to use placeholders for that.") + } + + if(!replaceChatTabModule) { + println("Could not replace placeholders for chat-tab module. Please make sure that the chat-tab module is loaded correctly if you want to use placeholders for that.") + } + + val register = PlaceholderHook(this).register() + + if(register) println("[INFO] Registered PlaceholderAPI hook successfully!") + else println("[FATAL] Failed to register PlaceholderAPI hook!") + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/StringExtension.kt b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/StringExtension.kt new file mode 100644 index 000000000..b500d9572 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/StringExtension.kt @@ -0,0 +1,108 @@ +package eu.thesimplecloud.module.placeholders.spigot + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.prefix.service.tablist.ProxyTablistHelper +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import java.util.UUID + +fun String.replace( + uuid: UUID, + replacePermissionModule: Boolean = false, + replaceChatTabModule: Boolean = false +): String { + + var replacedString = this + + if (replacePermissionModule) { + replacedString = replacedString.replacePermissionModule(uuid) + } + + if (replaceChatTabModule) { + replacedString = replacedString.replaceChatTabModule(uuid) + } + + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(uuid).getBlockingOrNull() + val proxy = CloudAPI.instance.getCloudPlayerManager().getCloudPlayer(uuid).getBlockingOrNull()?.getConnectedProxy() + val thisService = CloudPlugin.instance.thisService() + val wrapper = proxy?.getWrapper() + val cloudPlayerManager = CloudAPI.instance.getCloudPlayerManager() + + return replacedString + .replace("%ONLINE_PLAYERS%", cloudPlayerManager.getNetworkOnlinePlayerCount().get().toString()) + .replace("%MAX_PLAYERS%", proxy?.getMaxPlayers().toString()) + .replace("%REGISTERED_PLAYER_COUNT%", cloudPlayerManager.getRegisteredPlayerCount().get().toString()) + + .replace("%WRAPPER%", wrapper?.getName().toString()) + .replace("%WRAPPER_HOST%", wrapper?.getHost().toString()) + .replace("%WRAPPER_MAX_MEMORY%", wrapper?.getMaxMemory().toString()) + .replace("%WRAPPER_USED_MEMORY%", wrapper?.getUsedMemory().toString()) + .replace("%WRAPPER_CPU_USAGE%", wrapper?.getCpuUsage().toString()) + .replace("%WRAPPER_CURRENTLY_STARTING_SERVICES%", wrapper?.getCurrentlyStartingServices().toString()) + .replace("%WRAPPER_SERVICE_COUNT%", wrapper?.getServicesRunningOnThisWrapper()?.size.toString()) + + .replace("%PROXY%", proxy?.getName().toString()) + .replace("%PROXY_HOST%", proxy?.getHost().toString()) + .replace("%PROXY_STATE%", proxy?.getState().toString()) + .replace("%PROXY_NUMBER%", proxy?.getServiceNumber().toString()) + .replace("%PROXY_PORT%", proxy?.getPort().toString()) + .replace("%PROXY_DISPLAYNAME%", proxy?.getDisplayName().toString()) + .replace("%PROXY_GROUP%", proxy?.getGroupName().toString()) + .replace("%PROXY_ONLINE_PLAYERS%", proxy?.getOnlinePlayers()?.get()?.size.toString()) + .replace("%PROXY_MAX_PLAYERS%", proxy?.getMaxPlayers().toString()) + .replace("%PROXY_MAX_MEMORY%", proxy?.getMaxMemory().toString()) + .replace("%PROXY_USED_MEMORY%", proxy?.getUsedMemory().toString()) + .replace("%PROXY_TEMPLATE%", proxy?.getTemplateName().toString()) + + .replace("%SERVER%", thisService.getName()) + .replace("%SERVER_HOST%", thisService.getHost()) + .replace("%SERVER_STATE%", thisService.getState().toString()) + .replace("%SERVER_NUMBER%", thisService.getServiceNumber().toString()) + .replace("%SERVER_PORT%", thisService.getPort().toString()) + .replace("%SERVER_DISPLAYNAME%", thisService.getDisplayName()) + .replace("%SERVER_GROUP%", thisService.getGroupName()) + .replace("%SERVER_ONLINE_PLAYERS%", Bukkit.getOnlinePlayers().size.toString()) + .replace("%SERVER_MAX_PLAYERS%", Bukkit.getMaxPlayers().toString()) + .replace("%SERVER_MAX_MEMORY%", thisService.getMaxMemory().toString()) + .replace("%SERVER_USED_MEMORY%", thisService.getUsedMemory().toString()) + .replace("%SERVER_TEMPLATE%", thisService.getTemplateName()) + + .replace("%PLAYER_NAME%", cloudPlayer?.getName().toString()) + .replace("%PLAYER_PING%", Bukkit.getPlayer(uuid)?.ping.toString()) +} + +fun String.replacePermissionModule(uuid: UUID): String { + + var replacedString = this + + try { + //Using cached player because the player is definitely online when this method is called and should be cached. + val permissionPlayer = PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(uuid) + + replacedString = replacedString + .replace("%RANK_NAME%", permissionPlayer?.getHighestPermissionGroup()?.getName().toString()) + .replace("%RANK_PRIORITY%", permissionPlayer?.getHighestPermissionGroup()?.getPriority().toString()) + } catch (_: Exception) { + } + + return replacedString +} + +fun String.replaceChatTabModule(uuid: UUID): String { + + var replacedString = this + + try { + val tablistInformation = ProxyTablistHelper.getTablistInformationByUUID(uuid) + + replacedString = replacedString + .replace("%RANK_COLOR%", tablistInformation?.color.toString()) + .replace("%RANK_PREFIX%", tablistInformation?.prefix.toString()) + .replace("%RANK_SUFFIX%", tablistInformation?.suffix.toString()) + .replace("%RANK_TAB_PRIORITY%", tablistInformation?.priority.toString()) + } catch (_: Exception) { + } + + return replacedString +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/placeholderapi/PlaceholderHook.kt b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/placeholderapi/PlaceholderHook.kt new file mode 100644 index 000000000..0a68b0dde --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/kotlin/eu/thesimplecloud/module/placeholders/spigot/placeholderapi/PlaceholderHook.kt @@ -0,0 +1,24 @@ +package eu.thesimplecloud.module.placeholders.spigot.placeholderapi + +import eu.thesimplecloud.module.placeholders.spigot.BukkitPluginMain +import eu.thesimplecloud.module.placeholders.spigot.replace +import me.clip.placeholderapi.expansion.PlaceholderExpansion +import org.bukkit.OfflinePlayer + +class PlaceholderHook(private val plugin: BukkitPluginMain) : PlaceholderExpansion() { + + override fun getIdentifier(): String = "CLOUD" + + override fun getAuthor(): String = "rlqu, Panda" + + override fun getVersion(): String = "2.5.0" + + override fun canRegister(): Boolean = true + + override fun persist(): Boolean = true + + override fun onRequest(player: OfflinePlayer, params: String): String { + return ("%$params%").replace(player.uniqueId, plugin.replacePermissionModule, plugin.replaceChatTabModule) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/module.json new file mode 100644 index 000000000..b580aa821 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Placeholders", + "author": "rlqu, Panda", + "mainClass": "eu.thesimplecloud.module.placeholders.manager.PlaceholdersModule", + "moduleCopyType": "SERVER", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/plugin.yml b/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/plugin.yml new file mode 100644 index 000000000..4489bedaa --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/plugin.yml @@ -0,0 +1,15 @@ +name: SimpleCloud-Placeholders +version: 1.0 +authors: + - rlqu + - Panda + +main: eu.thesimplecloud.module.placeholders.spigot.BukkitPluginMain + +depend: + - SimpleCloud-Plugin + - PlaceholderAPI + +softdepend: + - SimpleCloud-Permission + - SimpleCloud-Chat-Tab \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/updater.json new file mode 100644 index 000000000..48c649213 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-placeholders/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-placeholders", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/build.gradle b/simplecloud-modules/simplecloud-module-proxy/build.gradle new file mode 100644 index 000000000..ff5d1b0fc --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/build.gradle @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Proxy.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-plugin")) + compileOnly(project(":simplecloud-launcher")) + compileOnly(project(":simplecloud-modules:simplecloud-module-permission")) + compileOnly(project(":simplecloud-modules:simplecloud-module-chat-tab")) + compileOnly group: 'com.google.code.gson', name: 'gson', version: '2.9.0' + compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT' + compileOnly 'com.velocitypowered:velocity-api:3.1.1' + annotationProcessor 'com.velocitypowered:velocity-api:3.1.1' +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/Config.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/Config.kt new file mode 100644 index 000000000..0423a2a89 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/Config.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.config + +import eu.thesimplecloud.api.CloudAPI + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 21:36 + */ +data class Config( + val proxyGroupConfigurations: List, + val tablistConfigurations: List, + val maintenanceKickMessage: String, + val fullProxyKickMessage: String +) { + + fun update() { + CloudAPI.instance.getGlobalPropertyHolder().setProperty("simplecloud-module-proxy-config", this) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/DefaultConfig.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/DefaultConfig.kt new file mode 100644 index 000000000..128e77a32 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/DefaultConfig.kt @@ -0,0 +1,87 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.config + +import eu.thesimplecloud.api.CloudAPI + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.03.2020 + * Time: 18:30 + */ +class DefaultConfig { + companion object { + fun get(): Config { + + val tablistConfiguration = TablistConfiguration( + listOf("Proxy"), + listOf( + " ", + "SimpleCloud » Simplify your network", + "Online » %ONLINE_PLAYERS%/%MAX_PLAYERS% Server » %DISPLAYNAME%", + "", + ), + listOf( + "", + "Twitter » @theSimpleCloud", + "Discord » discord.gg/MPZs4h8", + "Powered by » Venocix.de", + "", + ) + ) + + val config = Config( + CloudAPI.instance.getCloudServiceGroupManager().getProxyGroups() + .map { getDefaultProxyGroupConfiguration(it.getName()) }, + listOf(tablistConfiguration), + "§cThis service is in maintenance", + "§cThis service is full" + ) + + return config + } + + fun getDefaultProxyGroupConfiguration(groupName: String): ProxyGroupConfiguration { + val motdConfiguration = MotdConfiguration( + listOf("SimpleCloud » Simplify your network |<#4595ff> 1.12<#545454> - <#4595ff>1.19"), + listOf("× <#178fff>Status: <#22cc22>Online - <#ffffff>%PROXY%"), + emptyList(), + null + ) + val maintenanceMotdConfiguration = MotdConfiguration( + listOf("SimpleCloud » Simplify your network |<#4595ff> 1.12<#545454> - <#4595ff>1.19"), + listOf("× <#178fff>Status: <#c40000>Maintenance - %PROXY%"), + emptyList(), + "§4§oMaintenance" + ) + + return ProxyGroupConfiguration( + groupName, + mutableListOf("Fllip", "Wetterbericht"), + motdConfiguration, + maintenanceMotdConfiguration + ) + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/MotdConfiguration.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/MotdConfiguration.kt new file mode 100644 index 000000000..6eb6c817e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/MotdConfiguration.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.config + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 21:50 + */ + +data class MotdConfiguration( + val firstLines: List, + val secondLines: List, + val playerInfo: List?, + val versionName: String? +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/ProxyGroupConfiguration.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/ProxyGroupConfiguration.kt new file mode 100644 index 000000000..7ece424ab --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/ProxyGroupConfiguration.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.config + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 21:54 + */ + +data class ProxyGroupConfiguration( + val proxyGroup: String, + val whitelist: MutableList, + val motds: MotdConfiguration, + val maintenanceMotds: MotdConfiguration +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/TablistConfiguration.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/TablistConfiguration.kt new file mode 100644 index 000000000..b3b5ca962 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/config/TablistConfiguration.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.config + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 21:40 + */ +data class TablistConfiguration( + val proxies: List, + val headers: List, + val footers: List +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/extensions/ListExtension.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/extensions/ListExtension.kt new file mode 100644 index 000000000..e9dfda8f1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/extensions/ListExtension.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.extensions + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.03.2020 + * Time: 18:09 + */ + +fun List.mapToLowerCase(): List { + return this.map { it.lowercase() } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/GroupCreateListener.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/GroupCreateListener.kt new file mode 100644 index 000000000..bf0265ea6 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/GroupCreateListener.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager + +import eu.thesimplecloud.api.event.group.CloudServiceGroupCreatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.module.proxy.config.Config +import eu.thesimplecloud.module.proxy.config.DefaultConfig +import eu.thesimplecloud.module.proxy.service.ProxyHandler + +/** + * Created by IntelliJ IDEA. + * Date: 27.12.2020 + * Time: 18:00 + * @author Frederick Baier + */ +class GroupCreateListener(private val proxyModule: ProxyModule) : IListener { + + @CloudEventHandler + fun handle(event: CloudServiceGroupCreatedEvent) { + val currentConfig = ProxyHandler.configHolder.getValue() + val proxyGroup = event.serviceGroup + if (proxyGroup.getServiceType() != ServiceType.PROXY) return + if (proxyModule.getProxyConfiguration(proxyGroup.getName()) != null) return + + val proxyGroupConfiguration = DefaultConfig.getDefaultProxyGroupConfiguration(proxyGroup.getName()) + val newConfig = Config( + currentConfig.proxyGroupConfigurations.union(listOf(proxyGroupConfiguration)).toList(), + currentConfig.tablistConfigurations, + currentConfig.maintenanceKickMessage, + currentConfig.fullProxyKickMessage + ) + proxyModule.saveConfig(newConfig) + proxyModule.loadConfig() + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/MaintenanceToggleListener.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/MaintenanceToggleListener.kt new file mode 100644 index 000000000..bfa25ef29 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/MaintenanceToggleListener.kt @@ -0,0 +1,93 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.group.CloudServiceGroupUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.module.proxy.config.Config +import eu.thesimplecloud.module.proxy.config.ProxyGroupConfiguration +import eu.thesimplecloud.module.proxy.extensions.mapToLowerCase +import eu.thesimplecloud.module.proxy.service.ProxyHandler + +/** + * Created by IntelliJ IDEA. + * Date: 21.05.2021 + * Time: 18:51 + * @author Frederick Baier + */ +class MaintenanceToggleListener : IListener { + + private val configHolder = ProxyHandler.configHolder + + @CloudEventHandler + fun on(event: CloudServiceGroupUpdatedEvent) { + val serviceGroup = event.serviceGroup + if (serviceGroup.isInMaintenance() && serviceGroup.getServiceType() == ServiceType.PROXY) { + kickUnallowedPlayers(serviceGroup) + } + } + + private fun kickUnallowedPlayers(serviceGroup: ICloudServiceGroup) { + val allPlayers = CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects() + val playersOnline = allPlayers.filter { it.getConnectedProxy()?.getServiceGroup() == serviceGroup } + playersOnline.forEach { kickIfPermissionNotGrantedAndNotOnWhitelist(it, serviceGroup) } + } + + private fun kickIfPermissionNotGrantedAndNotOnWhitelist(player: ICloudPlayer, serviceGroup: ICloudServiceGroup) { + val hasPermissionPromise = isJoinPermissionGranted(player) + hasPermissionPromise.then { hasMaintenancePermission -> + if (!hasMaintenancePermission && !isPlayerOnWhitelist(player, serviceGroup)) + kickPlayerDueToMaintenance(player) + } + } + + private fun kickPlayerDueToMaintenance(player: ICloudPlayer) { + val config = getConfig() + player.kick(config.maintenanceKickMessage) + } + + private fun isPlayerOnWhitelist(player: ICloudPlayer, serviceGroup: ICloudServiceGroup): Boolean { + val proxyConfig = + getProxyConfigurations().firstOrNull { it.proxyGroup == serviceGroup.getName() } ?: return false + return proxyConfig.whitelist.mapToLowerCase().contains(player.getName().toLowerCase()) + } + + private fun isJoinPermissionGranted(player: ICloudPlayer): ICommunicationPromise { + return player.hasPermission(ProxyHandler.JOIN_MAINTENANCE_PERMISSION) + } + + private fun getProxyConfigurations(): List { + return getConfig().proxyGroupConfigurations + } + + private fun getConfig(): Config { + return this.configHolder.getValue() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/ProxyModule.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/ProxyModule.kt new file mode 100644 index 000000000..4020cc8c2 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/ProxyModule.kt @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.proxy.config.Config +import eu.thesimplecloud.module.proxy.config.DefaultConfig +import eu.thesimplecloud.module.proxy.config.ProxyGroupConfiguration +import eu.thesimplecloud.module.proxy.manager.commands.ProxyCommand +import eu.thesimplecloud.module.proxy.manager.converter.ConfigConverter +import eu.thesimplecloud.module.proxy.service.ProxyHandler +import java.io.File + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 21:31 + */ +class ProxyModule : ICloudModule { + + private val configFile = File("modules/proxy", "config.json") + + override fun onEnable() { + loadConfig() + Launcher.instance.commandManager + .registerCommand(this, ProxyCommand(this)) + + CloudAPI.instance.getEventManager().registerListener(this, GroupCreateListener(this)) + CloudAPI.instance.getEventManager().registerListener(this, MaintenanceToggleListener()) + } + + override fun onDisable() { + } + + fun loadConfig() { + ConfigConverter().convertIfNecessary() + if (!configFile.exists()) { + val config = DefaultConfig.get() + saveConfig(config) + } + + val config = JsonLib.fromJsonFile(configFile)!!.getObject(Config::class.java) + ProxyHandler.configHolder = Property(config) + config.update() + } + + fun saveConfig(config: Config) { + JsonLib.fromObject(config).saveAsFile(configFile) + } + + fun saveConfig() { + saveConfig(getConfig()) + } + + fun getProxyConfiguration(serviceGroupName: String): ProxyGroupConfiguration? { + return getConfig().proxyGroupConfigurations.firstOrNull { it.proxyGroup == serviceGroupName } + } + + fun getConfig(): Config { + return ProxyHandler.configHolder.getValue() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/commands/ProxyCommand.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/commands/ProxyCommand.kt new file mode 100644 index 000000000..01f33e4c5 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/commands/ProxyCommand.kt @@ -0,0 +1,102 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager.commands + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.proxy.extensions.mapToLowerCase +import eu.thesimplecloud.module.proxy.manager.ProxyModule + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.03.2020 + * Time: 17:51 + */ + +@Command("proxy", CommandType.CONSOLE_AND_INGAME, "cloud.module.proxy") +class ProxyCommand(val module: ProxyModule) : ICommandHandler { + + private val propertyPrefix = "module.proxy.command." + + @CommandSubPath("reload", "Reloads the proxy module") + fun handleReload(sender: ICommandSender) { + module.loadConfig() + sender.sendProperty("${propertyPrefix}reload") + } + + @CommandSubPath(" whitelist add ", "Adds a player to whitelist") + fun handleWhitelistAdd( + sender: ICommandSender, @CommandArgument("proxyName") proxyName: String, + @CommandArgument("playerName") playerName: String + ) { + val proxyConfiguration = module.getProxyConfiguration(proxyName) + + if (proxyConfiguration == null) { + sender.sendProperty("${propertyPrefix}whitelist.proxy-not-found") + return + } + + if (proxyConfiguration.whitelist.mapToLowerCase().contains(playerName.lowercase())) { + sender.sendProperty("${propertyPrefix}whitelist.already-whitelisted") + return + } + + proxyConfiguration.whitelist.add(playerName) + + module.getConfig().update() + module.saveConfig() + + sender.sendProperty("${propertyPrefix}whitelist.added", playerName) + } + + @CommandSubPath(" whitelist remove ", "Removes a player from whitelist") + fun handleWhitelistRemove( + sender: ICommandSender, @CommandArgument("proxyName") proxyName: String, + @CommandArgument("playerName") playerName: String + ) { + val proxyConfiguration = module.getProxyConfiguration(proxyName) + + if (proxyConfiguration == null) { + sender.sendProperty("${propertyPrefix}whitelist.proxy-not-found") + return + } + + if (!proxyConfiguration.whitelist.mapToLowerCase().contains(playerName.toLowerCase())) { + sender.sendProperty("${propertyPrefix}whitelist.not-whitelisted") + return + } + + proxyConfiguration.whitelist.remove(playerName) + + module.getConfig().update() + module.saveConfig() + + sender.sendProperty("${propertyPrefix}whitelist.removed", playerName) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/ConfigConverter.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/ConfigConverter.kt new file mode 100644 index 000000000..9076cfd65 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/ConfigConverter.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager.converter + +import java.io.File + +/** + * Date: 19.06.22 + * Time: 12:59 + * @author Frederick Baier + * + */ +class ConfigConverter { + + private val configFile = File("modules/proxy", "config.json") + + fun convertIfNecessary() { + if (!configFile.exists()) + return + MiniMessageConfigConverter().convertIfNecessary() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/MiniMessageConfigConverter.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/MiniMessageConfigConverter.kt new file mode 100644 index 000000000..5df1c4f9b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/MiniMessageConfigConverter.kt @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager.converter + +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.proxy.manager.converter.convert3to4.MessageConverter +import java.io.File + +/** + * Date: 19.06.22 + * Time: 13:05 + * @author Frederick Baier + * + */ +class MiniMessageConfigConverter { + + private val configDir = File("modules/proxy") + private val configFile = File(configDir, "config.json") + + fun convertIfNecessary() { + if (!this.configFile.exists()) + return + if (isConversionNecessary()) { + Launcher.instance.logger.console("Converting Proxy Config...") + createConfigBackup() + convert() + Launcher.instance.logger.console("Proxy config converted") + } + } + + private fun isConversionNecessary(): Boolean { + val lines = this.configFile.readLines() + return lines.any { it.contains("§") } + } + + private fun createConfigBackup() { + val backupFile = File(configDir, "config_backup_${System.currentTimeMillis()}.json") + this.configFile.copyTo(backupFile) + } + + private fun convert() { + val lines = this.configFile.readLines() + val newLines = lines.map { MessageConverter(it).convert() } + this.configFile.delete() + this.configFile.writeText(newLines.joinToString("\n")) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/MessageConverter.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/MessageConverter.kt new file mode 100644 index 000000000..8c739394c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/MessageConverter.kt @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager.converter.convert3to4 + +/** + * Date: 18.06.22 + * Time: 21:03 + * @author Frederick Baier + * + */ +class MessageConverter( + private var line: String +) { + + private val colorReplacements = mapOf( + "§0" to "", + "§1" to "", + "§2" to "", + "§3" to "", + "§4" to "", + "§5" to "", + "§6" to "", + "§7" to "", + "§8" to "", + "§9" to "", + "§a" to "", + "§b" to "", + "§c" to "", + "§d" to "", + "§e" to "", + "§f" to "", + ) + + fun convert(): String { + replaceBraces() + replaceColors() + replaceOtherColorCodes() + return this.line + } + + private fun replaceOtherColorCodes() { + line = SpecialColorCodeReplacer(line).convert() + } + + private fun replaceColors() { + for ((oldColor, newColor) in colorReplacements) { + line = line.replace(oldColor, newColor) + } + } + + private fun replaceBraces() { + line = line.replace("\\u003c", "<").replace("\\u003e", ">") + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SingleColorCodeReplacer.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SingleColorCodeReplacer.kt new file mode 100644 index 000000000..8ee8497b7 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SingleColorCodeReplacer.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager.converter.convert3to4 + +/** + * Date: 19.06.22 + * Time: 10:01 + * @author Frederick Baier + * + */ +class SingleColorCodeReplacer( + private val colorCode: Char, + private val colorCodeName: String +) { + + private var foundColorCode: Boolean = false + + fun getColorCode(): Char { + return this.colorCode + } + + fun foundColorCode(stringBuilder: StringBuilder) { + stringBuilder.append("<${colorCodeName}>") + this.foundColorCode = true + } + + fun endIfOpen(stringBuilder: StringBuilder) { + if (foundColorCode) { + foundColorCode = false + stringBuilder.append("") + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SpecialColorCodeReplacer.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SpecialColorCodeReplacer.kt new file mode 100644 index 000000000..69568d2f7 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/manager/converter/convert3to4/SpecialColorCodeReplacer.kt @@ -0,0 +1,82 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.manager.converter.convert3to4 + +/** + * Date: 18.06.22 + * Time: 21:20 + * @author Frederick Baier + * + */ +class SpecialColorCodeReplacer( + private var line: String +) { + + private val charArray = line.toCharArray() + + private val colorReplacements = listOf( + SingleColorCodeReplacer('k', "obfuscated"), + SingleColorCodeReplacer('l', "bold"), + SingleColorCodeReplacer('m', "strikethrough"), + SingleColorCodeReplacer('n', "underline"), + SingleColorCodeReplacer('o', "italic"), + ) + + + public fun convert(): String { + val stringBuilder = StringBuilder() + + var lastCharWasParagraph = false + for (charIndex in charArray.indices) { + val currentChar = this.charArray[charIndex] + if (currentChar == '§') { + lastCharWasParagraph = true + continue + } + if (!lastCharWasParagraph) { + stringBuilder.append(currentChar) + continue + } + //currentCharIsColorCode + lastCharWasParagraph = false + if (currentChar == 'r') { + endOpenColors(stringBuilder) + continue + } + val colorCodeReplacer = findColorReplacement(currentChar) + colorCodeReplacer?.foundColorCode(stringBuilder) + } + return stringBuilder.toString() + } + + private fun endOpenColors(stringBuilder: StringBuilder) { + this.colorReplacements.forEach { + it.endIfOpen(stringBuilder) + } + } + + private fun findColorReplacement(char: Char): SingleColorCodeReplacer? { + return this.colorReplacements.firstOrNull { it.getColorCode() == char } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/ProxyHandler.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/ProxyHandler.kt new file mode 100644 index 000000000..89f6025b9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/ProxyHandler.kt @@ -0,0 +1,153 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.property.Property +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.module.permission.PermissionPool +import eu.thesimplecloud.module.prefix.manager.config.TablistInformation +import eu.thesimplecloud.module.prefix.service.tablist.ProxyTablistHelper +import eu.thesimplecloud.module.proxy.config.Config +import eu.thesimplecloud.module.proxy.config.DefaultConfig +import eu.thesimplecloud.module.proxy.config.ProxyGroupConfiguration +import eu.thesimplecloud.module.proxy.config.TablistConfiguration +import eu.thesimplecloud.module.proxy.extensions.mapToLowerCase +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.TextComponent +import net.kyori.adventure.text.minimessage.MiniMessage +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.05.2020 + * Time: 23:43 + */ +object ProxyHandler { + + var configHolder: IProperty = Property(DefaultConfig.get()) + + fun onEnable() { + CloudAPI.instance.getGlobalPropertyHolder() + .requestProperty("simplecloud-module-proxy-config") + .addResultListener { + configHolder = it + } + } + + var index = 0 + + fun getCurrentTablistConfiguration(): TablistConfiguration? { + val configurations = getTabListConfigurations() + if (configurations.isEmpty()) return null + index++ + + if (index >= configurations.size) { + index = 0 + } + + return configurations[index] + } + + fun getTabListConfigurations(): List { + return configHolder.getValue().tablistConfigurations.filter { + it.proxies.mapToLowerCase().contains(CloudPlugin.instance.thisService().getGroupName().lowercase()) + } + } + + fun getProxyConfiguration(): ProxyGroupConfiguration? { + return configHolder.getValue().proxyGroupConfigurations.firstOrNull { + it.proxyGroup == CloudPlugin.instance.thisService().getGroupName() + } + } + + fun getOnlinePlayers(): Int { + return CloudPlugin.instance.thisService().getServiceGroup().getOnlinePlayerCount() + } + + fun getHexColorComponent(message: String): TextComponent { + return Component.textOfChildren(MiniMessage.miniMessage().deserialize(message)) + } + + fun replaceString(message: String): String { + return message + .replace("%ONLINE_PLAYERS%", getOnlinePlayers().toString()) + .replace("%MAX_PLAYERS%", CloudPlugin.instance.thisService().getMaxPlayers().toString()) + .replace("%MAX_MEMORY%", CloudPlugin.instance.thisService().getMaxMemory().toString()) + .replace("%USED_MEMORY%", CloudPlugin.instance.thisService().getUsedMemory().toString()) + .replace("%PORT%", CloudPlugin.instance.thisService().getPort().toString()) + .replace("%PROXY%", CloudPlugin.instance.thisService().getName()) + } + + fun replaceString(message: String, server: ICloudService): String { + return replaceString(message) + .replace("%SERVER%", server.getName()) + .replace("%DISPLAYNAME%", server.getDisplayName()) + .replace("%SERVER_GROUP%", server.getGroupName()) + .replace("%LOCAL_ONLINE_PLAYERS%", server.getOnlineCount().toString()) + } + + fun replaceString(message: String, server: ICloudService, uuid: UUID): String { + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uuid) + var replacedString = replaceString(message, server) + + val groupName = getPermissionsGroupName(uuid) + if (groupName != null) replacedString = replacedString.replace("%GROUP%", groupName) + + val tablistInformation = getTablistInformation(uuid) ?: return replacedString + + return replacedString + .replace("%COLOR%", tablistInformation.color) + .replace("%PRIORITY%", tablistInformation.priority.toString()) + .replace("%PREFIX%", tablistInformation.prefix) + .replace("%SUFFIX%", tablistInformation.suffix) + .replace("%PING%", (cloudPlayer?.getPing()?.get() ?: -1).toString()) + .replace("%PLAYER_NAME%", cloudPlayer?.getName() ?: "unknown") + } + + private fun getTablistInformation(uuid: UUID): TablistInformation? { + try { + return ProxyTablistHelper.getTablistInformationByUUID(uuid) + } catch (_: Throwable) { + } + return null + } + + private fun getPermissionsGroupName(uuid: UUID): String? { + try { + val permissionPlayer = + PermissionPool.instance.getPermissionPlayerManager().getCachedPermissionPlayer(uuid) ?: return null + val permissionGroup = permissionPlayer.getHighestPermissionGroup() + return permissionGroup.getName() + } catch (_: Throwable) { + } + return null + } + + const val JOIN_MAINTENANCE_PERMISSION = "cloud.maintenance.join" + const val JOIN_FULL_PERMISSION = "cloud.full.join" + +} diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/BungeePluginMain.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/BungeePluginMain.kt new file mode 100644 index 000000000..8ee49205f --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/BungeePluginMain.kt @@ -0,0 +1,96 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.service.bungee + +import eu.thesimplecloud.module.proxy.config.TablistConfiguration +import eu.thesimplecloud.module.proxy.service.ProxyHandler +import eu.thesimplecloud.module.proxy.service.bungee.listener.BungeeListener +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import eu.thesimplecloud.plugin.proxy.bungee.toBaseComponent +import net.kyori.adventure.platform.bungeecord.BungeeAudiences +import net.md_5.bungee.api.ProxyServer +import net.md_5.bungee.api.connection.ProxiedPlayer +import net.md_5.bungee.api.plugin.Plugin +import java.util.concurrent.TimeUnit + + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 21:33 + */ +class BungeePluginMain : Plugin() { + + private lateinit var bungeeAudiences: BungeeAudiences + + override fun onEnable() { + bungeeAudiences = BungeeAudiences.create(this) + + ProxyHandler.onEnable() + proxy.pluginManager.registerListener(this, BungeeListener(this)) + startScheduler() + } + + override fun onDisable() { + bungeeAudiences.close() + } + + private fun startScheduler() { + ProxyServer.getInstance().scheduler.schedule(this, { + val tablistConfiguration = ProxyHandler.getCurrentTablistConfiguration() ?: return@schedule + ProxyServer.getInstance().players.forEach { + sendHeaderAndFooter(it, tablistConfiguration) + } + }, 1, 1, TimeUnit.SECONDS) + } + + fun sendHeaderAndFooter(proxiedPlayer: ProxiedPlayer, tablistConfiguration: TablistConfiguration) { + val footerString = tablistConfiguration.footers.joinToString("\n") + val headerString = tablistConfiguration.headers.joinToString("\n") + sendHeaderAndFooter(proxiedPlayer, headerString, footerString) + } + + private fun sendHeaderAndFooter(player: ProxiedPlayer, header: String, footer: String) { + val server = player.getCloudPlayer().getConnectedServer() ?: return + + val headerBaseComponent = ProxyHandler.getHexColorComponent( + ProxyHandler.replaceString( + header, + server, + player.uniqueId + ) + ).toBaseComponent() + + val footerBaseComponent = ProxyHandler.getHexColorComponent( + ProxyHandler.replaceString( + footer, + server, + player.uniqueId + ) + ).toBaseComponent() + + player.setTabHeader(headerBaseComponent, footerBaseComponent) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/listener/BungeeListener.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/listener/BungeeListener.kt new file mode 100644 index 000000000..61032c8a6 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/bungee/listener/BungeeListener.kt @@ -0,0 +1,153 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.service.bungee.listener + +import eu.thesimplecloud.module.proxy.extensions.mapToLowerCase +import eu.thesimplecloud.module.proxy.service.ProxyHandler +import eu.thesimplecloud.module.proxy.service.bungee.BungeePluginMain +import eu.thesimplecloud.plugin.proxy.bungee.toBaseComponent +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer +import net.md_5.bungee.api.ServerPing +import net.md_5.bungee.api.event.ProxyPingEvent +import net.md_5.bungee.api.event.ServerConnectEvent +import net.md_5.bungee.api.event.ServerConnectedEvent +import net.md_5.bungee.api.event.ServerSwitchEvent +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.03.2020 + * Time: 22:14 + */ +class BungeeListener(private val plugin: BungeePluginMain) : Listener { + + @EventHandler(priority = EventPriority.HIGH) + fun on(event: ServerConnectEvent) { + val player = event.player + + val config = ProxyHandler.configHolder.getValue() + val proxyConfiguration = ProxyHandler.getProxyConfiguration() ?: return + + if (CloudPlugin.instance.thisService().getServiceGroup().isInMaintenance()) { + if (!player.hasPermission(ProxyHandler.JOIN_MAINTENANCE_PERMISSION) && + !proxyConfiguration.whitelist.mapToLowerCase().contains(player.name.lowercase()) + ) { + player.disconnect( + ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(config.maintenanceKickMessage)) + .toBaseComponent() + ) + event.isCancelled = true + return + } + } + + + val maxPlayers = CloudPlugin.instance.thisService().getServiceGroup().getMaxPlayers() + + if (ProxyHandler.getOnlinePlayers() > maxPlayers) { + if (!player.hasPermission(ProxyHandler.JOIN_FULL_PERMISSION) && + !proxyConfiguration.whitelist.mapToLowerCase().contains(player.name.lowercase()) + ) { + player.disconnect( + ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(config.fullProxyKickMessage)) + .toBaseComponent() + ) + event.isCancelled = true + } + } + + } + + @EventHandler + fun on(event: ServerConnectedEvent) { + val player = event.player + val tablistConfiguration = ProxyHandler.getCurrentTablistConfiguration() ?: return + plugin.sendHeaderAndFooter(player, tablistConfiguration) + } + + @EventHandler + fun on(event: ServerSwitchEvent) { + val player = event.player + + val tablistConfiguration = ProxyHandler.getCurrentTablistConfiguration() ?: return + plugin.sendHeaderAndFooter(player, tablistConfiguration) + } + + @EventHandler + fun on(event: ProxyPingEvent) { + val response = event.response + + val proxyConfiguration = ProxyHandler.getProxyConfiguration() ?: return + val motdConfiguration = if (CloudPlugin.instance.thisService().getServiceGroup().isInMaintenance()) + proxyConfiguration.maintenanceMotds else proxyConfiguration.motds + + val line1 = motdConfiguration.firstLines.random() + val line2 = motdConfiguration.secondLines.random() + + val motdComponent = ProxyHandler.getHexColorComponent(ProxyHandler.replaceString("$line1\n$line2")) + response.descriptionComponent = motdComponent.toBaseComponent() + + val playerInfo = motdConfiguration.playerInfo + val onlinePlayers = ProxyHandler.getOnlinePlayers() + + val versionName = motdConfiguration.versionName + if (versionName != null && versionName.isNotEmpty()) { + val versionColorComponent = ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(versionName)) + response.version = ServerPing.Protocol( + LegacyComponentSerializer.legacy('§').serialize(versionColorComponent), + -1 + ) + } + + val maxPlayers = CloudPlugin.instance.thisService().getServiceGroup().getMaxPlayers() + + if (playerInfo != null && playerInfo.isNotEmpty()) { + val sample = mutableListOf() + + playerInfo.forEach { + val playerInfoString = ProxyHandler.replaceString(it) + val playerInfoComponent = ProxyHandler.getHexColorComponent(playerInfoString) + + sample.add( + ServerPing.PlayerInfo( + LegacyComponentSerializer.legacy('§').serialize(playerInfoComponent), + UUID.randomUUID() + ) + ) + } + + response.players = ServerPing.Players(maxPlayers, onlinePlayers, sample.toTypedArray()) + + return + } + + response.players.max = maxPlayers + response.players.online = onlinePlayers + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/VelocityPluginMain.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/VelocityPluginMain.kt new file mode 100644 index 000000000..c960f5605 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/VelocityPluginMain.kt @@ -0,0 +1,85 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.service.velocity + +import com.google.inject.Inject +import com.velocitypowered.api.event.Subscribe +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent +import com.velocitypowered.api.plugin.Dependency +import com.velocitypowered.api.plugin.Plugin +import com.velocitypowered.api.proxy.Player +import com.velocitypowered.api.proxy.ProxyServer +import eu.thesimplecloud.module.proxy.config.TablistConfiguration +import eu.thesimplecloud.module.proxy.service.ProxyHandler +import eu.thesimplecloud.module.proxy.service.velocity.listener.VelocityListener +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.05.2020 + * Time: 23:37 + */ + +@Plugin(id = "simplecloud_proxy", dependencies = [Dependency(id = "simplecloud_plugin")]) +class VelocityPluginMain @Inject constructor( + private val proxyServer: ProxyServer +) { + + + @Subscribe + fun handleInit(event: ProxyInitializeEvent) { + + ProxyHandler.onEnable() + proxyServer.eventManager.register(this, VelocityListener(this)) + startScheduler() + } + + private fun startScheduler() { + proxyServer.scheduler.buildTask(this) { + val tablistConfiguration = ProxyHandler.getCurrentTablistConfiguration() ?: return@buildTask + proxyServer.allPlayers.forEach { + sendHeaderAndFooter(it, tablistConfiguration) + } + }.repeat(1, TimeUnit.SECONDS).schedule() + } + + fun sendHeaderAndFooter(player: Player, tablistConfiguration: TablistConfiguration) { + val footerString = tablistConfiguration.footers.joinToString("\n") + val headerString = tablistConfiguration.headers.joinToString("\n") + sendHeaderAndFooter(player, headerString, footerString) + } + + private fun sendHeaderAndFooter(player: Player, header: String, footer: String) { + val server = player.getCloudPlayer().getConnectedServer() ?: return + + val headerHexColorComponent = ProxyHandler + .getHexColorComponent(ProxyHandler.replaceString(header, server, player.uniqueId)) + val footerHexColorComponent = ProxyHandler + .getHexColorComponent(ProxyHandler.replaceString(footer, server, player.uniqueId)) + + player.sendPlayerListHeaderAndFooter(headerHexColorComponent, footerHexColorComponent) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/listener/VelocityListener.kt b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/listener/VelocityListener.kt new file mode 100644 index 000000000..1ae1e25c2 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/kotlin/eu/thesimplecloud/module/proxy/service/velocity/listener/VelocityListener.kt @@ -0,0 +1,151 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.proxy.service.velocity.listener + +import com.velocitypowered.api.event.PostOrder +import com.velocitypowered.api.event.Subscribe +import com.velocitypowered.api.event.player.ServerConnectedEvent +import com.velocitypowered.api.event.player.ServerPreConnectEvent +import com.velocitypowered.api.event.proxy.ProxyPingEvent +import com.velocitypowered.api.proxy.server.ServerPing +import com.velocitypowered.api.proxy.server.ServerPing.SamplePlayer +import eu.thesimplecloud.module.proxy.extensions.mapToLowerCase +import eu.thesimplecloud.module.proxy.service.ProxyHandler +import eu.thesimplecloud.module.proxy.service.velocity.VelocityPluginMain +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.05.2020 + * Time: 23:48 + */ +class VelocityListener(val plugin: VelocityPluginMain) { + + @Subscribe(order = PostOrder.EARLY) + fun handle(event: ServerPreConnectEvent) { + val player = event.player + + val config = ProxyHandler.configHolder.getValue() + val proxyConfiguration = ProxyHandler.getProxyConfiguration() ?: return + + if (CloudPlugin.instance.thisService().getServiceGroup().isInMaintenance()) { + if (!player.hasPermission(ProxyHandler.JOIN_MAINTENANCE_PERMISSION) && + !proxyConfiguration.whitelist.mapToLowerCase().contains(player.username.toLowerCase()) + ) { + player.disconnect(ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(config.maintenanceKickMessage))) + event.result = ServerPreConnectEvent.ServerResult.denied() + return + } + } + + + val maxPlayers = CloudPlugin.instance.thisService().getServiceGroup().getMaxPlayers() + + + + if (ProxyHandler.getOnlinePlayers() < maxPlayers) + return + + if (player.hasPermission(ProxyHandler.JOIN_FULL_PERMISSION) && + proxyConfiguration.whitelist.mapToLowerCase().contains(player.username.toLowerCase()) + ) + return + + player.disconnect(ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(config.fullProxyKickMessage))) + event.result = ServerPreConnectEvent.ServerResult.denied() + } + + @Subscribe + fun on(event: ServerConnectedEvent) { + val player = event.player + val tablistConfiguration = ProxyHandler.getCurrentTablistConfiguration() ?: return + plugin.sendHeaderAndFooter(player, tablistConfiguration) + } + + @Subscribe + fun handle(event: ProxyPingEvent) { + val proxyConfiguration = ProxyHandler.getProxyConfiguration() ?: return + val motdConfiguration = if (CloudPlugin.instance.thisService().getServiceGroup().isInMaintenance()) + proxyConfiguration.maintenanceMotds else proxyConfiguration.motds + + val motdBuilder = StringBuilder(); + + if (motdConfiguration.firstLines.isNotEmpty()) + motdBuilder.append(motdConfiguration.firstLines.random()) else motdBuilder.append(" ") + + motdBuilder.append("\n") + + if (motdConfiguration.secondLines.isNotEmpty()) + motdBuilder.append(motdConfiguration.secondLines.random()) else motdBuilder.append(" ") + + val motd = ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(motdBuilder.toString())) + + val ping = event.ping + var protocol: ServerPing.Version = ping.version + var players: ServerPing.Players? = if (ping.players.isPresent) ping.players.get() else null + val favicon = if (ping.favicon.isPresent) ping.favicon.get() else null + val modinfo = if (ping.modinfo.isPresent) ping.modinfo.get() else null + + val playerInfo = motdConfiguration.playerInfo + val onlinePlayers = ProxyHandler.getOnlinePlayers() + + val versionName = motdConfiguration.versionName + + if (versionName != null && versionName.isNotEmpty()) { + val versionColorComponent = ProxyHandler.getHexColorComponent(ProxyHandler.replaceString(versionName)) + protocol = ServerPing.Version( + -1, + LegacyComponentSerializer.legacy('§').serialize(versionColorComponent) + ) + } + + val maxPlayers = CloudPlugin.instance.thisService().getServiceGroup().getMaxPlayers() + + val playerSamples = if (playerInfo != null && playerInfo.isNotEmpty()) { + val sample = mutableListOf() + + playerInfo.forEach { + val playerInfoString = ProxyHandler.replaceString(it) + val playerInfoComponent = ProxyHandler.getHexColorComponent(playerInfoString) + + sample.add( + SamplePlayer( + LegacyComponentSerializer.legacy('§').serialize(playerInfoComponent), + UUID.randomUUID() + ) + ) + } + + sample + } else { + emptyList() + } + + players = ServerPing.Players(onlinePlayers, maxPlayers, playerSamples) + event.ping = ServerPing(protocol, players, motd, favicon, modinfo) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/de.json new file mode 100644 index 000000000..15a7936a9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/de.json @@ -0,0 +1,8 @@ +{ + "module.proxy.command.reload": "Proxy config neugeladen.", + "module.proxy.command.whitelist.proxy-not-found": "Proxy nicht gefunden.", + "module.proxy.command.whitelist.already-whitelisted": "Dieser Spieler ist bereits auf der Whitelist.", + "module.proxy.command.whitelist.added": "Spieler %PLAYER% wurde zur Whitelist hinzugefügt.", + "module.proxy.command.whitelist.not-whitelisted": "Dieser Spieler ist nicht auf der Whitelist.", + "module.proxy.command.whitelist.removed": "Der Spieler %PLAYER% wurde von der Whitelist entfernt." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/en.json new file mode 100644 index 000000000..5a42228bf --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/languages/en.json @@ -0,0 +1,8 @@ +{ + "module.proxy.command.reload": "Reloaded proxy config.", + "module.proxy.command.whitelist.proxy-not-found": "Proxy not found.", + "module.proxy.command.whitelist.already-whitelisted": "The specified player is already whitelisted.", + "module.proxy.command.whitelist.added": "Added player %PLAYER% to the whitelist.", + "module.proxy.command.whitelist.not-whitelisted": "The specified player is not whitelisted.", + "module.proxy.command.whitelist.removed": "Removed player %PLAYER% from the whitelist." +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/module.json new file mode 100644 index 000000000..25a77a11d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Proxy", + "author": "Fllip", + "mainClass": "eu.thesimplecloud.module.proxy.manager.ProxyModule", + "moduleCopyType": "PROXY", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/resources/plugin.yml b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/plugin.yml new file mode 100644 index 000000000..773428e08 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/plugin.yml @@ -0,0 +1,8 @@ +name: SimpleCloud-Proxy +version: 1.0 +author: Fllip + +main: eu.thesimplecloud.module.proxy.service.bungee.BungeePluginMain + +softdepend: [ SimpleCloud-Permissions, SimpleCloud-Chat-Tab ] +depend: [ SimpleCloud-Plugin ] diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/updater.json new file mode 100644 index 000000000..4e7e9a94b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-proxy", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-proxy/src/main/resources/velocity-plugin.json b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/velocity-plugin.json new file mode 100644 index 000000000..484589256 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-proxy/src/main/resources/velocity-plugin.json @@ -0,0 +1,9 @@ +{ + "id": "simplecloud_proxy", + "name": "SimpleCloud-Proxy", + "version": "1.0", + "authors": [ + "Fllip" + ], + "main": "eu.thesimplecloud.module.proxy.service.velocity.VelocityPluginMain" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/build.gradle b/simplecloud-modules/simplecloud-module-rest/build.gradle new file mode 100644 index 000000000..36e6ddf92 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/build.gradle @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Rest.jar") +} + +repositories { + maven { url 'https://jitpack.io' } +} + +dependencies { + compileOnly "org.jetbrains.kotlin:kotlin-stdlib" + testApi group: 'junit', name: 'junit', version: '4.12' + compileOnly 'io.javalin:javalin:3.13.7' + compileOnly 'com.auth0:java-jwt:3.16.0' + compileOnly 'com.github.kmehrunes:javalin-jwt:v0.2' + compileOnly 'org.slf4j:slf4j-simple:1.7.36' + compileOnly "org.slf4j:slf4j-api:1.8.0-beta4" + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-launcher")) { + transitive = false + } + // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 + compileOnly group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' + compileOnly(group: 'eu.thesimplecloud.clientserverapi', name: 'clientserverapi', version: depedencyClientServerAPIVersion) +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/RestModule.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/RestModule.kt new file mode 100644 index 000000000..4edb7f1d0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/RestModule.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest + +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.rest.auth.JwtProvider +import eu.thesimplecloud.module.rest.config.RestConfig +import eu.thesimplecloud.module.rest.config.RestConfigLoader +import eu.thesimplecloud.module.rest.javalin.RestServer +import eu.thesimplecloud.module.rest.util.executeWithDifferentContextClassLoader + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 14:57 + * @author Frederick Baier + */ +class RestModule : ICloudModule { + + lateinit var server: RestServer + + override fun onEnable() { + val config = loadConfig() + val moduleClassLoader = this::class.java.classLoader + executeWithDifferentContextClassLoader(moduleClassLoader) { + startRestServer(config) + } + Launcher.instance.consoleSender.sendProperty("module.rest.loaded", config.port.toString()) + } + + private fun loadConfig(): RestConfig { + return RestConfigLoader().loadConfig() + } + + private fun startRestServer(config: RestConfig) { + JwtProvider(config.secret) + this.server = RestServer(config.port) + } + + override fun onDisable() { + server.shutdown() + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestBody.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestBody.kt new file mode 100644 index 000000000..23b091323 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestBody.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 15:38 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class RequestBody \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestMapping.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestMapping.kt new file mode 100644 index 000000000..d3f62718f --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestMapping.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 15:38 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FUNCTION) +annotation class RequestMapping( + val requestType: RequestType, + val additionalPath: String = "", + val permission: String = "" +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestParam.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestParam.kt new file mode 100644 index 000000000..b36f4c71b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestParam.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 15:38 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class RequestParam( + val parameterName: String, + val required: Boolean = true +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestPathParam.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestPathParam.kt new file mode 100644 index 000000000..37cdb95fa --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestPathParam.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 15:38 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class RequestPathParam( + val parameterName: String +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestType.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestType.kt new file mode 100644 index 000000000..8a0e9045f --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestType.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 18:07 + * @author Frederick Baier + */ + +enum class RequestType { + + GET, + + PUT, + + POST, + + DELETE + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestingUser.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestingUser.kt new file mode 100644 index 000000000..d4c20ced3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RequestingUser.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 15:38 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class RequestingUser \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RestController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RestController.kt new file mode 100644 index 000000000..4326da170 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/RestController.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 15:38 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CLASS) +annotation class RestController( + val path: String +) { +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/WebExclude.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/WebExclude.kt new file mode 100644 index 000000000..f73cf51d8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/annotation/WebExclude.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.annotation + +/** + * Created by IntelliJ IDEA. + * Date: 05.10.2020 + * Time: 13:15 + * @author Frederick Baier + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FIELD) +annotation class WebExclude \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/AuthService.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/AuthService.kt new file mode 100644 index 000000000..f8350848c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/AuthService.kt @@ -0,0 +1,120 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.rest.auth.controller.LoginDto +import eu.thesimplecloud.module.rest.auth.user.User +import eu.thesimplecloud.module.rest.auth.user.permission.Permission +import eu.thesimplecloud.module.rest.controller.IExceptionHelper +import org.apache.commons.lang3.RandomStringUtils +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 05.10.2020 + * Time: 13:05 + * @author Frederick Baier + */ +class AuthService : IExceptionHelper { + + private val usersFile = File("modules/rest/users.json") + private val users: MutableList + + init { + if (!usersFile.exists()) { + this.users = ArrayList() + val standardUser = User("admin", RandomStringUtils.randomAlphabetic(32)) + standardUser.addPermission(Permission("*", true)) + this.users.add(standardUser) + saveUpdateToFile() + } else { + this.users = JsonLib.fromJsonFile(this.usersFile)!!.getObject(Array::class.java).toMutableList() + } + } + + fun handleLogin(login: LoginDto): String? { + val user = getUserByName(login.username) + if (user == null || user.password != login.password) + return null + return JwtProvider.instance.provider.generateToken(user) + } + + fun handleAddUser(user: User): User { + if (doesUserExist(user.username)) + throwElementAlreadyExist() + + val user = cloneUser(user) + this.users.add(user) + saveUpdateToFile() + return user + } + + fun handleUserUpdate(user: User): User { + if (!doesUserExist(user.username)) + throwNoSuchElement() + + val user = cloneUser(user) + this.users.removeIf { it.username == user.username } + this.users.add(user) + saveUpdateToFile() + return user + } + + fun handleUserDelete(user: User) { + if (!doesUserExist(user.username)) + throwNoSuchElement() + + this.users.removeIf { it.username == user.username } + saveUpdateToFile() + } + + fun handleUserGet(username: String): User? { + return getUserByName(username) + } + + fun getUserByName(userName: String): User? { + return this.users.firstOrNull { it.username == userName } + } + + fun doesUserExist(userName: String): Boolean { + return getUserByName(userName) != null + } + + fun getUsers(): List { + return this.users + } + + private fun cloneUser(user: User): User { + return User(user.username, user.password) + } + + private fun saveUpdateToFile() { + JsonLib.fromObject(users).saveAsFile(usersFile) + } + + class UserAlreadyExistException() : Exception("The user does already exist") + + class UserNotExistException() : Exception("The user does not exist") + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/JwtProvider.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/JwtProvider.kt new file mode 100644 index 000000000..327781883 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/JwtProvider.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth + +import com.auth0.jwt.JWT +import com.auth0.jwt.JWTVerifier +import com.auth0.jwt.algorithms.Algorithm +import eu.thesimplecloud.module.rest.auth.user.User +import javalinjwt.JWTGenerator +import javalinjwt.JWTProvider +import java.util.* +import java.util.concurrent.TimeUnit + + +class JwtProvider(secret: String) { + + private val jwtAlgorithm: Algorithm = Algorithm.HMAC512(secret) + + private val jwtGenerator = JWTGenerator { user: User, algorithm: Algorithm -> + val token = JWT.create() + .withClaim("username", user.username) + .withExpiresAt(Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(7))) + + token.sign(algorithm) + } + private val jwtVerifier: JWTVerifier = JWT.require(jwtAlgorithm).build() + + val provider = JWTProvider(jwtAlgorithm, jwtGenerator, jwtVerifier) + + init { + instance = this + } + + companion object { + lateinit var instance: JwtProvider + } +} + + diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/Roles.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/Roles.kt new file mode 100644 index 000000000..74fb6930d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/Roles.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth + +import io.javalin.core.security.Role + +enum class Roles : Role { + + ANYONE, USER + +} + +fun createRolesMapping(): HashMap { + val rolesMapping = HashMap() + Roles.values().forEach { + rolesMapping[it.toString()] = it + } + return rolesMapping +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/AuthController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/AuthController.kt new file mode 100644 index 000000000..6a09705cd --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/AuthController.kt @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth.controller + +import eu.thesimplecloud.module.rest.annotation.RequestBody +import eu.thesimplecloud.module.rest.annotation.RequestMapping +import eu.thesimplecloud.module.rest.annotation.RequestType +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.auth.AuthService +import eu.thesimplecloud.module.rest.controller.IController +import io.javalin.http.Context +import javalinjwt.examples.JWTResponse + +/** + * Created by IntelliJ IDEA. + * Date: 05.10.2020 + * Time: 13:01 + * @author Frederick Baier + */ +@RestController("auth/") +class AuthController( + private val authService: AuthService +) : IController { + + @RequestMapping(RequestType.POST, "login/") + fun handleLogin(@RequestBody login: LoginDto, context: Context) { + val token = authService.handleLogin(login) + if (token == null) { + context.status(401) + context.result("Username or password wrong!") + } else { + context.json(JWTResponse(token)) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/LoginDto.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/LoginDto.kt new file mode 100644 index 000000000..5cb823088 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/controller/LoginDto.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth.controller + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 12.06.2020 + * Time: 17:46 + */ +data class LoginDto( + val username: String, + val password: String +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/User.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/User.kt new file mode 100644 index 000000000..6386ad693 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/User.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth.user + +import eu.thesimplecloud.module.rest.annotation.WebExclude +import eu.thesimplecloud.module.rest.auth.user.permission.entity.PermissionEntity + + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 18.06.2020 + * Time: 17:07 + */ +data class User( + val username: String, + @WebExclude + var password: String +) : PermissionEntity() \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/Permission.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/Permission.kt new file mode 100644 index 000000000..41e66d7bd --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/Permission.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth.user.permission + + +data class Permission(val permissionString: String, val active: Boolean) { + + fun matches(permission: String): Boolean { + return matchesPermission(permission) + } + + private fun matchesPermission(permission: String): Boolean { + val endsWithStar = this.permissionString.endsWith(".*") + return if (endsWithStar) { + matchesWithStarAtTheEnd(permission) + } else { + isPermissionToCheckEqualToThisPermission(permission) + } + } + + private fun isPermissionToCheckEqualToThisPermission(permission: String): Boolean { + return permission == this.permissionString + } + + private fun matchesWithStarAtTheEnd(permission: String): Boolean { + val checkPermissionComponents = permission.split(".") + val thisPermissionComponents = this.permissionString.split(".") + + val isPermissionToCheckLongEnough = checkPermissionComponents.size >= thisPermissionComponents.size + return if (isPermissionToCheckLongEnough) { + areAllPermissionComponentsEqual(checkPermissionComponents, thisPermissionComponents) + } else { + false + } + } + + private fun areAllPermissionComponentsEqual( + checkPermissionComponents: List, + thisPermissionComponents: List + ): Boolean { + val thisPermissionComponentsWithoutStar = thisPermissionComponents.dropLast(1) + val checkComponentsWithLimit = checkPermissionComponents.take(thisPermissionComponentsWithoutStar.size) + return checkComponentsWithLimit == thisPermissionComponentsWithoutStar + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/IPermissionEntity.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/IPermissionEntity.kt new file mode 100644 index 000000000..1910f7967 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/IPermissionEntity.kt @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth.user.permission.entity + +import eu.thesimplecloud.module.rest.auth.user.permission.Permission + + +interface IPermissionEntity { + + /** + * Returns whether the group has the specified [permission] + */ + fun hasPermission(permission: String): Boolean { + if (permission.isBlank()) return true + val permissionObj = getPermissionByMatch(permission) ?: return hasAllRights() + return permissionObj.active + } + + fun getPermissionByMatch(permission: String): Permission? { + val notExpiredPermissions = getPermissions() + return notExpiredPermissions.firstOrNull { it.matches(permission) } + } + + /** + * Returns the permission object of the specified [permission] + */ + fun getPermissionByName(permission: String): Permission? = + getPermissions().firstOrNull { it.permissionString == permission } + + /** + * Returns all permissions of this entity + */ + fun getPermissions(): Collection + + /** + * Adds the specified [permission] to the list + */ + fun addPermission(permission: Permission) + + /** + * Removes the permission object found by the specified [permissionString] + */ + fun removePermission(permissionString: String) + + /** + * Removes all permissions from this entity + */ + fun clearAllPermission() + + /** + * Returns whether this + */ + fun hasAllRights(): Boolean = getPermissions().any { it.permissionString == "*" } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/PermissionEntity.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/PermissionEntity.kt new file mode 100644 index 000000000..98be2a2eb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/auth/user/permission/entity/PermissionEntity.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.auth.user.permission.entity + +import eu.thesimplecloud.module.rest.auth.user.permission.Permission + + +open class PermissionEntity : IPermissionEntity { + + private val permissions = ArrayList() + + override fun getPermissions(): Collection = this.permissions + + override fun addPermission(permission: Permission) { + removePermission(permission.permissionString) + this.permissions.add(permission) + } + + override fun removePermission(permissionString: String) { + this.permissions.remove(getPermissionByName(permissionString)) + } + + override fun clearAllPermission() { + this.permissions.clear() + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfig.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfig.kt new file mode 100644 index 000000000..1951b0051 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfig.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.config + +import org.apache.commons.lang3.RandomStringUtils + +/** + * Created by IntelliJ IDEA. + * Date: 06.12.2020 + * Time: 19:25 + * @author Frederick Baier + */ +class RestConfig( + val port: Int = 8585, + val secret: String = RandomStringUtils.randomAlphabetic(170) +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfigLoader.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfigLoader.kt new file mode 100644 index 000000000..f400d24c0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/config/RestConfigLoader.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.config + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 06.12.2020 + * Time: 19:07 + * @author Frederick Baier + */ +class RestConfigLoader : AbstractJsonLibConfigLoader( + RestConfig::class.java, + File("modules/rest/config.json"), + { RestConfig() }, + true +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/ControllerHandler.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/ControllerHandler.kt new file mode 100644 index 000000000..a185fd216 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/ControllerHandler.kt @@ -0,0 +1,101 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.controller + +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.auth.user.User +import eu.thesimplecloud.module.rest.javalin.RestServer +import io.javalin.http.Context +import java.lang.reflect.Method +import java.lang.reflect.Parameter + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 17:56 + * @author Frederick Baier + */ +class ControllerHandler(private val restServer: RestServer) { + + + fun registerController(controller: IController) { + val javaClass = controller::class.java + val restController = javaClass.getAnnotation(RestController::class.java)!! + val methods = javaClass.declaredMethods + val methodsWithAnnotation = methods.filter { it.isAnnotationPresent(RequestMapping::class.java) } + + methodsWithAnnotation.forEach { + registerMethod(restController, it, controller) + } + } + + private fun registerMethod(restController: RestController, method: Method, controller: IController) { + val requestMapping = method.getAnnotation(RequestMapping::class.java) + val parameterDataList = method.parameters.map { createParameterData(it) } + val requestMethodData = RequestMethodData( + controller, + method, + restController.path + requestMapping.additionalPath, + requestMapping.requestType, + requestMapping.permission, + parameterDataList + ) + restServer.registerRequestMethod(requestMethodData) + } + + private fun createParameterData(parameter: Parameter): RequestMethodData.RequestParameterData { + if (parameter.type == Context::class.java) + return createContextParameterData() + if (parameter.isAnnotationPresent(RequestingUser::class.java)) { + if (parameter.type != User::class.java) { + throw IllegalStateException("RequestingUser annotation can only be used on User") + } + val requestingUser = parameter.getAnnotation(RequestingUser::class.java)!! + return createRequestingUserParameterData(requestingUser) + } + + val requestParam = parameter.getAnnotation(RequestParam::class.java) + if (requestParam != null) { + return RequestMethodData.RequestParameterData(parameter.type, requestParam) + } + val requestBody = parameter.getAnnotation(RequestBody::class.java) + if (requestBody != null) { + return RequestMethodData.RequestParameterData(parameter.type, requestBody) + } + val requestPathParam = parameter.getAnnotation(RequestPathParam::class.java) + if (requestPathParam != null) { + return RequestMethodData.RequestParameterData(parameter.type, requestPathParam) + } + throw IllegalArgumentException("Parameter with type ${parameter.type.name} in not annotated with RequestBody, RequestParam or RequestPathParam") + } + + private fun createRequestingUserParameterData(requestingUser: RequestingUser): RequestMethodData.RequestParameterData { + return RequestMethodData.RequestParameterData(User::class.java, requestingUser) + } + + private fun createContextParameterData(): RequestMethodData.RequestParameterData { + return RequestMethodData.RequestParameterData(Context::class.java, null) + } + + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IController.kt new file mode 100644 index 000000000..1b0306a3c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IController.kt @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.controller + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 17:57 + * @author Frederick Baier + */ +interface IController : IExceptionHelper \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IExceptionHelper.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IExceptionHelper.kt new file mode 100644 index 000000000..f0f1c3612 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/IExceptionHelper.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.controller + +import eu.thesimplecloud.module.rest.exception.ElementAlreadyExistException + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 11:01 + * @author Frederick Baier + */ +interface IExceptionHelper { + + fun throwElementAlreadyExist(): Nothing = throw ElementAlreadyExistException() + + fun throwNoSuchElement(): Nothing = throw NoSuchElementException("Element not found") + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/RequestMethodData.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/RequestMethodData.kt new file mode 100644 index 000000000..9507c6815 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/controller/RequestMethodData.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.controller + +import eu.thesimplecloud.module.rest.annotation.RequestType +import java.lang.reflect.Method + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 18:13 + * @author Frederick Baier + */ +class RequestMethodData( + val controller: IController, + val method: Method, + val path: String, + val requestType: RequestType, + val permission: String, + val parameters: List +) { + + class RequestParameterData( + val parameterType: Class<*>, + val annotation: Annotation? + ) + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/UserController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/UserController.kt new file mode 100644 index 000000000..b526cf386 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/UserController.kt @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller + +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.auth.AuthService +import eu.thesimplecloud.module.rest.auth.user.User +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 05.10.2020 + * Time: 17:14 + * @author Frederick Baier + */ +@RestController("user/") +class UserController( + private val authService: AuthService +) : IController { + + @RequestMapping(RequestType.GET, "", "web.user.get.all") + fun handleGetAllUsers(): List { + return authService.getUsers() + } + + @RequestMapping(RequestType.GET, "self/", "web.user.get.self") + fun handleGetSelfUser(@RequestingUser user: User): User { + return user + } + + @RequestMapping(RequestType.GET, "name/:name", "web.user.get.one") + fun handleGetOneUsers(@RequestPathParam("name") username: String): User { + return authService.handleUserGet(username) ?: throwNoSuchElement() + } + + @RequestMapping(RequestType.POST, "", "web.user.create") + fun handleCreateUser(@RequestBody user: User): User { + return authService.handleAddUser(user) + } + + @RequestMapping(RequestType.PUT, "", "web.user.update") + fun handleUpdateUser(@RequestBody user: User): User { + return authService.handleUserUpdate(user) + } + + @RequestMapping(RequestType.DELETE, "", "web.user.delete") + fun handleDeleteUser(@RequestBody user: User): User { + authService.handleUserDelete(user) + return user + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/CommandDto.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/CommandDto.kt new file mode 100644 index 000000000..815f48fe9 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/CommandDto.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.dto + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 17:53 + * @author Frederick Baier + */ +class CommandDto( + val command: String +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ErrorDto.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ErrorDto.kt new file mode 100644 index 000000000..cd42966cd --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ErrorDto.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.dto + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 22:23 + * @author Frederick Baier + */ +class ErrorDto( + val errorClass: String, + error: String? +) { + + val error = error ?: "" + + + companion object { + fun fromException(ex: Throwable): ErrorDto { + return ErrorDto(ex::class.java.name, ex.message) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/PathDto.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/PathDto.kt new file mode 100644 index 000000000..605bd59bb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/PathDto.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.dto + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 17:53 + * @author Frederick Baier + */ +class PathDto( + val path: String +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ResultDto.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ResultDto.kt new file mode 100644 index 000000000..e2a6524e8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/dto/ResultDto.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.dto + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 18:05 + * @author Frederick Baier + */ +class ResultDto( + val result: Any? +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/filemanager/FileManagerController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/filemanager/FileManagerController.kt new file mode 100644 index 000000000..2151fab76 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/filemanager/FileManagerController.kt @@ -0,0 +1,111 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.filemanager + +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.rest.annotation.RequestMapping +import eu.thesimplecloud.module.rest.annotation.RequestType +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.controller.IController +import io.javalin.core.util.FileUtil +import io.javalin.http.Context +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 17.11.2020 + * Time: 20:18 + * @author Frederick Baier + */ +@RestController("filemanager/") +class FileManagerController : IController { + + @RequestMapping(RequestType.GET, "*", "web.filemanager.read") + fun handleRead(ctx: Context): Collection { + checkForSuspiciousPath(ctx) + val file = getFileFromRequest(ctx) + if (!file.exists()) throwNoSuchElement() + if (file.isDirectory) { + val listFiles = file.listFiles().toList() + val directories = listFiles.filter { it.isDirectory }.sortedBy { it.name } + val files = listFiles.filter { !it.isDirectory }.sortedBy { it.name } + return directories.union(files).map { FileInfo(it.name, it.isDirectory, it.length()) } + } + if (ctx.queryParam("view") == null) + ctx.res.setHeader("Content-Disposition", "attachment; filename=${file.name}") + ctx.result(file.readBytes()) + return emptyList() + } + + @RequestMapping(RequestType.DELETE, "*", "web.filemanager.delete") + fun handleDelete(ctx: Context): Boolean { + checkForSuspiciousPath(ctx) + val file = getFileFromRequest(ctx) + if (!file.exists()) throwNoSuchElement() + if (file.isDirectory) { + //FileUtils.deleteDirectory(file) + } else { + file.delete() + } + return true + } + + @RequestMapping(RequestType.POST, "*", "web.filemanager.create") + fun handleCreate(ctx: Context): Boolean { + checkForSuspiciousPath(ctx) + val file = getFileFromRequest(ctx) + println(file.absolutePath) + if (file.exists() && file.isDirectory) return false + if (file.exists()) file.delete() + file.parentFile?.mkdirs() + val uploadedFile = ctx.uploadedFile("file") + + if (uploadedFile != null) { + FileUtil.streamToFile(uploadedFile.content, file.absolutePath) + } else { + Launcher.instance.logger.info(ctx.body()) + if (ctx.body().isNotEmpty()) { + file.writeText(ctx.body()) + } + } + return true + } + + private fun getFileFromRequest(ctx: Context): File { + val filepath = ctx.req.pathInfo.replace("/filemanager/", "") + if (filepath.isBlank()) return File(".") + return File(filepath) + } + + private fun checkForSuspiciousPath(ctx: Context) { + if (ctx.req.pathInfo.contains("..") || ctx.req.pathInfo.contains("//")) + throw InvalidPathException("Invalid file path") + } + + class FileAlreadyExistsException(message: String) : Exception(message) + + class InvalidPathException(message: String) : Exception(message) + + class FileInfo(val name: String, val isDirectory: Boolean, val size: Long) + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupActionController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupActionController.kt new file mode 100644 index 000000000..877f1f1ea --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupActionController.kt @@ -0,0 +1,57 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.group + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.module.rest.annotation.RequestMapping +import eu.thesimplecloud.module.rest.annotation.RequestPathParam +import eu.thesimplecloud.module.rest.annotation.RequestType +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 17:56 + * @author Frederick Baier + */ +@RestController("cloud/action/group/") +class ServiceGroupActionController : IController { + + @RequestMapping(RequestType.POST, "name/:name/startService", "web.cloud.action.group.startservice") + fun handleStartNewService(@RequestPathParam("name") name: String): ICloudService? { + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name) + ?: return null + return serviceGroup.startNewService().getBlocking() + } + + @RequestMapping(RequestType.POST, "name/:name/shutdownAll", "web.cloud.action.group.shutdownall") + fun handleStopAllServices(@RequestPathParam("name") name: String): Boolean { + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name) + ?: throwNoSuchElement() + serviceGroup.shutdownAllServices() + return true + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupController.kt new file mode 100644 index 000000000..d0ee53c5c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/group/ServiceGroupController.kt @@ -0,0 +1,134 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.group + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudLobbyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudProxyGroup +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultLobbyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultProxyGroup +import eu.thesimplecloud.api.servicegroup.impl.DefaultServerGroup +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.controller.IController +import io.javalin.http.Context +import kotlin.reflect.KClass + +/** + * Created by IntelliJ IDEA. + * Date: 05.10.2020 + * Time: 17:13 + * @author Frederick Baier + */ +@RestController("cloud/group/") +class ServiceGroupController : IController { + + //Get groups + + @RequestMapping(RequestType.GET, "", "web.cloud.group.get.all") + fun handleGetAllGroups(): List { + return CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + } + + @RequestMapping(RequestType.GET, "name/:name", "web.cloud.group.get.one") + fun handleGetOneGroup(@RequestPathParam("name") name: String): ICloudServiceGroup? { + return CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name) + } + + @RequestMapping(RequestType.GET, "name/:name/services", "web.cloud.group.get.services") + fun handleGetServicesOfGroup(@RequestPathParam("name") name: String): List { + return CloudAPI.instance.getCloudServiceManager().getCloudServicesByGroupName(name) + } + + //Get group types + + @RequestMapping(RequestType.GET, "lobby/", "web.cloud.group.get.type") + fun handleGetLobbyGroups(): List { + return CloudAPI.instance.getCloudServiceGroupManager().getLobbyGroups() + } + + @RequestMapping(RequestType.GET, "server/", "web.cloud.group.get.type") + fun handleGetServerGroups(): List { + return CloudAPI.instance.getCloudServiceGroupManager().getServerGroups() + } + + @RequestMapping(RequestType.GET, "proxy/", "web.cloud.group.get.type") + fun handleGetProxyGroups(): List { + return CloudAPI.instance.getCloudServiceGroupManager().getProxyGroups() + } + + //Create groups + + @RequestMapping(RequestType.POST, "lobby/", "web.cloud.group.create") + fun handleCreateLobbyGroup(@RequestBody group: DefaultLobbyGroup): Boolean { + return CloudAPI.instance.getCloudServiceGroupManager().createServiceGroup(group).syncUninterruptibly().isSuccess + } + + @RequestMapping(RequestType.POST, "server/", "web.cloud.group.create") + fun handleCreateServerGroup(@RequestBody group: DefaultServerGroup): Boolean { + return CloudAPI.instance.getCloudServiceGroupManager().createServiceGroup(group).syncUninterruptibly().isSuccess + } + + @RequestMapping(RequestType.POST, "proxy/", "web.cloud.group.create") + fun handleCreateProxyGroup(@RequestBody group: DefaultProxyGroup): Boolean { + return CloudAPI.instance.getCloudServiceGroupManager().createServiceGroup(group).syncUninterruptibly().isSuccess + } + + //Update groups + + @RequestMapping(RequestType.PUT, "", "web.cloud.group.update") + fun handleUpdateLobbyGroup(ctx: Context): Boolean { + val jsonLib = JsonLib.fromJsonString(ctx.body()) + val groupName = jsonLib.getString("name") ?: throwNoSuchElement() + if (!doesGroupExist(groupName)) throwNoSuchElement() + val groupClass = getRegisteredGroupTypeClassByName(groupName) + val updateGroup = jsonLib.getObject(groupClass.java) + CloudAPI.instance.getCloudServiceGroupManager().update(updateGroup) + return true + } + + //delete groups + @RequestMapping(RequestType.DELETE, "name/:name", "web.cloud.group.delete") + fun handleDeleteServiceGroup(@RequestPathParam("name") name: String): Boolean { + if (!doesGroupExist(name)) throwNoSuchElement() + val group = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name)!! + CloudAPI.instance.getCloudServiceGroupManager().delete(group) + return true + } + + private fun getRegisteredGroupTypeClassByName(groupName: String): KClass { + return CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(groupName)!!::class + } + + private fun doesGroupExist(group: ICloudServiceGroup): Boolean { + return doesGroupExist(group.getName()) + } + + private fun doesGroupExist(name: String): Boolean { + return CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(name) != null + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerActionController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerActionController.kt new file mode 100644 index 000000000..e3e3dfbef --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerActionController.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.player + +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 07.10.2020 + * Time: 19:46 + * @author Frederick Baier + */ +@RestController("cloud/action/player/") +class PlayerActionController : IController { + + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerController.kt new file mode 100644 index 000000000..d84de012d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/player/PlayerController.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.player + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.IOfflineCloudPlayer +import eu.thesimplecloud.api.player.SimpleCloudPlayer +import eu.thesimplecloud.module.rest.annotation.RequestMapping +import eu.thesimplecloud.module.rest.annotation.RequestPathParam +import eu.thesimplecloud.module.rest.annotation.RequestType +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 07.10.2020 + * Time: 19:38 + * @author Frederick Baier + */ +@RestController("cloud/player/") +class PlayerController : IController { + + @RequestMapping(RequestType.GET, "name/:name", "web.cloud.player.get.one") + fun handleGetOnePlayer(@RequestPathParam("name") name: String): IOfflineCloudPlayer { + return CloudAPI.instance.getCloudPlayerManager().getOfflineCloudPlayer(name).getBlockingOrNull() + ?: throwNoSuchElement() + } + + @RequestMapping(RequestType.GET, "", "web.cloud.player.get.all") + fun handleGetAllPlayer(): List { + return CloudAPI.instance.getCloudPlayerManager().getAllOnlinePlayers().getBlockingOrNull() ?: emptyList() + } + + @RequestMapping(RequestType.GET, "count", "web.cloud.player.get.all") + fun handleGetOnlinePlayerCount(): Int { + return CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects().size + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceActionController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceActionController.kt new file mode 100644 index 000000000..fd6b61287 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceActionController.kt @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.controller.IController +import eu.thesimplecloud.module.rest.defaultcontroller.dto.CommandDto +import eu.thesimplecloud.module.rest.defaultcontroller.dto.PathDto + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 16:38 + * @author Frederick Baier + */ +@RestController("cloud/action/service/") +class ServiceActionController : IController { + + @RequestMapping(RequestType.POST, "name/:name/shutdown", "web.cloud.action.service.shutdown") + fun handleServiceStop(@RequestPathParam("name") name: String): ICloudService { + val service = getServiceByName(name) ?: throwNoSuchElement() + service.shutdown() + return service + } + + @RequestMapping(RequestType.POST, "name/:name/copy", "web.cloud.action.service.copy") + fun handleCopyService(@RequestPathParam("name") name: String, @RequestBody path: PathDto): ICloudService { + val service = getServiceByName(name) ?: throwNoSuchElement() + service.copy(path.path) + return service + } + + @RequestMapping(RequestType.POST, "name/:name/execute", "web.cloud.action.service.execute") + fun handleCommandExecute(@RequestPathParam("name") name: String, @RequestBody command: CommandDto): ICloudService { + val service = getServiceByName(name) ?: throwNoSuchElement() + service.executeCommand(command.command) + return service + } + + private fun getServiceByName(name: String): ICloudService? { + return CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceController.kt new file mode 100644 index 000000000..ef6931f19 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/service/ServiceController.kt @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.impl.DefaultCloudService +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 16:26 + * @author Frederick Baier + */ +@RestController("cloud/service/") +class ServiceController : IController { + + @RequestMapping(RequestType.GET, "", "web.cloud.service.get.all") + fun handleGetAllServices(): List { + return CloudAPI.instance.getCloudServiceManager().getAllCachedObjects() + } + + @RequestMapping(RequestType.GET, "name/:name", "web.cloud.service.get.one") + fun handleGetOneService(@RequestPathParam("name") name: String): ICloudService { + return CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) ?: throwNoSuchElement() + } + + @RequestMapping(RequestType.PUT, "", "web.cloud.service.update") + fun handleUpdateService(@RequestBody service: DefaultCloudService): ICloudService { + if (!doesServiceExist(service.getName())) throwNoSuchElement() + CloudAPI.instance.getCloudServiceManager().update(service) + return service + } + + @RequestMapping(RequestType.GET, "logs/:name", "web.cloud.service.logs") + fun handleGetServiceLogs(@RequestPathParam("name") name: String): List { + if (!doesServiceExist(name)) throwNoSuchElement() + val screen = Launcher.instance.screenManager.getScreen(name) + return screen?.getAllSavedMessages() ?: emptyList() + } + + private fun doesServiceExist(name: String): Boolean { + return CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(name) != null + } + + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/template/TemplateController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/template/TemplateController.kt new file mode 100644 index 000000000..e1301e0c0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/template/TemplateController.kt @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.template + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.template.ITemplate +import eu.thesimplecloud.api.template.impl.DefaultTemplate +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 06.10.2020 + * Time: 19:59 + * @author Frederick Baier + */ +@RestController("cloud/template/") +class TemplateController : IController { + + @RequestMapping(RequestType.GET, "", "web.cloud.template.get.all") + fun handleGetAllTemplates(): List { + return CloudAPI.instance.getTemplateManager().getAllCachedObjects() + } + + @RequestMapping(RequestType.GET, "name/:name/", "web.cloud.template.get.one") + fun handleGetOneTemplates(@RequestPathParam("name") name: String): ITemplate { + return CloudAPI.instance.getTemplateManager().getTemplateByName(name) ?: throwNoSuchElement() + } + + @RequestMapping(RequestType.POST, "", "web.cloud.template.create") + fun handleCreateTemplate(@RequestBody template: DefaultTemplate): ITemplate { + if (doesTemplateExist(template.getName())) throwElementAlreadyExist() + CloudAPI.instance.getTemplateManager().update(template) + return template + } + + @RequestMapping(RequestType.PUT, "", "web.cloud.template.update") + fun handleUpdateTemplate(@RequestBody template: DefaultTemplate): ITemplate { + if (!doesTemplateExist(template.getName())) throwNoSuchElement() + CloudAPI.instance.getTemplateManager().update(template) + return template + } + + @RequestMapping(RequestType.DELETE, "name/:name", "web.cloud.template.delete") + fun handleDeleteTemplate(@RequestPathParam("name") name: String): ITemplate { + if (!doesTemplateExist(name)) throwNoSuchElement() + val template = CloudAPI.instance.getTemplateManager().getTemplateByName(name)!! + CloudAPI.instance.getTemplateManager().deleteTemplate(name) + return template + } + + private fun doesTemplateExist(name: String): Boolean { + return CloudAPI.instance.getTemplateManager().getTemplateByName(name) != null + } + + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/uptime/UptimeController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/uptime/UptimeController.kt new file mode 100644 index 000000000..5120eeeb7 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/uptime/UptimeController.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.uptime + +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.rest.annotation.RequestMapping +import eu.thesimplecloud.module.rest.annotation.RequestType +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 23.11.2020 + * Time: 18:04 + * @author Frederick Baier + */ +@RestController("cloud/uptime/") +class UptimeController : IController { + + @RequestMapping(RequestType.GET, "", "web.cloud.uptime.get") + fun handleGetUptime(): Long { + return Launcher.instance.getUpTime() / 1000 + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/version/VersionController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/version/VersionController.kt new file mode 100644 index 000000000..51927d09c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/version/VersionController.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.version + +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.rest.annotation.RequestMapping +import eu.thesimplecloud.module.rest.annotation.RequestType +import eu.thesimplecloud.module.rest.annotation.RestController +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 13.11.2020 + * Time: 12:51 + * @author Frederick Baier + */ +@RestController("version/") +class VersionController : IController { + + @RequestMapping(RequestType.GET, "cloud/") + fun handleGetCloudVersion(): String { + return Launcher.instance.getCurrentVersion() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/wrapper/WrapperController.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/wrapper/WrapperController.kt new file mode 100644 index 000000000..021a810e3 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/defaultcontroller/wrapper/WrapperController.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.defaultcontroller.wrapper + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.api.wrapper.impl.DefaultWrapperInfo +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.controller.IController + +/** + * Created by IntelliJ IDEA. + * Date: 07.10.2020 + * Time: 19:20 + * @author Frederick Baier + */ +@RestController("cloud/wrapper/") +class WrapperController : IController { + + @RequestMapping(RequestType.GET, "", "web.cloud.wrapper.get.all") + fun handleGetAllWrappers(): List { + return CloudAPI.instance.getWrapperManager().getAllCachedObjects() + } + + @RequestMapping(RequestType.GET, "name/:name/", "web.cloud.wrapper.get.one") + fun handleGetOneWrapper(@RequestPathParam("name") name: String): IWrapperInfo? { + return getWrapperByName(name) + } + + @RequestMapping(RequestType.POST, "", "web.cloud.wrapper.create") + fun handleCreateWrapper(@RequestBody wrapper: DefaultWrapperInfo): IWrapperInfo { + if (doesWrapperExist(wrapper.getName())) throwElementAlreadyExist() + CloudAPI.instance.getWrapperManager().update(wrapper) + return wrapper + } + + @RequestMapping(RequestType.PUT, "", "web.cloud.wrapper.update") + fun handleUpdateWrapper(@RequestBody wrapper: DefaultWrapperInfo): IWrapperInfo? { + if (!doesWrapperExist(wrapper.getName())) throwNoSuchElement() + CloudAPI.instance.getWrapperManager().update(wrapper) + return wrapper + } + + @RequestMapping(RequestType.DELETE, "name/:name", "web.cloud.wrapper.delete") + fun handleDeleteWrapper(@RequestPathParam("name") name: String): IWrapperInfo? { + if (!doesWrapperExist(name)) throwNoSuchElement() + val wrapper = getWrapperByName(name)!! + CloudAPI.instance.getWrapperManager().delete(wrapper) + return wrapper + } + + + private fun getWrapperByName(name: String): IWrapperInfo? { + return CloudAPI.instance.getWrapperManager().getWrapperByName(name) + } + + private fun doesWrapperExist(name: String): Boolean { + return getWrapperByName(name) != null + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/ElementAlreadyExistException.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/ElementAlreadyExistException.kt new file mode 100644 index 000000000..07acf1d76 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/ElementAlreadyExistException.kt @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.exception + +/** + * Created by IntelliJ IDEA. + * Date: 09.10.2020 + * Time: 23:49 + * @author Frederick Baier + */ +class ElementAlreadyExistException : Exception("The element does already exist") \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/NullResultException.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/NullResultException.kt new file mode 100644 index 000000000..96b2d91ea --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/exception/NullResultException.kt @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.exception + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 10:57 + * @author Frederick Baier + */ +class NullResultException : Exception("Result is null") \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/JavalinRequestHandler.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/JavalinRequestHandler.kt new file mode 100644 index 000000000..688cbc187 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/JavalinRequestHandler.kt @@ -0,0 +1,85 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.javalin + +import com.auth0.jwt.interfaces.DecodedJWT +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.rest.auth.AuthService +import eu.thesimplecloud.module.rest.auth.JwtProvider +import eu.thesimplecloud.module.rest.auth.user.User +import eu.thesimplecloud.module.rest.controller.RequestMethodData +import eu.thesimplecloud.module.rest.defaultcontroller.dto.ErrorDto +import io.javalin.http.Context +import io.javalin.http.Handler +import javalinjwt.JavalinJWT +import java.lang.reflect.InvocationTargetException +import java.util.* + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 18:02 + * @author Frederick Baier + */ +class JavalinRequestHandler(val requestMethodData: RequestMethodData, private val authService: AuthService) : Handler { + + override fun handle(ctx: Context) { + val user = getUserByContext(ctx) + + if (!isPermitted(user)) { + ctx.result("Unauthorized") + ctx.status(401) + return + } + + try { + SingleRequestProcessor(ctx, requestMethodData, user).processRequest() + } catch (ex: Exception) { + val exception = if (ex is InvocationTargetException) ex.cause!! else ex + ctx.status(500) + val json = JsonLib.fromObject(ErrorDto.fromException(exception)) + ctx.result(json.getAsJsonString()) + + ex.printStackTrace() + } + } + + private fun isPermitted(user: User?): Boolean { + return user?.hasPermission(this.requestMethodData.permission) ?: requestMethodData.permission.isEmpty() + } + + private fun getUserByContext(context: Context): User? { + val decodedJWTOptional: Optional = JavalinJWT.getTokenFromHeader(context) + .flatMap(JwtProvider.instance.provider::validateToken) as Optional + + if (!decodedJWTOptional.isPresent) { + return null + } + + val decodedJWT = decodedJWTOptional.get() + + val username = decodedJWT.getClaim("username").asString() + return authService.getUserByName(username) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/RestServer.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/RestServer.kt new file mode 100644 index 000000000..ef80d9128 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/RestServer.kt @@ -0,0 +1,121 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.javalin + +import eu.thesimplecloud.clientserverapi.lib.json.PacketExclude +import eu.thesimplecloud.jsonlib.GsonCreator +import eu.thesimplecloud.module.rest.annotation.WebExclude +import eu.thesimplecloud.module.rest.auth.AuthService +import eu.thesimplecloud.module.rest.auth.JwtProvider +import eu.thesimplecloud.module.rest.auth.Roles +import eu.thesimplecloud.module.rest.auth.controller.AuthController +import eu.thesimplecloud.module.rest.auth.createRolesMapping +import eu.thesimplecloud.module.rest.controller.ControllerHandler +import eu.thesimplecloud.module.rest.controller.RequestMethodData +import eu.thesimplecloud.module.rest.defaultcontroller.UserController +import eu.thesimplecloud.module.rest.defaultcontroller.filemanager.FileManagerController +import eu.thesimplecloud.module.rest.defaultcontroller.group.ServiceGroupActionController +import eu.thesimplecloud.module.rest.defaultcontroller.group.ServiceGroupController +import eu.thesimplecloud.module.rest.defaultcontroller.player.PlayerController +import eu.thesimplecloud.module.rest.defaultcontroller.service.ServiceActionController +import eu.thesimplecloud.module.rest.defaultcontroller.service.ServiceController +import eu.thesimplecloud.module.rest.defaultcontroller.template.TemplateController +import eu.thesimplecloud.module.rest.defaultcontroller.uptime.UptimeController +import eu.thesimplecloud.module.rest.defaultcontroller.version.VersionController +import eu.thesimplecloud.module.rest.defaultcontroller.wrapper.WrapperController +import io.javalin.Javalin +import io.javalin.core.security.SecurityUtil +import io.javalin.http.HandlerType +import javalinjwt.JWTAccessManager +import javalinjwt.JavalinJWT + +/** + * Created by IntelliJ IDEA. + * Date: 04.10.2020 + * Time: 18:01 + * @author Frederick Baier + */ +class RestServer(port: Int) { + + private val authService = AuthService() + + val controllerHandler = ControllerHandler(this) + + private val app = Javalin.create().start(port) + + val webGson = GsonCreator().excludeAnnotations(WebExclude::class.java, PacketExclude::class.java).create() + + init { + instance = this + + app.config.accessManager(JWTAccessManager("role", createRolesMapping(), Roles.ANYONE)) + app.before(JavalinJWT.createHeaderDecodeHandler(JwtProvider.instance.provider)) + app.before { ctx -> + ctx.header("Access-Control-Allow-Headers", "*") + ctx.header("Access-Control-Allow-Origin", "*") + ctx.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS") + ctx.header("Content-Type", "application/json; charset=utf-8") + } + + app.options("/*", { + it.status(200) + }, SecurityUtil.roles(Roles.ANYONE)) + + controllerHandler.registerController(AuthController(this.authService)) + controllerHandler.registerController(UserController(this.authService)) + controllerHandler.registerController(ServiceGroupController()) + controllerHandler.registerController(ServiceGroupActionController()) + controllerHandler.registerController(ServiceController()) + controllerHandler.registerController(ServiceActionController()) + controllerHandler.registerController(TemplateController()) + controllerHandler.registerController(WrapperController()) + controllerHandler.registerController(PlayerController()) + controllerHandler.registerController(VersionController()) + controllerHandler.registerController(FileManagerController()) + controllerHandler.registerController(UptimeController()) + } + + fun registerRequestMethod(requestMethodData: RequestMethodData) { + val requestHandler = JavalinRequestHandler(requestMethodData, authService) + addToJavalin(requestHandler) + } + + private fun addToJavalin(requestHandler: JavalinRequestHandler) { + val requestMethodData = requestHandler.requestMethodData + app.addHandler( + HandlerType.valueOf(requestMethodData.requestType.name), + requestMethodData.path, + requestHandler, + setOf(Roles.ANYONE) + ) + } + + fun shutdown() { + app.stop() + } + + + companion object { + lateinit var instance: RestServer + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/SingleRequestProcessor.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/SingleRequestProcessor.kt new file mode 100644 index 000000000..4e049a4b2 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/javalin/SingleRequestProcessor.kt @@ -0,0 +1,141 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.javalin + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.rest.annotation.RequestBody +import eu.thesimplecloud.module.rest.annotation.RequestParam +import eu.thesimplecloud.module.rest.annotation.RequestPathParam +import eu.thesimplecloud.module.rest.annotation.RequestingUser +import eu.thesimplecloud.module.rest.auth.user.User +import eu.thesimplecloud.module.rest.controller.RequestMethodData +import eu.thesimplecloud.module.rest.defaultcontroller.dto.ErrorDto +import eu.thesimplecloud.module.rest.defaultcontroller.dto.ResultDto +import eu.thesimplecloud.module.rest.exception.NullResultException +import io.javalin.http.Context +import java.lang.reflect.InvocationTargetException + +/** + * Created by IntelliJ IDEA. + * Date: 05.10.2020 + * Time: 13:43 + * @author Frederick Baier + */ +class SingleRequestProcessor( + private val ctx: Context, + private val requestMethodData: RequestMethodData, + private val requestingUser: User? +) { + + fun processRequest() { + val parameterDataToInvokeValue = try { + handleParameters() + } catch (e: Exception) { + handleClientFaultException(e) + return + } + + val valueArray = parameterDataToInvokeValue.values.toTypedArray() + + val result = try { + this.requestMethodData.method.invoke(this.requestMethodData.controller, *valueArray) + } catch (e: Exception) { + val ex = if (e is InvocationTargetException) e.cause!! else e + handleClientFaultException(ex) + return + } + + //then the result was set by the called method + if (this.ctx.resultString() != null) { + return + } + + if (result == null) { + throw NullResultException() + } + + if (result == Unit) { + return + } + + ctx.status(200) + val resultDto = ResultDto(result) + ctx.result(JsonLib.fromObject(resultDto, RestServer.instance.webGson).getAsJsonString()) + } + + private fun handleClientFaultException(ex: Throwable) { + ctx.status(400) + ctx.result(JsonLib.fromObject(ErrorDto.fromException(ex)).getAsJsonString()) + } + + private fun handleParameters(): Map { + val parameterDataToInvokeValue = requestMethodData.parameters + .map { it to handleValueForParameter(it) }.toMap() + + if (parameterDataToInvokeValue.any { isValueIncorrect(it.key, it.value) }) { + throw IncorrectValueException("A value is incorrect") + } + return parameterDataToInvokeValue + } + + private fun isValueIncorrect(parameterData: RequestMethodData.RequestParameterData, value: Any?): Boolean { + val annotation = parameterData.annotation + if (annotation is RequestParam) { + return annotation.required && value == null + } + if (annotation is RequestPathParam) { + return value == null + } + return false + } + + + private fun handleValueForParameter(parameterData: RequestMethodData.RequestParameterData): Any? { + if (parameterData.parameterType == Context::class.java) { + return this.ctx + } + if (parameterData.parameterType == User::class.java && parameterData.annotation is RequestingUser) { + return this.requestingUser + } + + val annotation = parameterData.annotation!! + when (annotation) { + is RequestBody -> { + return JsonLib.fromJsonString(this.ctx.body(), RestServer.instance.webGson) + .getObject(parameterData.parameterType) + } + is RequestParam -> { + val parameter = this.ctx.req.getParameter(annotation.parameterName) ?: return null + return JsonLib.fromJsonString(parameter).getObject(parameterData.parameterType) + } + is RequestPathParam -> { + val pathParam = this.ctx.pathParam(annotation.parameterName) + return JsonLib.fromJsonString(pathParam).getObject(parameterData.parameterType) + } + } + throw IllegalStateException() + } + + class IncorrectValueException(message: String) : Exception(message) + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/util/ContextClassLoaderChanger.kt b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/util/ContextClassLoaderChanger.kt new file mode 100644 index 000000000..a4fb9f7b7 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/kotlin/eu/thesimplecloud/module/rest/util/ContextClassLoaderChanger.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.rest.util + +/** + * Created by IntelliJ IDEA. + * Date: 13.06.2021 + * Time: 11:55 + * @author Frederick Baier + */ + +fun executeWithDifferentContextClassLoader(classLoader: ClassLoader, runnable: Runnable) { + val currentContextClassLoader = Thread.currentThread().contextClassLoader + changedContextClassLoader(classLoader) + runnable.run() + changedContextClassLoader(currentContextClassLoader) +} + +private fun changedContextClassLoader(classLoader: ClassLoader) { + Thread.currentThread().contextClassLoader = classLoader +} diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/de.json new file mode 100644 index 000000000..b8715ed95 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/de.json @@ -0,0 +1,3 @@ +{ + "module.rest.loaded": "Der REST-Server lauscht auf Port %PORT%" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/en.json new file mode 100644 index 000000000..cd6bcac06 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/resources/languages/en.json @@ -0,0 +1,3 @@ +{ + "module.rest.loaded": "REST-Server is listening on port %PORT%" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-rest/src/main/resources/module.json new file mode 100644 index 000000000..47c132525 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/resources/module.json @@ -0,0 +1,29 @@ +{ + "name": "SimpleCloud-Rest", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.rest.RestModule", + "moduleCopyType": "NONE", + "repositories": [ + "https://repo.maven.apache.org/maven2/", + "https://jitpack.io/" + ], + "dependencies": [ + { + "groupId": "io.javalin", + "artifactId": "javalin", + "version": "3.13.7" + }, + { + "groupId": "com.auth0", + "artifactId": "java-jwt", + "version": "3.16.0" + }, + { + "groupId": "com.github.kmehrunes", + "artifactId": "javalin-jwt", + "version": "v0.2" + } + ], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-rest/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-rest/src/main/resources/updater.json new file mode 100644 index 000000000..89f019cd4 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-rest/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-rest", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-serviceselection/build.gradle b/simplecloud-modules/simplecloud-module-serviceselection/build.gradle new file mode 100644 index 000000000..6746b6e53 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-serviceselection/build.gradle @@ -0,0 +1,21 @@ +repositories { + mavenCentral() +} + +dependencies { + testApi group: 'junit', name: 'junit', version: '4.12' + compileOnly(project(":simplecloud-api")) + testApi(project(":simplecloud-api")) + + + compileOnly 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT' + testApi group: 'commons-io', name: 'commons-io', version: dependencyCommonsIOVersion + testApi group: 'com.google.guava', name: 'guava', version: dependencyGuavaVersion + testApi group: 'io.netty', name: 'netty-all', version: dependencyNettyVersion + testApi group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: dependencyKotlinCouroutinesVersion + testApi 'io.mockk:mockk:1.12.3' +} + +shadowJar { + archiveFileName.set("SimpleCloud-ServiceSelection.jar") +} diff --git a/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/AbstractServiceViewer.kt b/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/AbstractServiceViewer.kt new file mode 100644 index 000000000..9eb3cbdc8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/AbstractServiceViewer.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.serviceselection.api + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState + +abstract class AbstractServiceViewer { + + var service: ICloudService? = null + + /** + * Update will be called when the service was changed + */ + abstract fun updateView() + + /** + * Will be called when this viewer shall be removed + */ + abstract fun removeView() + + fun isVacant() = service == null || !service!!.isStartingOrVisible() + + fun isCurrentServiceStarting() = this.service?.getState() == ServiceState.STARTING + +} diff --git a/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewGroupManager.kt b/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewGroupManager.kt new file mode 100644 index 000000000..454bfc8bb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewGroupManager.kt @@ -0,0 +1,103 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.serviceselection.api + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +/** + * Created by IntelliJ IDEA. + * Date: 01.07.2020 + * Time: 11:47 + * @author Frederick Baier + */ +class ServiceViewGroupManager( + val group: ICloudServiceGroup +) { + + private val serviceViewers: MutableList = ArrayList() + + fun addServiceViewers(vararg serviceViewer: T) { + this.serviceViewers.addAll(serviceViewer) + } + + fun removeServiceViewer(serviceViewer: T) { + this.serviceViewers.remove(serviceViewer) + serviceViewer.removeView() + } + + fun sortWaitingServicesToViewers() { + val allServicesWaiting = getAllServicesWaitingForViewer() + val allVisibleServices = allServicesWaiting.filter { it.getState() == ServiceState.VISIBLE } + val allStartingServices = allServicesWaiting.filter { it.getState() == ServiceState.STARTING } + allVisibleServices.forEach { searchViewerForService(it) } + allStartingServices.forEach { searchViewerForService(it) } + } + + fun updateAllViewers() { + this.serviceViewers.forEach { it.updateView() } + } + + fun getServiceViewers(): List { + return this.serviceViewers + } + + private fun searchViewerForService(service: ICloudService) { + require(!hasViewer(service)) { "Service does already has a viewer" } + val newViewer = getNewViewerForService(service) + newViewer?.service = service + //don't update here. The update method will be called for all viewers after sorting the services to the viewers. + } + + private fun getNewViewerForService(service: ICloudService): T? { + require(!hasViewer(service)) { "Service does already has a viewer" } + return if (service.getState() == ServiceState.VISIBLE) { + getVacantOrStartingViewer() + } else { + //state must be starting + getVacantViewer() + } + } + + private fun getVacantOrStartingViewer(): T? { + return this.serviceViewers.firstOrNull { it.isVacant() || it.isCurrentServiceStarting() } + } + + private fun getVacantViewer(): T? { + return this.serviceViewers.firstOrNull { it.isVacant() } + } + + private fun hasViewer(service: ICloudService): Boolean { + return this.serviceViewers.any { it.service == service } + } + + private fun getAllServicesWaitingForViewer(): List { + return getAllServicesToDisplay().filter { !hasViewer(it) } + } + + private fun getAllServicesToDisplay(): List { + return this.group.getAllServices().filter { it.isStartingOrVisible() } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewManager.kt b/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewManager.kt new file mode 100644 index 000000000..a60d71b1e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-serviceselection/src/main/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceViewManager.kt @@ -0,0 +1,69 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.serviceselection.api + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import org.bukkit.Bukkit +import org.bukkit.plugin.java.JavaPlugin + +open class ServiceViewManager( + private val plugin: JavaPlugin, + private val updateDelay: Long = 20 +) { + + private val groupNameToGroupView = HashMap>() + + init { + startUpdateScheduler() + } + + private fun startUpdateScheduler() { + Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, { + performUpdate() + }, 20, this.updateDelay) + } + + fun addServiceViewGroupManager(serviceViewGroupManager: ServiceViewGroupManager) { + this.groupNameToGroupView[serviceViewGroupManager.group.getName()] = serviceViewGroupManager + } + + fun getGroupView(group: ICloudServiceGroup): ServiceViewGroupManager { + return this.groupNameToGroupView.getOrPut(group.getName()) { ServiceViewGroupManager(group) } + } + + fun isGroupViewRegistered(group: ICloudServiceGroup): Boolean { + return this.groupNameToGroupView.containsKey(group.getName()) + } + + fun getAllGroupViewManagers(): Collection> { + return this.groupNameToGroupView.values + } + + open fun performUpdate() { + val groups = this.groupNameToGroupView.values + groups.forEach { it.sortWaitingServicesToViewers() } + groups.forEach { it.updateAllViewers() } + } + + +} diff --git a/simplecloud-modules/simplecloud-module-serviceselection/src/test/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceSelectionTest.kt b/simplecloud-modules/simplecloud-module-serviceselection/src/test/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceSelectionTest.kt new file mode 100644 index 000000000..04189d4eb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-serviceselection/src/test/kotlin/eu/thesimplecloud/module/serviceselection/api/ServiceSelectionTest.kt @@ -0,0 +1,46 @@ +package eu.thesimplecloud.module.serviceselection.api + +import eu.thesimplecloud.api.service.ICloudService +import io.mockk.mockk +import io.mockk.spyk +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.Test + +/** + * Created by IntelliJ IDEA. + * Date: 29.06.2020 + * Time: 13:38 + * @author Frederick Baier + */ +class ServiceSelectionTest { + + private lateinit var serviceViewer: AbstractServiceViewer + + @Before + fun setUp() { + this.serviceViewer = createServiceDisplayer() + } + + @Test + fun newServiceDisplayer_ServiceNull() { + assertNull(this.serviceViewer.service) + } + + @Test + fun setService_ServiceEqualsSetService() { + val service = createDummyService() + this.serviceViewer.service = service + assertEquals(service, this.serviceViewer.service) + } + + private fun createServiceDisplayer(): AbstractServiceViewer { + return spyk() + } + + private fun createDummyService(): ICloudService { + return mockk() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/build.gradle b/simplecloud-modules/simplecloud-module-sign/build.gradle new file mode 100644 index 000000000..39de94bf6 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/build.gradle @@ -0,0 +1,26 @@ + +shadowJar { + archiveFileName.set("SimpleCloud-Sign.jar") +} + +dependencies { + compileOnly(project(":simplecloud-base")) { + transitive = false + } + compileOnly(project(":simplecloud-api")) { + transitive = false + } + compileOnly(project(":simplecloud-plugin")) { + transitive = false + } + compileOnly(project(":simplecloud-launcher")) { + transitive = false + } + api(project(":simplecloud-modules:simplecloud-module-serviceselection")) { + transitive = false + } + + compileOnly 'org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT' + compileOnly(group: 'commons-io', name: 'commons-io', version: dependencyCommonsIOVersion) + +} diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/SignModuleConfig.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/SignModuleConfig.kt new file mode 100644 index 000000000..6ec7f7e03 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/SignModuleConfig.kt @@ -0,0 +1,78 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.module.sign.lib.group.GroupLayoutsContainer +import eu.thesimplecloud.module.sign.lib.layout.LayoutType +import eu.thesimplecloud.module.sign.lib.layout.SignLayout +import eu.thesimplecloud.module.sign.lib.layout.SignLayoutContainer +import eu.thesimplecloud.module.sign.lib.settings.CloudSignSettingsContainer +import eu.thesimplecloud.module.sign.lib.sign.CloudSignContainer + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 17:01 + * @author Frederick Baier + */ +class SignModuleConfig( + val signLayoutContainer: SignLayoutContainer, + val signContainer: CloudSignContainer, + val groupsLayoutContainer: GroupLayoutsContainer, + val cloudSignSettingsContainer: CloudSignSettingsContainer +) { + + fun getSignLayoutForGroup(layoutType: LayoutType, groupName: String): SignLayout { + val groupLayouts = this.groupsLayoutContainer.getGroupLayoutsByGroupName(groupName) + ?: return getDefaultLayout(layoutType) + val layoutName = groupLayouts.getLayoutNameByType(layoutType) + return this.signLayoutContainer.getLayoutByName(layoutType, layoutName)!! + } + + private fun getDefaultLayout(layoutType: LayoutType): SignLayout { + return this.signLayoutContainer.getDefaultLayout(layoutType) + } + + fun update() { + property = CloudAPI.instance.getGlobalPropertyHolder().setProperty("sign-config", this) + } + + companion object { + + @Volatile + private var property: IProperty? = null + + fun getConfig(): SignModuleConfig { + if (this.property == null) { + this.property = + CloudAPI.instance.getGlobalPropertyHolder().requestProperty("sign-config") + .getBlocking() + } + return this.property!!.getValue() + } + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayouts.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayouts.kt new file mode 100644 index 000000000..ccf5e3d9e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayouts.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.group + +import eu.thesimplecloud.module.sign.lib.layout.LayoutType + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 14:52 + * @author Frederick Baier + */ +class GroupLayouts( + val groupName: String, + val layoutTypeToLayoutName: MutableMap +) { + + fun setLayout(layoutType: LayoutType, layoutName: String) { + this.layoutTypeToLayoutName[layoutType] = layoutName + } + + fun getLayoutNameByType(layoutType: LayoutType): String { + return this.layoutTypeToLayoutName[layoutType] ?: "default" + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayoutsContainer.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayoutsContainer.kt new file mode 100644 index 000000000..e86d35927 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/group/GroupLayoutsContainer.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.group + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 14:57 + * @author Frederick Baier + */ +class GroupLayoutsContainer { + + private val groupLayouts = CopyOnWriteArrayList() + + fun addGroupLayouts(groupLayouts: GroupLayouts) { + this.groupLayouts.add(groupLayouts) + } + + fun hasGroupLayout(group: ICloudServiceGroup): Boolean { + return getGroupLayoutsByGroupName(group.getName()) != null + } + + fun getAllGroupLayouts(): List { + return this.groupLayouts + } + + fun getGroupLayoutsByGroupName(name: String): GroupLayouts? { + return this.groupLayouts.firstOrNull { it.groupName == name } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/LayoutType.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/LayoutType.kt new file mode 100644 index 000000000..052937729 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/LayoutType.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.layout + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 13:16 + * @author Frederick Baier + */ +enum class LayoutType { + + SEARCHING, + + STARTING, + + ONLINE, + + FULL, + + MAINTENANCE + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignFrame.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignFrame.kt new file mode 100644 index 000000000..781e34a53 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignFrame.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.layout + +class SignFrame( + val lines: Array +) { + + init { + if (lines.size != 4) throw IllegalStateException("Frame must have 4 lines") + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayout.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayout.kt new file mode 100644 index 000000000..ef0b1116b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayout.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.layout + +import eu.thesimplecloud.api.utils.Nameable +import eu.thesimplecloud.jsonlib.JsonLibExclude + +class SignLayout( + private val name: String, + val layoutType: LayoutType, + private val frames: List +) : Nameable { + + @JsonLibExclude + private var currentFrameIndex = 0 + + fun getCurrentFrame(): SignFrame { + return frames.getOrNull(currentFrameIndex) ?: SignFrame(arrayOf("", "empty layout", "", "")) + } + + fun nextFrame() { + currentFrameIndex++ + if (currentFrameIndex > this.frames.size - 1) currentFrameIndex = 0 + } + + override fun getName(): String { + return name + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayoutContainer.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayoutContainer.kt new file mode 100644 index 000000000..1b4602ceb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/layout/SignLayoutContainer.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.layout + +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 12:50 + * @author Frederick Baier + */ +class SignLayoutContainer( + private val layouts: MutableList = CopyOnWriteArrayList() +) { + + fun addLayout(signLayout: SignLayout) { + this.layouts.add(signLayout) + } + + fun getLayoutByName(layoutType: LayoutType, name: String): SignLayout? { + return this.layouts.firstOrNull { it.layoutType == layoutType && it.getName() == name } + } + + fun getAllLayouts(): List { + return this.layouts + } + + fun getDefaultLayout(layoutType: LayoutType): SignLayout { + return getLayoutByName(layoutType, "default")!! + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/settings/CloudSignSettingsContainer.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/settings/CloudSignSettingsContainer.kt new file mode 100644 index 000000000..2cde32c56 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/settings/CloudSignSettingsContainer.kt @@ -0,0 +1,10 @@ +package eu.thesimplecloud.module.sign.lib.settings + +/** + * Created by MrManHD + * Class create at 21.06.2023 12:12 + */ + +class CloudSignSettingsContainer( + val updateSignInterval: Long +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSign.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSign.kt new file mode 100644 index 000000000..02c459703 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSign.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.sign + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.location.TemplateLocation +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup + +data class CloudSign( + val templateLocation: TemplateLocation, + val forGroup: String +) { + + fun getGroup(): ICloudServiceGroup { + return CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(forGroup)!! + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSignContainer.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSignContainer.kt new file mode 100644 index 000000000..fc6019691 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/lib/sign/CloudSignContainer.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.lib.sign + +import eu.thesimplecloud.api.location.TemplateLocation +import eu.thesimplecloud.api.template.ITemplate +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 14:46 + * @author Frederick Baier + */ +class CloudSignContainer { + + private val signs = CopyOnWriteArrayList() + + fun addSign(sign: CloudSign) { + this.signs.add(sign) + } + + fun removeSign(sign: CloudSign) { + this.signs.remove(sign) + } + + fun getAllSigns(): List { + return this.signs + } + + fun getSignsForTemplate(template: ITemplate): List { + return this.signs.filter { it.templateLocation.templateName == template.getName() } + } + + fun getCloudSignByLocation(forTemplate: ITemplate, templateLocation: TemplateLocation): CloudSign? { + return getSignsForTemplate(forTemplate).firstOrNull { it.templateLocation == templateLocation } + } + + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModule.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModule.kt new file mode 100644 index 000000000..94b448eca --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModule.kt @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.manager + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.sync.`object`.GlobalPropertyUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.sign.lib.SignModuleConfig +import eu.thesimplecloud.module.sign.manager.command.SignCommand + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 12:42 + * @author Frederick Baier + */ +class SignModule : ICloudModule { + + override fun onEnable() { + instance = this + + Launcher.instance.commandManager.registerCommand(this, SignCommand()) + val signModuleConfig = SignModuleConfigPersistence.load() + SignModuleConfigPersistence.save(signModuleConfig) + CloudAPI.instance.getGlobalPropertyHolder().setProperty("sign-config", signModuleConfig) + + CloudAPI.instance.getEventManager().registerListener(this, object : IListener { + + @CloudEventHandler + fun handleUpdate(event: GlobalPropertyUpdatedEvent) { + if (event.propertyName == "sign-config") { + val property = event.property as IProperty + SignModuleConfigPersistence.save(property.getValue()) + } + } + + }) + } + + override fun onDisable() { + } + + companion object { + lateinit var instance: SignModule + private set + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModuleConfigPersistence.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModuleConfigPersistence.kt new file mode 100644 index 000000000..1187e1ab1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/SignModuleConfigPersistence.kt @@ -0,0 +1,130 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.manager + +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.sign.lib.SignModuleConfig +import eu.thesimplecloud.module.sign.lib.group.GroupLayoutsContainer +import eu.thesimplecloud.module.sign.lib.layout.LayoutType +import eu.thesimplecloud.module.sign.lib.layout.SignFrame +import eu.thesimplecloud.module.sign.lib.layout.SignLayout +import eu.thesimplecloud.module.sign.lib.layout.SignLayoutContainer +import eu.thesimplecloud.module.sign.lib.settings.CloudSignSettingsContainer +import eu.thesimplecloud.module.sign.lib.sign.CloudSignContainer +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 17:11 + * @author Frederick Baier + */ +object SignModuleConfigPersistence { + + private val layoutsDir = File("modules/sign/layouts/") + + private val signsFile = File("modules/sign/signs.json") + private val signSettingsFile = File("modules/sign/signSettings.json") + private val groupLayoutsFile = File("modules/sign/groupLayouts.json") + + fun save(signModuleConfig: SignModuleConfig) { + JsonLib.fromObject(signModuleConfig.groupsLayoutContainer).saveAsFile(groupLayoutsFile) + JsonLib.fromObject(signModuleConfig.signContainer).saveAsFile(signsFile) + JsonLib.fromObject(signModuleConfig.cloudSignSettingsContainer).saveAsFile(signSettingsFile) + + val allLayouts = signModuleConfig.signLayoutContainer.getAllLayouts() + allLayouts.forEach { + val dir = getLayoutsDirectoryByLayoutType(it.layoutType) + JsonLib.fromObject(it).saveAsFile(File(dir, it.getName() + ".json")) + } + } + + private fun getLayoutsDirectoryByLayoutType(layoutType: LayoutType): File { + return File(layoutsDir, layoutType.name.lowercase() + "/") + } + + fun load(): SignModuleConfig { + if (!groupLayoutsFile.exists()) return createDefaultConfig() + if (!signsFile.exists()) return createDefaultConfig() + if (!signSettingsFile.exists()) return createDefaultConfig() + + val groupsLayoutContainer = + JsonLib.fromJsonFile(groupLayoutsFile)!!.getObject(GroupLayoutsContainer::class.java) + val cloudSignContainer = JsonLib.fromJsonFile(signsFile)!!.getObject(CloudSignContainer::class.java) + val cloudSignSettingsContainer = JsonLib.fromJsonFile(signSettingsFile)!!.getObject(CloudSignSettingsContainer::class.java) + + val allLayoutDirectories = LayoutType.values().map { getLayoutsDirectoryByLayoutType(it) } + val allFiles = allLayoutDirectories.map { it.listFiles().toList() }.flatten() + + val layouts = allFiles.map { JsonLib.fromJsonFile(it)!!.getObject(SignLayout::class.java) } + return SignModuleConfig( + SignLayoutContainer(layouts.toMutableList()), + cloudSignContainer, + groupsLayoutContainer, + cloudSignSettingsContainer + ) + } + + private fun createDefaultConfig(): SignModuleConfig { + val groupsLayoutContainer = GroupLayoutsContainer() + val cloudSignContainer = CloudSignContainer() + val layoutsContainer = SignLayoutContainer(getDefaultLayoutList().toMutableList()) + val cloudSignSettingsContainer = CloudSignSettingsContainer(20) + return SignModuleConfig(layoutsContainer, cloudSignContainer, groupsLayoutContainer, cloudSignSettingsContainer) + } + + private fun getDefaultLayoutList(): List { + return listOf( + SignLayout( + "default", LayoutType.SEARCHING, listOf( + SignFrame(arrayOf("§8--------", "Searching for", "server.", "§8--------")), + SignFrame(arrayOf("§8--------", "Searching for", "server..", "§8--------")), + SignFrame(arrayOf("§8--------", "Searching for", "server...", "§8--------")) + ) + ), + SignLayout( + "default", LayoutType.STARTING, listOf( + SignFrame(arrayOf("§6--------", "Server is", "starting.", "§6--------")), + SignFrame(arrayOf("§6--------", "Server is", "starting..", "§6--------")), + SignFrame(arrayOf("§6--------", "Server is", "starting...", "§6--------")) + ) + ), + SignLayout( + "default", LayoutType.MAINTENANCE, listOf( + SignFrame(arrayOf("§4--------", "%GROUP%", "§8Maintenance", "§4--------")) + ) + ), + SignLayout( + "default", LayoutType.ONLINE, listOf( + SignFrame(arrayOf("%DISPLAYNAME%", "§a%STATE%", "%MOTD%", "%ONLINE_PLAYERS%/%MAX_PLAYERS%")) + ) + ), + SignLayout( + "default", LayoutType.FULL, listOf( + SignFrame(arrayOf("%DISPLAYNAME%", "§6%STATE%", "%MOTD%", "%ONLINE_PLAYERS%/%MAX_PLAYERS%")) + ) + ) + ) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/command/SignCommand.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/command/SignCommand.kt new file mode 100644 index 000000000..9e8cffb7b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/manager/command/SignCommand.kt @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.manager.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandArgument +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.sign.lib.group.GroupLayouts +import eu.thesimplecloud.module.sign.lib.layout.LayoutType +import eu.thesimplecloud.module.sign.manager.SignModuleConfigPersistence + +/** + * Created by IntelliJ IDEA. + * Date: 11.10.2020 + * Time: 19:16 + * @author Frederick Baier + */ +@Command("sign", CommandType.CONSOLE_AND_INGAME, "cloud.module.sign") +class SignCommand : ICommandHandler { + + @CommandSubPath("reload", "Reloads the sign module") + fun handleReload(sender: ICommandSender) { + val config = SignModuleConfigPersistence.load() + config.update() + sender.sendProperty("manager.command.sign.reload") + } + + @CommandSubPath("layout ", "Sets the layout for a group") + fun handleEditLayout( + sender: ICommandSender, + @CommandArgument("group") groupName: String, + @CommandArgument("layoutType") layoutType: LayoutType, + @CommandArgument("layout") layoutName: String + ) { + val group = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(groupName) + if (group == null) { + sender.sendProperty("manager.command.sign.layout.group-not-found") + return + } + val config = SignModuleConfigPersistence.load() + val signLayout = config.signLayoutContainer.getLayoutByName(layoutType, layoutName) + if (signLayout == null) { + sender.sendProperty("manager.command.sign.layout.layout-not-found") + return + } + val groupsLayoutContainer = config.groupsLayoutContainer + if (groupsLayoutContainer.hasGroupLayout(group)) { + val groupLayouts = groupsLayoutContainer.getGroupLayoutsByGroupName(group.getName())!! + groupLayouts.setLayout(layoutType, layoutName) + } else { + val groupsLayout = GroupLayouts(group.getName(), mutableMapOf(layoutType to layoutName)) + groupsLayoutContainer.addGroupLayouts(groupsLayout) + } + config.update() + SignModuleConfigPersistence.save(config) + sender.sendProperty("manager.command.sign.layout.success", group.getName(), layoutName, layoutType.toString()) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitCloudSign.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitCloudSign.kt new file mode 100644 index 000000000..2b0c4ffaa --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitCloudSign.kt @@ -0,0 +1,135 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.module.serviceselection.api.AbstractServiceViewer +import eu.thesimplecloud.module.sign.lib.SignModuleConfig +import eu.thesimplecloud.module.sign.lib.layout.LayoutType +import eu.thesimplecloud.module.sign.lib.sign.CloudSign +import eu.thesimplecloud.module.sign.service.event.BukkitCloudSignUpdatedEvent +import eu.thesimplecloud.plugin.extension.toBukkitLocation +import org.bukkit.block.Sign + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 18:25 + * @author Frederick Baier + */ +class BukkitCloudSign( + val cloudSign: CloudSign +) : AbstractServiceViewer() { + + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(cloudSign.forGroup) + val location = cloudSign.templateLocation.toBukkitLocation() + + override fun updateView() { + if (serviceGroup == null) { + println("[SimpleCloud-Sign] WARNING: Cannot find group by name: ${cloudSign.forGroup}") + return + } + if (location == null) { + println("[SimpleCloud-Sign] WARNING: Cannot find world by name: ${cloudSign.templateLocation.worldName}") + return + } + if (!location.chunk.isLoaded) { + return + } + if (location.block.state !is Sign) { + return + } + val currentServer = this.service + val sign = location.block.state as Sign + clearSign(false) + + val config = SignModuleConfig.getConfig() + val layoutType = calculateLayoutType() + val signLayout = config.getSignLayoutForGroup(layoutType, this.serviceGroup.getName()) + + val currentFrame = signLayout.getCurrentFrame() + for (i in 0 until 4) { + sign.setLine(i, replacePlaceholders(currentFrame.lines[i], currentServer)) + } + sign.update() + + CloudAPI.instance.getEventManager().call(BukkitCloudSignUpdatedEvent(this)) + } + + private fun replacePlaceholders(lineToReplace: String, currentServer: ICloudService?): String { + var lineToReplace = lineToReplace + if (currentServer != null) + PLACEHOLDERS.forEach { lineToReplace = it.replacePlaceholder(currentServer, lineToReplace) } + GROUP_PLACEHOLDERS.forEach { lineToReplace = it.replacePlaceholder(this.serviceGroup!!, lineToReplace) } + return lineToReplace + } + + private fun calculateLayoutType(): LayoutType { + if (this.serviceGroup!!.isInMaintenance()) return LayoutType.MAINTENANCE + if (this.service == null) return LayoutType.SEARCHING + if (this.service!!.getState() == ServiceState.STARTING) return LayoutType.STARTING + if (this.service!!.getState() != ServiceState.VISIBLE) return LayoutType.SEARCHING + if (this.service!!.isFull()) return LayoutType.FULL + return LayoutType.ONLINE + } + + override fun removeView() { + this.clearSign(true) + } + + private fun clearSign(update: Boolean = true) { + val location = this.location!! + if (location.block.state is Sign) { + val sign = location.block.state as Sign + for (i in 0 until 4) { + sign.setLine(i, "") + } + if (update) sign.update() + } + } + + + companion object { + private val PLACEHOLDERS = listOf>( + Placeholder("SERVICE") { it.getName() }, + Placeholder("ONLINE_PLAYERS") { it.getOnlineCount().toString() }, + Placeholder("ONLINE_COUNT") { it.getOnlineCount().toString() }, + Placeholder("MOTD") { it.getMOTD() }, + Placeholder("HOST") { it.getHost() }, + Placeholder("PORT") { it.getPort().toString() }, + Placeholder("STATE") { it.getState().name }, + Placeholder("NUMBER") { it.getServiceNumber().toString() }, + Placeholder("WRAPPER") { it.getWrapperName()!! }, + Placeholder("MAX_PLAYERS") { it.getMaxPlayers().toString() }, + Placeholder("DISPLAYNAME") { it.getDisplayName() } + ) + + private val GROUP_PLACEHOLDERS = listOf>( + Placeholder("GROUP") { it.getName() }, + Placeholder("TEMPLATE") { it.getTemplateName() } + ) + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitPluginMain.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitPluginMain.kt new file mode 100644 index 000000000..2c3ca3cfe --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/BukkitPluginMain.kt @@ -0,0 +1,138 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.group.CloudServiceGroupUpdatedEvent +import eu.thesimplecloud.api.event.sync.`object`.GlobalPropertyUpdatedEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.module.serviceselection.api.ServiceViewGroupManager +import eu.thesimplecloud.module.sign.lib.SignModuleConfig +import eu.thesimplecloud.module.sign.lib.sign.CloudSign +import eu.thesimplecloud.module.sign.lib.sign.CloudSignContainer +import eu.thesimplecloud.module.sign.service.command.CloudSignsCommand +import eu.thesimplecloud.module.sign.service.event.BukkitCloudSignAddedEvent +import eu.thesimplecloud.module.sign.service.event.BukkitCloudSignRemovedEvent +import eu.thesimplecloud.module.sign.service.listener.InteractListener +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.plugin.java.JavaPlugin + +/** + * Created by IntelliJ IDEA. + * Date: 10.10.2020 + * Time: 18:00 + * @author Frederick Baier + */ +class BukkitPluginMain : JavaPlugin() { + + private lateinit var serviceViewManager: SignServiceViewManager + + override fun onEnable() { + SignAPI(this) + serviceViewManager = SignAPI.instance.serviceViewManager + val config = SignModuleConfig.getConfig() + CloudAPI.instance.getCloudServiceGroupManager().getServerOrLobbyGroups().forEach { + setupGroup(it, config) + } + + server.pluginManager.registerEvents(InteractListener(), this) + getCommand("cloudsigns")!!.setExecutor(CloudSignsCommand()) + + CloudAPI.instance.getEventManager() + .registerListener(CloudAPI.instance.getThisSidesCloudModule(), object : IListener { + + @CloudEventHandler + fun handleUpdate(event: GlobalPropertyUpdatedEvent) { + if (event.propertyName == "sign-config") { + val property = event.property as IProperty + updateSigns(property.getValue().signContainer) + } + } + + @CloudEventHandler + fun handleServiceGroupUpdate(event: CloudServiceGroupUpdatedEvent) { + if (event.serviceGroup is ICloudServerGroup) + setupGroup(event.serviceGroup, SignModuleConfig.getConfig()) + } + + }) + + } + + private fun updateSigns(signContainer: CloudSignContainer) { + + val signsForTemplate = signContainer.getSignsForTemplate(CloudPlugin.instance.thisService().getTemplate()) + + //remove removed BukkitCloudSigns + val serverGroups = CloudAPI.instance.getCloudServiceGroupManager().getServerOrLobbyGroups() + for (group in serverGroups) { + val groupView = serviceViewManager.getGroupView(group) + val signsForThisGroup = signsForTemplate.filter { it.forGroup == group.getName() } + val serviceViewers = groupView.getServiceViewers() + val bukkitSignsToUnregister = serviceViewers.filter { !signsForThisGroup.contains(it.cloudSign) } + bukkitSignsToUnregister.forEach { unregisterSign(it, groupView) } + } + + //add added BukkitCloudSigns + val registeredCloudSigns = serverGroups.map { serviceViewManager.getGroupView(it) } + .map { it.getServiceViewers() }.flatten() + + signsForTemplate.forEach { cloudSign -> + if (!isSignRegistered(cloudSign, registeredCloudSigns)) { + registerCloudSign(cloudSign) + } + } + } + + private fun unregisterSign(bukkitCloudSign: BukkitCloudSign, groupView: ServiceViewGroupManager) { + groupView.removeServiceViewer(bukkitCloudSign) + CloudAPI.instance.getEventManager().call(BukkitCloudSignRemovedEvent(bukkitCloudSign)) + } + + private fun registerCloudSign(cloudSign: CloudSign) { + val groupView = this.serviceViewManager.getGroupView(cloudSign.getGroup()) + val bukkitCloudSign = BukkitCloudSign(cloudSign) + groupView.addServiceViewers(bukkitCloudSign) + CloudAPI.instance.getEventManager().call(BukkitCloudSignAddedEvent(bukkitCloudSign)) + } + + private fun isSignRegistered(cloudSign: CloudSign, allRegisteredSigns: List): Boolean { + return allRegisteredSigns.map { it.cloudSign }.contains(cloudSign) + } + + private fun setupGroup(group: ICloudServiceGroup, config: SignModuleConfig) { + if (this.serviceViewManager.isGroupViewRegistered(group)) return + val serviceViewGroupManager = ServiceViewGroupManager(group) + val signsForTemplate = + config.signContainer.getSignsForTemplate(CloudPlugin.instance.thisService().getTemplate()) + val signsToRegister = signsForTemplate.filter { it.forGroup == group.getName() } + val bukkitSigns = signsToRegister.map { BukkitCloudSign(it) } + serviceViewGroupManager.addServiceViewers(*bukkitSigns.toTypedArray()) + this.serviceViewManager.addServiceViewGroupManager(serviceViewGroupManager) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/Placeholder.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/Placeholder.kt new file mode 100644 index 000000000..52775f1c7 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/Placeholder.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service + +class Placeholder( + private val name: String, + private val replaceValueFunction: (T) -> String +) { + + fun replacePlaceholder(type: T, message: String): String { + return message.replace("%$name%", replaceValueFunction(type)) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignAPI.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignAPI.kt new file mode 100644 index 000000000..85e96c3ce --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignAPI.kt @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service + +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import org.bukkit.Location +import org.bukkit.plugin.java.JavaPlugin + +/** + * Created by IntelliJ IDEA. + * Date: 11.10.2020 + * Time: 19:04 + * @author Frederick Baier + */ +class SignAPI(plugin: JavaPlugin) { + + val serviceViewManager: SignServiceViewManager = SignServiceViewManager(plugin) + + init { + instance = this + } + + fun getAllRegisteredSigns(): List { + return this.serviceViewManager.getAllGroupViewManagers().map { it.getServiceViewers() }.flatten() + } + + fun getAllRegisteredSignsByGroup(group: ICloudServiceGroup): List { + return this.serviceViewManager.getGroupView(group).getServiceViewers() + } + + fun getSignOnLocation(location: Location): BukkitCloudSign? { + return getAllRegisteredSigns().firstOrNull { it.location == location } + } + + fun isSignOnLocation(location: Location): Boolean { + return getSignOnLocation(location) != null + } + + + companion object { + lateinit var instance: SignAPI + private set + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignServiceViewManager.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignServiceViewManager.kt new file mode 100644 index 000000000..f44637305 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/SignServiceViewManager.kt @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service + +import eu.thesimplecloud.module.serviceselection.api.ServiceViewManager +import eu.thesimplecloud.module.sign.lib.SignModuleConfig +import org.bukkit.Location +import org.bukkit.plugin.java.JavaPlugin + +/** + * Created by IntelliJ IDEA. + * Date: 11.10.2020 + * Time: 18:53 + * @author Frederick Baier + */ +class SignServiceViewManager(plugin: JavaPlugin) : ServiceViewManager( + plugin, + SignModuleConfig.getConfig().cloudSignSettingsContainer.updateSignInterval +) { + + override fun performUpdate() { + super.performUpdate() + val config = SignModuleConfig.getConfig() + val signLayoutContainer = config.signLayoutContainer + signLayoutContainer.getAllLayouts().forEach { it.nextFrame() } + } + + fun getBukkitCloudSignByLocation(location: Location): BukkitCloudSign? { + val registeredSigns = this.getAllGroupViewManagers().map { it.getServiceViewers() }.flatten() + return registeredSigns.firstOrNull { it.location == location } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/command/CloudSignsCommand.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/command/CloudSignsCommand.kt new file mode 100644 index 000000000..8d39bb0ab --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/command/CloudSignsCommand.kt @@ -0,0 +1,129 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ServiceType +import eu.thesimplecloud.module.sign.lib.SignModuleConfig +import eu.thesimplecloud.module.sign.lib.sign.CloudSign +import eu.thesimplecloud.plugin.extension.toCloudLocation +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.block.Block +import org.bukkit.block.Sign +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.command.TabCompleter +import org.bukkit.entity.Player + +/** + * Created by IntelliJ IDEA. + * Date: 11.10.2020 + * Time: 12:05 + * @author Frederick Baier + */ +class CloudSignsCommand : CommandExecutor, TabCompleter { + + private val thisService = CloudPlugin.instance.thisService() + + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { + if (sender !is Player) return true + val block: Block = sender.getTargetBlock(null, 4) + if (block.state !is Sign) { + sender.sendMessage("§cYou must look at a sign.") + return true + } + if (args.isEmpty()) { + sender.sendMessage("§cUsage: /cloudsigns [group]") + return true + } + when (args[0].lowercase()) { + "add" -> { + if (args.size != 2) { + sender.sendMessage("§cUsage: /cloudsigns ") + return true + } + val groupName = args[1] + val serviceGroup = CloudAPI.instance.getCloudServiceGroupManager().getServiceGroupByName(groupName) + if (serviceGroup == null) { + sender.sendMessage("§cGroup not found.") + return true + } + if (serviceGroup.getServiceType() == ServiceType.PROXY) { + sender.sendMessage("§cCannot create a sign for proxy groups.") + return true + } + val signModuleConfig = SignModuleConfig.getConfig() + val templateLocation = block.location.toCloudLocation().toTemplateLocation() + val cloudSignByLocation = signModuleConfig.signContainer.getCloudSignByLocation( + this.thisService.getTemplate(), + templateLocation + ) + if (cloudSignByLocation != null) { + sender.sendMessage("§cThere is already a sign registered on this location.") + return true + } + signModuleConfig.signContainer.addSign(CloudSign(templateLocation, serviceGroup.getName())) + + signModuleConfig.update() + sender.sendMessage("§aSign added.") + } + "remove" -> { + val signModuleConfig = SignModuleConfig.getConfig() + val templateLocation = block.location.toCloudLocation().toTemplateLocation() + val cloudSign = signModuleConfig.signContainer.getCloudSignByLocation( + this.thisService.getTemplate(), + templateLocation + ) + if (cloudSign == null) { + sender.sendMessage("§cSign is not registered.") + return true + } + signModuleConfig.signContainer.removeSign(cloudSign) + signModuleConfig.update() + sender.sendMessage("§aSign removed.") + } + else -> { + sender.sendMessage("§cUsage: /cloudsigns [group]") + return true + } + } + return true + } + + override fun onTabComplete( + sender: CommandSender, + command: Command, + label: String, + args: Array + ): MutableList { + return when (args.size) { + 1 -> mutableListOf("add", "remove") + 2 -> CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects() + .filter { it.getServiceType() != ServiceType.PROXY } + .map { it.getName() } + .toMutableList() + else -> mutableListOf() + } + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignAddedEvent.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignAddedEvent.kt new file mode 100644 index 000000000..d7eecb01c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignAddedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service.event + +import eu.thesimplecloud.module.sign.service.BukkitCloudSign + +/** + * Created by IntelliJ IDEA. + * Date: 12.10.2020 + * Time: 11:27 + * @author Frederick Baier + */ +class BukkitCloudSignAddedEvent(bukkitCloudSign: BukkitCloudSign) : BukkitCloudSignEvent(bukkitCloudSign) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignEvent.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignEvent.kt new file mode 100644 index 000000000..335b7500a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignEvent.kt @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service.event + +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.module.sign.service.BukkitCloudSign + +/** + * Created by IntelliJ IDEA. + * Date: 12.10.2020 + * Time: 11:27 + * @author Frederick Baier + */ +open class BukkitCloudSignEvent( + val bukkitCloudSign: BukkitCloudSign +) : IEvent \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignRemovedEvent.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignRemovedEvent.kt new file mode 100644 index 000000000..cb12b3729 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignRemovedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service.event + +import eu.thesimplecloud.module.sign.service.BukkitCloudSign + +/** + * Created by IntelliJ IDEA. + * Date: 12.10.2020 + * Time: 11:27 + * @author Frederick Baier + */ +class BukkitCloudSignRemovedEvent(bukkitCloudSign: BukkitCloudSign) : BukkitCloudSignEvent(bukkitCloudSign) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignUpdatedEvent.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignUpdatedEvent.kt new file mode 100644 index 000000000..4c85308a8 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/event/BukkitCloudSignUpdatedEvent.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service.event + +import eu.thesimplecloud.module.sign.service.BukkitCloudSign + +/** + * Created by IntelliJ IDEA. + * Date: 12.10.2020 + * Time: 11:27 + * @author Frederick Baier + */ +class BukkitCloudSignUpdatedEvent(bukkitCloudSign: BukkitCloudSign) : BukkitCloudSignEvent(bukkitCloudSign) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/listener/InteractListener.kt b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/listener/InteractListener.kt new file mode 100644 index 000000000..206f24336 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/kotlin/eu/thesimplecloud/module/sign/service/listener/InteractListener.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.sign.service.listener + +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.module.sign.service.SignAPI +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import org.bukkit.block.Sign +import org.bukkit.event.Event +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.Action +import org.bukkit.event.player.PlayerInteractEvent + +class InteractListener : Listener { + + @EventHandler + fun on(event: PlayerInteractEvent) { + if (event.useInteractedBlock() == Event.Result.DENY) return + if (event.action != Action.RIGHT_CLICK_BLOCK) + return + val clickedBlock = event.clickedBlock ?: return + val state = clickedBlock.state + if (state is Sign) { + val bukkitCloudSign = SignAPI.instance.serviceViewManager.getBukkitCloudSignByLocation(state.location) + ?: return + if (bukkitCloudSign.serviceGroup?.isInMaintenance() == true) return + val currentServer = bukkitCloudSign.service ?: return + if (currentServer.getState() != ServiceState.VISIBLE) return + event.player.getCloudPlayer().connect(currentServer) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/de.json b/simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/de.json new file mode 100644 index 000000000..8ff11c94e --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/de.json @@ -0,0 +1,6 @@ +{ + "manager.command.sign.group-not-found": "§cGruppe wurde nicht gefunden", + "manager.command.sign.layout-not-found": "§cLayout wurde nicht gefunden", + "manager.command.sign.layout-set": "§7Die Gruppe §e%GROUP% §7benutzt nun das Layout §e%LAYOUT%", + "manager.command.sign.reload": "§aNeuladen der Konfiguration erfolgreich abgeschlossen" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/en.json b/simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/en.json new file mode 100644 index 000000000..5621a430b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/resources/languages/en.json @@ -0,0 +1,6 @@ +{ + "manager.command.sign.group-not-found": "§cGroup not found", + "manager.command.sign.layout-not-found": "§cLayout not found", + "manager.command.sign.layout-set": "§7Group §e%GROUP% §7is now using the layout §e%LAYOUT%§7", + "manager.command.sign.reload": "§aConfig reloaded" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-sign/src/main/resources/module.json new file mode 100644 index 000000000..2b91f73a2 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Sign", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.sign.manager.SignModule", + "moduleCopyType": "LOBBY", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/resources/plugin.yml b/simplecloud-modules/simplecloud-module-sign/src/main/resources/plugin.yml new file mode 100644 index 000000000..a203afac6 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/resources/plugin.yml @@ -0,0 +1,13 @@ +name: SimpleCloud-Sign +version: 1.0 +author: Wetterbericht + +main: eu.thesimplecloud.module.sign.service.BukkitPluginMain + +depend: [ SimpleCloud-Plugin ] + +api-version: 1.13 + +commands: + cloudsigns: + permission: cloud.command.signs diff --git a/simplecloud-modules/simplecloud-module-sign/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-sign/src/main/resources/updater.json new file mode 100644 index 000000000..13924ce5a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-sign/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-sign", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/build.gradle b/simplecloud-modules/simplecloud-module-statistics/build.gradle new file mode 100644 index 000000000..1a8c9de6c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/build.gradle @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Statistics.jar") +} + +dependencies { + compileOnly "org.jetbrains.kotlin:kotlin-stdlib" + compileOnly group: 'org.litote.kmongo', name: 'kmongo', version: dependencyKMongoVersion + api group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.7.4' + + + compileOnly(project(":simplecloud-base")) { + transitive = false + } + compileOnly(project(":simplecloud-api")) + compileOnly(project(":simplecloud-modules:simplecloud-module-rest")) + compileOnly(project(":simplecloud-plugin")) { + transitive = false + } + compileOnly(project(":simplecloud-launcher")) { + transitive = false + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/StatisticsModule.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/StatisticsModule.kt new file mode 100644 index 000000000..bca9271f1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/StatisticsModule.kt @@ -0,0 +1,98 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.base.manager.database.MongoOfflineCloudPlayerHandler +import eu.thesimplecloud.base.manager.database.SQLOfflineCloudPlayerHandler +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.module.rest.javalin.RestServer +import eu.thesimplecloud.module.statistics.rest.timed.TimedValueController +import eu.thesimplecloud.module.statistics.timed.TimedValueCollectorManager +import eu.thesimplecloud.module.statistics.timed.collector.CPUUsageTimedCollector +import eu.thesimplecloud.module.statistics.timed.collector.MemoryTimedCollector +import eu.thesimplecloud.module.statistics.timed.collector.PlayerCountTimedCollector +import eu.thesimplecloud.module.statistics.timed.listener.CloudServiceStartListener +import eu.thesimplecloud.module.statistics.timed.listener.PlayerConnectListener +import eu.thesimplecloud.module.statistics.timed.store.ITimedValueStore +import eu.thesimplecloud.module.statistics.timed.store.MongoTimedValueStore +import eu.thesimplecloud.module.statistics.timed.store.SQLTimedValueStore +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Created by IntelliJ IDEA. + * Date: 26.12.2020 + * Time: 10:38 + * @author Frederick Baier + */ +class StatisticsModule : ICloudModule { + + private val timedValueCollectorManager = TimedValueCollectorManager() + + private val valueStores = CopyOnWriteArrayList>() + + override fun onEnable() { + instance = this + CloudAPI.instance.getEventManager().registerListener(this, CloudServiceStartListener()) + CloudAPI.instance.getEventManager().registerListener(this, PlayerConnectListener()) + + CloudAPI.instance.getWrapperManager().getAllCachedObjects().forEach { + timedValueCollectorManager.registerValueCollector(CPUUsageTimedCollector(it), Float::class.java) + timedValueCollectorManager.registerValueCollector(MemoryTimedCollector(it), Int::class.java) + } + timedValueCollectorManager.registerValueCollector(PlayerCountTimedCollector(), Int::class.java) + timedValueCollectorManager.start() + + RestServer.instance.controllerHandler.registerController(TimedValueController()) + } + + override fun onDisable() { + } + + companion object { + lateinit var instance: StatisticsModule + private set + } + + fun getValueStoreByName(name: String): ITimedValueStore<*>? { + return this.valueStores.firstOrNull { it.getCollectionName() == name } + } + + fun createTimedValueStore(collectionName: String, clazz: Class): ITimedValueStore { + val offlineCloudPlayerHandler = Manager.instance.offlineCloudPlayerHandler + if (offlineCloudPlayerHandler is SQLOfflineCloudPlayerHandler) { + val sqlTimedValueStore = SQLTimedValueStore(clazz, collectionName) + valueStores.add(sqlTimedValueStore) + return sqlTimedValueStore + } else if (offlineCloudPlayerHandler is MongoOfflineCloudPlayerHandler) { + val mongoTimedValueStore = + MongoTimedValueStore(clazz, collectionName, offlineCloudPlayerHandler.database) + valueStores.add(mongoTimedValueStore) + return mongoTimedValueStore + } + + throw IllegalStateException("OfflineCloudPlayerManager was not SQL or MongoDB") + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/rest/timed/TimedValueController.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/rest/timed/TimedValueController.kt new file mode 100644 index 000000000..dd009a347 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/rest/timed/TimedValueController.kt @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.rest.timed + +import eu.thesimplecloud.module.rest.annotation.* +import eu.thesimplecloud.module.rest.controller.IController +import eu.thesimplecloud.module.statistics.StatisticsModule +import eu.thesimplecloud.module.statistics.timed.TimedValue + +/** + * Created by IntelliJ IDEA. + * Date: 26.12.2020 + * Time: 10:56 + * @author Frederick Baier + */ +@RestController("statistics/timedvalue/") +class TimedValueController : IController { + + /** + * The parameters [from] and [to] are from negative infinity to 0. 0 is now. + */ + @RequestMapping(RequestType.GET, "data/:name", "web.statistics.get.data") + fun handleGet( + @RequestPathParam("name") name: String, + @RequestParam("from", true) from: Long, + @RequestParam("to", true) to: Long, + @RequestParam("resolution", false) resolution: Long? + ): List> { + + + val valueStore = StatisticsModule.instance.getValueStoreByName(name) + ?: throwNoSuchElement() + + val recalculatedFrom = from + System.currentTimeMillis() + val recalculatedTo = to + System.currentTimeMillis() + + return if (resolution == null) { + valueStore.get(recalculatedFrom, recalculatedTo) + } else { + valueStore.get(recalculatedFrom, recalculatedTo, resolution) + } + } + + @RequestMapping(RequestType.GET, "count/:name", "web.statistics.get.count") + fun handleGetCount( + @RequestPathParam("name") name: String + ): Int { + + val valueStore = StatisticsModule.instance.getValueStoreByName(name) + ?: throwNoSuchElement() + + return valueStore.count() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/Timed.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/Timed.kt new file mode 100644 index 000000000..9807d0d46 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/Timed.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:02 + * @author Frederick Baier + */ +/** + * Represents an object associated with a specific timestamp + */ +interface Timed { + + /** + * Returns the timestamp of this [Timed] + */ + fun getTimeStamp(): Long + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValue.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValue.kt new file mode 100644 index 000000000..122722241 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValue.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:05 + * @author Frederick Baier + */ +data class TimedValue( + val value: T, + private val timeStamp: Long = System.currentTimeMillis() +) : Timed { + + override fun getTimeStamp(): Long { + return this.timeStamp + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValueCollectorManager.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValueCollectorManager.kt new file mode 100644 index 000000000..dc5deae92 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/TimedValueCollectorManager.kt @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed + +import com.google.common.collect.Maps +import eu.thesimplecloud.api.utils.time.Timestamp +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.statistics.StatisticsModule +import eu.thesimplecloud.module.statistics.timed.collector.ITimedValueCollector +import eu.thesimplecloud.module.statistics.timed.store.ITimedValueStore +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:24 + * @author Frederick Baier + */ +class TimedValueCollectorManager { + + private val storeAndCollectorToLastExecutedTime = + Maps.newConcurrentMap, Timestamp>() + + fun start() { + Launcher.instance.scheduler.scheduleAtFixedRate({ + val collectors = + storeAndCollectorToLastExecutedTime.filter { it.value.hasTimePassed(it.key.collector.collectInterval()) }.keys + collectors.forEach { + it.storeNextValue() + this.storeAndCollectorToLastExecutedTime[it] = Timestamp() + } + }, 0, 1, TimeUnit.SECONDS) + } + + fun registerValueCollector(collector: ITimedValueCollector, clazz: Class) { + val store = StatisticsModule.instance.createTimedValueStore(collector.collectionName(), clazz) + val storeAndValueCollector = StoreAndValueCollector(collector, store) + this.storeAndCollectorToLastExecutedTime[storeAndValueCollector] = Timestamp(0) + } + + + fun getStoreByCollectionNameUnsafe(name: String): ITimedValueStore? { + return this.storeAndCollectorToLastExecutedTime.keys.firstOrNull { it.collector.collectionName() == name }?.store + } + + class StoreAndValueCollector( + val collector: ITimedValueCollector, + val store: ITimedValueStore + ) { + + fun storeNextValue() { + store.store(collector.collectValue()) + } + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/CPUUsageTimedCollector.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/CPUUsageTimedCollector.kt new file mode 100644 index 000000000..a41659c11 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/CPUUsageTimedCollector.kt @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.collector + +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.module.statistics.timed.TimedValue +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:19 + * @author Frederick Baier + */ +class CPUUsageTimedCollector(private val wrapperInfo: IWrapperInfo) : ITimedValueCollector { + + + override fun collectValue(): TimedValue { + return TimedValue(wrapperInfo.getCpuUsage()) + } + + override fun collectInterval(): Long { + return TimeUnit.MINUTES.toMillis(1) + } + + override fun collectionName(): String { + return "cloud_stats_cpu_usage_${wrapperInfo.getName()}" + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/ITimedValueCollector.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/ITimedValueCollector.kt new file mode 100644 index 000000000..08c6d7e3a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/ITimedValueCollector.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.collector + +import eu.thesimplecloud.module.statistics.timed.TimedValue + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:08 + * @author Frederick Baier + */ +interface ITimedValueCollector { + + fun collectValue(): TimedValue + + fun collectInterval(): Long + + fun collectionName(): String + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/MemoryTimedCollector.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/MemoryTimedCollector.kt new file mode 100644 index 000000000..c3d19f26d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/MemoryTimedCollector.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.collector + +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.module.statistics.timed.TimedValue +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:15 + * @author Frederick Baier + */ +class MemoryTimedCollector(private val wrapperInfo: IWrapperInfo) : ITimedValueCollector { + + override fun collectValue(): TimedValue { + val usedMemory = wrapperInfo.getUsedMemory() + return TimedValue(usedMemory) + } + + override fun collectInterval(): Long { + return TimeUnit.MINUTES.toMillis(1) + } + + override fun collectionName(): String { + return "cloud_stats_memory_usage_${wrapperInfo.getName()}" + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/PlayerCountTimedCollector.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/PlayerCountTimedCollector.kt new file mode 100644 index 000000000..a70668322 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/collector/PlayerCountTimedCollector.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.collector + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.module.statistics.timed.TimedValue +import java.util.concurrent.TimeUnit + +/** + * Created by IntelliJ IDEA. + * Date: 26.12.2020 + * Time: 23:39 + * @author Frederick Baier + */ +class PlayerCountTimedCollector : ITimedValueCollector { + + override fun collectValue(): TimedValue { + val onlineCount = CloudAPI.instance.getCloudPlayerManager().getNetworkOnlinePlayerCount().getBlocking() + return TimedValue(onlineCount) + } + + override fun collectInterval(): Long { + return TimeUnit.MINUTES.toMillis(1) + } + + override fun collectionName(): String { + return "cloud_stats_player_count" + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/CloudServiceStartListener.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/CloudServiceStartListener.kt new file mode 100644 index 000000000..7c834810d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/CloudServiceStartListener.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.listener + +import eu.thesimplecloud.api.event.service.CloudServiceStartingEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.module.statistics.StatisticsModule +import eu.thesimplecloud.module.statistics.timed.TimedValue + +/** + * Created by IntelliJ IDEA. + * Date: 26.12.2020 + * Time: 12:19 + * @author Frederick Baier + */ +class CloudServiceStartListener : IListener { + + private val store = + StatisticsModule.instance.createTimedValueStore("cloud_stats_service_starts", String::class.java) + + @CloudEventHandler + fun handleStarting(event: CloudServiceStartingEvent) { + val cloudService = event.cloudService + store.store(TimedValue(cloudService.getName())) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/PlayerConnectListener.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/PlayerConnectListener.kt new file mode 100644 index 000000000..e1d898523 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/listener/PlayerConnectListener.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.listener + +import eu.thesimplecloud.api.event.player.CloudPlayerLoginEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.module.statistics.StatisticsModule +import eu.thesimplecloud.module.statistics.timed.TimedValue +import java.util.* + +/** + * Created by IntelliJ IDEA. + * Date: 26.12.2020 + * Time: 12:28 + * @author Frederick Baier + */ +class PlayerConnectListener : IListener { + + private val store = + StatisticsModule.instance.createTimedValueStore("cloud_stats_player_connects", UUID::class.java) + + @CloudEventHandler + fun handle(event: CloudPlayerLoginEvent) { + store.store(TimedValue(event.playerUniqueId)) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/ITimedValueStore.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/ITimedValueStore.kt new file mode 100644 index 000000000..ce2e995dc --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/ITimedValueStore.kt @@ -0,0 +1,101 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.store + +import eu.thesimplecloud.module.statistics.timed.TimedValue + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:34 + * @author Frederick Baier + */ +interface ITimedValueStore { + + fun getCollectionName(): String + + fun store(timedValue: TimedValue) + + fun getAll(): List> + + fun count(): Int + + fun get(fromTimeStamp: Long, toTimeStamp: Long): List> + + fun get(fromTimeStamp: Long, toTimeStamp: Long, resolution: Long): List> { + val list = get(fromTimeStamp, toTimeStamp) + if (list.isEmpty()) return list + + val firstElement = list.first() + if (firstElement.value is Number) { + return getAveraged(list as List>, resolution) as List> + } + + var lastTimeStamp = firstElement.getTimeStamp() + val returnList = mutableListOf(firstElement) + + list.drop(1).forEach { + if (lastTimeStamp + resolution <= it.getTimeStamp()) { + lastTimeStamp = it.getTimeStamp() + returnList.add(it) + } + } + return returnList + } + + fun getAveraged( + valueList: List>, + resolution: Long + ): List> { + if (valueList.isEmpty()) return valueList + var lastTimeStamp = valueList.first().getTimeStamp() + val indicesList = mutableListOf(0) + + valueList.drop(1).forEachIndexed { index, value -> + if (lastTimeStamp + resolution <= value.getTimeStamp()) { + lastTimeStamp = value.getTimeStamp() + indicesList.add(index + 1) + } + } + + + val listOfValueLists: List>> = indicesList.mapIndexed { thisIndex, valueIndex -> + val fromIndex = valueIndex + val toIndex = if (thisIndex == indicesList.lastIndex) valueList.lastIndex else indicesList[thisIndex + 1] + valueList.subList(fromIndex, toIndex) + } + + val returnList = listOfValueLists.map { list -> + if (list.isEmpty()) return@map null + val average = calculateAverage(list.map { it.value }) + TimedValue(average, list.first().getTimeStamp()) + } + + return returnList.filterNotNull() as List> + } + + private fun calculateAverage(list: List): Double { + return list.sumByDouble { it.toDouble() } / list.size + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/MongoTimedValueStore.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/MongoTimedValueStore.kt new file mode 100644 index 000000000..bbaec42ad --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/MongoTimedValueStore.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.store + +import com.mongodb.BasicDBObject +import com.mongodb.client.MongoDatabase +import com.mongodb.client.model.IndexOptions +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.statistics.timed.TimedValue +import org.bson.Document +import org.litote.kmongo.ensureIndex +import org.litote.kmongo.find +import org.litote.kmongo.getCollection + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 23:23 + * @author Frederick Baier + */ +class MongoTimedValueStore( + private val classOfT: Class, + private val collectionName: String, + database: MongoDatabase +) : ITimedValueStore { + + private val collection = database.getCollection(collectionName) + + init { + collection.ensureIndex(BasicDBObject("timeStamp", 1), IndexOptions().unique(false)) + } + + override fun store(timedValue: TimedValue) { + val document = JsonLib.fromObject(timedValue).getObject(Document::class.java) + collection.insertOne(document) + } + + override fun getAll(): List> { + return collection.find().toList().map { constructTimedValueFromDocument(it) } + } + + override fun get(fromTimeStamp: Long, toTimeStamp: Long): List> { + return collection.find("{ timeStamp : { \$gt : $fromTimeStamp, \$lt : $toTimeStamp}}").toList() + .map { constructTimedValueFromDocument(it) } + } + + override fun getCollectionName(): String { + return this.collectionName + } + + private fun constructTimedValueFromDocument(document: Document): TimedValue { + val jsonLib = JsonLib.fromObject(document) + val value = jsonLib.getObject("value", classOfT)!! + val timeStamp = jsonLib.getLong("timeStamp")!! + return TimedValue(value, timeStamp) + } + + override fun count(): Int { + return this.collection.countDocuments().toInt() + } +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/SQLTimedValueStore.kt b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/SQLTimedValueStore.kt new file mode 100644 index 000000000..e7de9d95f --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/kotlin/eu/thesimplecloud/module/statistics/timed/store/SQLTimedValueStore.kt @@ -0,0 +1,119 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.module.statistics.timed.store + +import eu.thesimplecloud.base.manager.database.SQLOfflineCloudPlayerHandler +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.module.statistics.timed.TimedValue +import java.sql.Connection +import java.sql.DatabaseMetaData +import java.sql.ResultSet + +/** + * Created by IntelliJ IDEA. + * Date: 25.12.2020 + * Time: 12:43 + * @author Frederick Baier + */ +class SQLTimedValueStore( + private val classOfT: Class, + private val collectionName: String +) : ITimedValueStore { + + init { + createDatabaseAndIndicesIfNotExist() + } + + private fun getConnection(): Connection { + val playerHandler = Manager.instance.offlineCloudPlayerHandler as SQLOfflineCloudPlayerHandler + return playerHandler.connection!! + } + + private fun createDatabaseAndIndicesIfNotExist() { + if (!doesTableExist()) { + val statement = + getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS `$collectionName` (`value` varchar(36), `timestamp` BIGINT(20))") + statement.executeUpdate() + createIndex("timestamp") + } + } + + override fun store(timedValue: TimedValue) { + val statement = + getConnection().prepareStatement("INSERT INTO `$collectionName` (`value`, `timestamp`) VALUES (?, ?)") + statement.setString(1, timedValue.value.toString()) + statement.setLong(2, timedValue.getTimeStamp()) + statement.executeUpdate() + } + + + private fun createIndex(columnName: String) { + val statement = getConnection().prepareStatement("ALTER TABLE $collectionName ADD INDEX ($columnName)") + statement.executeUpdate() + } + + private fun doesTableExist(): Boolean { + val meta: DatabaseMetaData = getConnection().metaData + val res = meta.getTables(null, null, this.collectionName, arrayOf("TABLE")) + return res.next() + } + + override fun getAll(): List> { + val statement = getConnection().prepareStatement("SELECT * FROM `$collectionName`") + val resultSet = statement.executeQuery() + return getAllTimedValuesFromResultSet(resultSet) + } + + override fun get(fromTimeStamp: Long, toTimeStamp: Long): List> { + val statement = + getConnection().prepareStatement("SELECT * FROM `$collectionName` WHERE timestamp BETWEEN $fromTimeStamp and $toTimeStamp ORDER BY timestamp ASC") + val resultSet = statement.executeQuery() + return getAllTimedValuesFromResultSet(resultSet) + } + + private fun getAllTimedValuesFromResultSet(resultSet: ResultSet): List> { + val returnList = ArrayList>() + while (resultSet.next()) { + val value = resultSet.getString(1) + val timeStamp = resultSet.getLong(2) + returnList.add(TimedValue(JsonLib.fromJsonString(value).getObject(classOfT), timeStamp)) + } + return returnList + } + + override fun getCollectionName(): String { + return this.collectionName + } + + override fun count(): Int { + val statement = getConnection().prepareStatement("SELECT COUNT(*) FROM `$collectionName`") + val resultSet = statement.executeQuery() + return if (!resultSet.next()) { + 0 + } else { + resultSet.getInt(1) + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-statistics/src/main/resources/module.json new file mode 100644 index 000000000..e14e13834 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/resources/module.json @@ -0,0 +1,12 @@ +{ + "name": "SimpleCloud-Statistics", + "author": "Wetterbericht", + "mainClass": "eu.thesimplecloud.module.statistics.StatisticsModule", + "moduleCopyType": "NONE", + "repositories": [], + "dependencies": [], + "depend": [ + "SimpleCloud-Rest" + ], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-statistics/src/main/resources/updater.json b/simplecloud-modules/simplecloud-module-statistics/src/main/resources/updater.json new file mode 100644 index 000000000..5250794b1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-statistics/src/main/resources/updater.json @@ -0,0 +1,6 @@ +{ + "groupId": "eu.thesimplecloud.simplecloud", + "artifactId": "simplecloud-module-statistics", + "repository": "CLOUD", + "updateMethod": "CLOUD" +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/build.gradle b/simplecloud-modules/simplecloud-module-support/build.gradle new file mode 100644 index 000000000..79f39fbdd --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/build.gradle @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +shadowJar { + archiveFileName.set("SimpleCloud-Support.jar") +} + +dependencies { + compileOnly project(":simplecloud-base") + compileOnly project(":simplecloud-api") + compileOnly project(":simplecloud-plugin") + compileOnly project(":simplecloud-launcher") +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFile.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFile.kt new file mode 100644 index 000000000..528265527 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFile.kt @@ -0,0 +1,63 @@ +package eu.thesimplecloud.module.support.lib + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.base.manager.startup.Manager +import eu.thesimplecloud.module.support.lib.creator.* +import java.io.File + +/** + * Created by MrManHD + * Class create at 25.06.2023 20:58 + */ + +class DumpFile( + private val time: String +) { + + val fileString = getDumpFileTemplate() + .replace("%MODULES%", getModulesString()) + .replace("%JVM_ARGUMENTS%", getJvmArgumentsString()) + .replace("%WRAPPERS%", WrapperFileCreator().create()) + .replace("%SERVICES%", ServiceFileCreator().create()) + .replace("%TEMPLATES%", getTemplatesString()) + .replace("%GROUPS%", GroupFileCreator().create()) + .replace("%STATIC_JARS%", ServiceVersionFileCreator().create()) + .replace("%LOG%", getCloudLogs()) + + private fun getDumpFileTemplate(): String { + return DumpFile::class.java.getResource("/temp/dump-file.txt")!!.readText() + .replace("%TIME%", this.time) + .replace("%OS_NAME%", System.getProperty("os.name")) + .replace("%JAVA_VERSION%", System.getProperty("java.version")) + .replace("%CLOUD_VERSION%", System.getProperty("simplecloud.version")) + } + + private fun getModulesString(): String { + val stringBuilder = StringBuilder() + Manager.instance.cloudModuleHandler.getLoadedModules().forEach { + stringBuilder.append("\n ${it.file.name}") + } + return stringBuilder.toString() + } + + private fun getTemplatesString(): String { + val stringBuilder = StringBuilder() + CloudAPI.instance.getTemplateManager().getAllCachedObjects().forEach { + stringBuilder.append("\n ${it.getName()}") + } + return stringBuilder.toString() + } + + private fun getJvmArgumentsString(): String { + val stringBuilder = StringBuilder() + Manager.instance.jvmArgumentsConfig.jvmArguments.forEach { + stringBuilder.append("\n ${it.groups.joinToString(", ")}: ${it.arguments.joinToString(" ")}") + } + return stringBuilder.toString() + } + + private fun getCloudLogs(): String { + return File("logs/simplecloud-log.0").readText() + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFileCreator.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFileCreator.kt new file mode 100644 index 000000000..9f3786fd0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/DumpFileCreator.kt @@ -0,0 +1,20 @@ +package eu.thesimplecloud.module.support.lib + +import java.text.SimpleDateFormat +import java.util.* + +/** + * Created by MrManHD + * Class create at 25.06.2023 20:57 + */ + +class DumpFileCreator( + private val timestamp: Long = System.currentTimeMillis() +) { + + fun create(): String { + val simpleDateFormat = SimpleDateFormat("dd.MM.yyyy HH:mm:ss") + return DumpFile(simpleDateFormat.format(Date(this.timestamp))).fileString + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfig.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfig.kt new file mode 100644 index 000000000..ecbd68d7c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfig.kt @@ -0,0 +1,18 @@ +package eu.thesimplecloud.module.support.lib.config + +/** + * Created by MrManHD + * Class create at 07.07.2023 19:55 + */ + +class UploadConfig( + val uploadUrl: String +) { + + object Default { + fun get(): UploadConfig { + return UploadConfig("https://haste.simplecloud.app") + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfigLoader.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfigLoader.kt new file mode 100644 index 000000000..5b01b85c0 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/config/UploadConfigLoader.kt @@ -0,0 +1,16 @@ +package eu.thesimplecloud.module.support.lib.config + +import eu.thesimplecloud.api.config.AbstractJsonLibConfigLoader +import java.io.File + +/** + * Created by MrManHD + * Class create at 07.07.2023 19:57 + */ + +class UploadConfigLoader : AbstractJsonLibConfigLoader( + UploadConfig::class.java, + File("modules/support/settings.json"), + { UploadConfig.Default.get() }, + true +) \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/GroupFileCreator.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/GroupFileCreator.kt new file mode 100644 index 000000000..56f31857c --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/GroupFileCreator.kt @@ -0,0 +1,40 @@ +package eu.thesimplecloud.module.support.lib.creator + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.module.support.lib.DumpFile + +/** + * Created by MrManHD + * Class create at 30.06.2023 21:03 + */ + +class GroupFileCreator { + + fun create(): String { + val stringBuilder = StringBuilder() + CloudAPI.instance.getCloudServiceGroupManager().getAllCachedObjects().forEach { + stringBuilder.append("\n${getGroupFile(it)}") + } + return stringBuilder.toString() + } + + private fun getGroupFile(group: ICloudServiceGroup): String { + return DumpFile::class.java.getResource("/temp/group.txt")!!.readText() + .replace("%GROUP_NAME%", group.getName()) + .replace("%SERVICE_GROUP_TYPE%", group.getServiceType().toString()) + .replace("%TEMPLATE_NAME%", group.getTemplateName()) + .replace("%MAX_MEMORY%", group.getMaxMemory().toString()) + .replace("%MIN_SERVICE%", group.getMinimumOnlineServiceCount().toString()) + .replace("%MAX_SERVICE%", group.getMaximumOnlineServiceCount().toString()) + .replace("%MAINTENANCE%", group.isInMaintenance().toString()) + .replace("%STATIC%", group.isStatic().toString()) + .replace("%START_PERCENT%", group.getPercentToStartNewService().toString()) + .replace("%WRAPPER_NAME%", group.getWrapperName().toString()) + .replace("%START_PRIORITY%", group.getStartPriority().toString()) + .replace("%JAVA_NAME%", group.getJavaCommandName()) + .replace("%PERMISSION%", group.getPermission().toString()) + .replace("%SERVICE_VERSION%", group.getServiceVersion().name) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceFileCreator.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceFileCreator.kt new file mode 100644 index 000000000..2fa5a6cfb --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceFileCreator.kt @@ -0,0 +1,36 @@ +package eu.thesimplecloud.module.support.lib.creator + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.module.support.lib.DumpFile + +/** + * Created by MrManHD + * Class create at 02.07.2023 14:52 + */ + +class ServiceFileCreator { + + fun create(): String { + val stringBuilder = StringBuilder() + CloudAPI.instance.getCloudServiceManager().getAllCachedObjects().forEach { + stringBuilder.append("\n${getServiceFile(it)}") + } + return stringBuilder.toString() + } + + private fun getServiceFile(service: ICloudService): String { + return DumpFile::class.java.getResource("/temp/service.txt")!!.readText() + .replace("%SERVICE_NAME%", service.getName()) + .replace("%GROUP_NAME%", service.getGroupName()) + .replace("%DISPLAY_NAME%", service.getDisplayName()) + .replace("%PORT%", service.getPort().toString()) + .replace("%STATE%", service.getState().toString()) + .replace("%ONLINE_COUNT%", service.getOnlineCount().toString()) + .replace("%MEMORY%", service.getUsedMemory().toString()) + .replace("%TEMPLATE_NAME%", service.getTemplateName()) + .replace("%WRAPPER_NAME%", service.getWrapperName().toString()) + .replace("%SERVICE_VERSION%", service.getServiceVersion().name) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceVersionFileCreator.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceVersionFileCreator.kt new file mode 100644 index 000000000..dd417fb07 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/ServiceVersionFileCreator.kt @@ -0,0 +1,30 @@ +package eu.thesimplecloud.module.support.lib.creator + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.service.version.ServiceVersion +import eu.thesimplecloud.module.support.lib.DumpFile + +/** + * Created by MrManHD + * Class create at 02.07.2023 14:52 + */ + +class ServiceVersionFileCreator { + + fun create(): String { + val stringBuilder = StringBuilder() + CloudAPI.instance.getServiceVersionHandler().getAllVersions().forEach { + stringBuilder.append("\n${getServiceFile(it)}") + } + return stringBuilder.toString() + } + + private fun getServiceFile(serviceVersion: ServiceVersion): String { + return DumpFile::class.java.getResource("/temp/static-jars.txt")!!.readText() + .replace("%JAR_NAME%", serviceVersion.name) + .replace("%URL_NAME%", serviceVersion.downloadURL) + .replace("%SERVICE_TYPE%", serviceVersion.serviceAPIType.toString()) + .replace("%PAPER_CLIP%", serviceVersion.isPaperClip.toString()) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/WrapperFileCreator.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/WrapperFileCreator.kt new file mode 100644 index 000000000..191cd3832 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/lib/creator/WrapperFileCreator.kt @@ -0,0 +1,30 @@ +package eu.thesimplecloud.module.support.lib.creator + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.wrapper.IWrapperInfo +import eu.thesimplecloud.module.support.lib.DumpFile + +/** + * Created by MrManHD + * Class create at 30.06.2023 21:02 + */ + +class WrapperFileCreator { + + fun create(): String { + val stringBuilder = StringBuilder() + CloudAPI.instance.getWrapperManager().getAllCachedObjects().forEach { + stringBuilder.append("\n${getWrapperFile(it)}") + } + return stringBuilder.toString() + } + + private fun getWrapperFile(wrapper: IWrapperInfo): String { + return DumpFile::class.java.getResource("/temp/wrapper.txt")!!.readText() + .replace("%ADDRESS%", wrapper.getHost()) + .replace("%WRAPPER_NAME%", wrapper.getName()) + .replace("%MAX_SIM_SERVICE%", wrapper.getMaxSimultaneouslyStartingServices().toString()) + .replace("%MAX_MEMORY%", wrapper.getMaxMemory().toString()) + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/SupportModule.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/SupportModule.kt new file mode 100644 index 000000000..e5c314eb6 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/SupportModule.kt @@ -0,0 +1,22 @@ +package eu.thesimplecloud.module.support.manager + +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.launcher.startup.Launcher +import eu.thesimplecloud.module.support.manager.command.DumpCommand + +/** + * Created by MrManHD + * Class create at 25.06.2023 21:43 + */ + +class SupportModule : ICloudModule { + + override fun onEnable() { + Launcher.instance.commandManager.registerCommand(this, DumpCommand()) + } + + override fun onDisable() { + + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/command/DumpCommand.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/command/DumpCommand.kt new file mode 100644 index 000000000..3df13eff1 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/command/DumpCommand.kt @@ -0,0 +1,32 @@ +package eu.thesimplecloud.module.support.manager.command + +import eu.thesimplecloud.api.command.ICommandSender +import eu.thesimplecloud.launcher.console.command.CommandType +import eu.thesimplecloud.launcher.console.command.ICommandHandler +import eu.thesimplecloud.launcher.console.command.annotations.Command +import eu.thesimplecloud.launcher.console.command.annotations.CommandSubPath +import eu.thesimplecloud.module.support.lib.DumpFileCreator +import eu.thesimplecloud.module.support.manager.handler.UploadHandler + +/** + * Created by MrManHD + * Class create at 30.06.2023 20:43 + */ + +@Command("dump", CommandType.CONSOLE_AND_INGAME, "cloud.command.dump") +class DumpCommand : ICommandHandler { + + private val uploadHandler = UploadHandler() + + @CommandSubPath + fun execute(sender: ICommandSender) { + sender.sendMessage("A new dump is being created... This can take a few seconds!") + this.uploadHandler.uploadFile(DumpFileCreator().create()) + .thenAccept { sender.sendMessage("A new dump has been created under $it") } + .exceptionally { + sender.sendMessage("The dump could not be uploaded! Is the upload server online?") + null + } + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/handler/UploadHandler.kt b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/handler/UploadHandler.kt new file mode 100644 index 000000000..7cb67b819 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/kotlin/eu/thesimplecloud/module/support/manager/handler/UploadHandler.kt @@ -0,0 +1,50 @@ +package eu.thesimplecloud.module.support.manager.handler + +import eu.thesimplecloud.module.support.lib.config.UploadConfigLoader +import java.io.BufferedReader +import java.io.DataOutputStream +import java.io.InputStreamReader +import java.net.URL +import java.net.URLConnection +import java.util.concurrent.CompletableFuture + +/** + * Created by MrManHD + * Class create at 07.07.2023 20:02 + */ + +class UploadHandler { + + private val uploadUrl = UploadConfigLoader().loadConfig().uploadUrl + "/" + private val url = URL("${uploadUrl}documents") + + fun uploadFile(message: String): CompletableFuture { + return CompletableFuture.supplyAsync { + val httpURLConnection = createNewConnection(message) + + val dataOutputStream = DataOutputStream(httpURLConnection.outputStream) + dataOutputStream.write(message.encodeToByteArray()) + dataOutputStream.close() + + val response = getResponsePath(httpURLConnection) + this.uploadUrl + response + } + } + + private fun createNewConnection(message: String): URLConnection { + val connection = url.openConnection() + connection.doOutput = true + connection.setRequestProperty("User-Agent", "Hastebin Java Api") + connection.setRequestProperty("Content-Length", message.length.toString()) + connection.useCaches = false + return connection + } + + private fun getResponsePath(httpURLConnection: URLConnection): String { + val bufferedReader = BufferedReader(InputStreamReader(httpURLConnection.inputStream)) + var response = bufferedReader.readLine() + response = response.substring(response.indexOf(":") + 2, response.length - 2) + return response + } + +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/resources/module.json b/simplecloud-modules/simplecloud-module-support/src/main/resources/module.json new file mode 100644 index 000000000..735dc155b --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/resources/module.json @@ -0,0 +1,10 @@ +{ + "name": "SimpleCloud-Support", + "author": "MrManHD", + "mainClass": "eu.thesimplecloud.module.support.manager.SupportModule", + "moduleCopyType": "NONE", + "repositories": [], + "dependencies": [], + "depend": [], + "softDepend": [] +} \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/dump-file.txt b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/dump-file.txt new file mode 100644 index 000000000..d7a354d2a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/dump-file.txt @@ -0,0 +1,23 @@ +Dump created %TIME% + +OS-Name: %OS_NAME% +Java-Version: %JAVA_VERSION% +Cloud-Version: %CLOUD_VERSION% + + +Modules: %MODULES% + +JVM-Arguments: %JVM_ARGUMENTS% + +Static-Minecraft-Jars: %STATIC_JARS% + +Wrappers: %WRAPPERS% + +Templates: %TEMPLATES% + +Groups: %GROUPS% + +Services: %SERVICES% + +====== CLOUD LOG ====== +%LOG% \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/group.txt b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/group.txt new file mode 100644 index 000000000..e5b82826d --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/group.txt @@ -0,0 +1,14 @@ + %GROUP_NAME%: + - serviceGroupType: %SERVICE_GROUP_TYPE% + - template: %TEMPLATE_NAME% + - maxMemory: %MAX_MEMORY% + - minimumOnlineServiceCount: %MIN_SERVICE% + - maximumOnlineServiceCount: %MAX_SERVICE% + - maintenance: %MAINTENANCE% + - static: %STATIC% + - percentToStartNewService: %START_PERCENT% + - wrapperName: %WRAPPER_NAME% + - startPriority: %START_PRIORITY% + - javaCommandName: %JAVA_NAME% + - permission: %PERMISSION% + - serviceVersion: %SERVICE_VERSION% \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/service.txt b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/service.txt new file mode 100644 index 000000000..cd4b5092a --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/service.txt @@ -0,0 +1,10 @@ + %SERVICE_NAME%: + - groupName: %GROUP_NAME% + - displayName: %DISPLAY_NAME% + - templateName: %TEMPLATE_NAME% + - wrapperName: %WRAPPER_NAME% + - port: %PORT% + - serviceVersion: %SERVICE_VERSION% + - serviceState: %STATE% + - onlineCount: %ONLINE_COUNT% + - usedMemory: %MEMORY% \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/static-jars.txt b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/static-jars.txt new file mode 100644 index 000000000..765aebfc7 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/static-jars.txt @@ -0,0 +1,4 @@ + %JAR_NAME%: + - url: %URL_NAME% + - serviceType: %SERVICE_TYPE% + - paperClip: %PAPER_CLIP% \ No newline at end of file diff --git a/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/wrapper.txt b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/wrapper.txt new file mode 100644 index 000000000..615264775 --- /dev/null +++ b/simplecloud-modules/simplecloud-module-support/src/main/resources/temp/wrapper.txt @@ -0,0 +1,4 @@ + %WRAPPER_NAME%: + - host: %ADDRESS% + - maxSimultaneouslyStartingServices: %MAX_SIM_SERVICE% + - maxMemory: %MAX_MEMORY% \ No newline at end of file diff --git a/simplecloud-plugin/build.gradle b/simplecloud-plugin/build.gradle new file mode 100644 index 000000000..398bd68ca --- /dev/null +++ b/simplecloud-plugin/build.gradle @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +dependencies { + compileOnly group: 'org.reflections', name: 'reflections', version: '0.9.12' + compileOnly(group: 'io.netty', name: 'netty-all', version: '4.1.77.Final') + api(group: 'eu.thesimplecloud.clientserverapi', name: 'clientserverapi', version: depedencyClientServerAPIVersion) + api(group: 'eu.thesimplecloud.jsonlib', name: 'json-lib', version: "1.0.8") + api(project(":simplecloud-api")) + + api(project(":simplecloud-client")) + compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT' + compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT' + compileOnly 'com.velocitypowered:velocity-api:3.1.1' + annotationProcessor 'com.velocitypowered:velocity-api:3.1.1' + + api('net.kyori:adventure-text-minimessage:4.11.0') + api('net.kyori:adventure-platform-bungeecord:4.1.2') +} + +shadowJar { + archiveFileName.set("SimpleCloud-Plugin-${version}.jar") + dependencies { + relocate 'com.google.gson', 'eu.thesimplecloud.external' + } +} + +jar { + dependsOn ':simplecloud-client:jar' +} diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/ICloudServicePlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/ICloudServicePlugin.kt new file mode 100644 index 000000000..a47ac35fd --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/ICloudServicePlugin.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin + +import eu.thesimplecloud.api.player.ICloudPlayerManager +import kotlin.reflect.KClass + + +interface ICloudServicePlugin { + + fun getCloudPlayerManagerClass(): KClass + + fun onBeforeFirstUpdate() {} + + fun shutdown() + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/LocationExtension.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/LocationExtension.kt new file mode 100644 index 000000000..daebc7725 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/LocationExtension.kt @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.extension + +import eu.thesimplecloud.api.location.ServiceLocation +import eu.thesimplecloud.api.location.SimpleLocation +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import org.bukkit.Location + +/** + * Returns the bukkit location with the content of this location. + * Returns null if the world was not found. + */ +fun SimpleLocation.toBukkitLocation(): Location? { + val world = Bukkit.getWorld(this.worldName) ?: return null + return Location(world, x, y, z, yaw, pitch) +} + +/** + * Returns a this location parsed to a [ServiceLocation] + */ +fun Location.toCloudLocation(): ServiceLocation { + if (this.world == null) throw IllegalStateException("World must be not null.") + return ServiceLocation( + CloudPlugin.instance.thisService(), + this.world!!.name, + this.x, + this.y, + this.z, + this.yaw, + this.pitch + ) +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/PlayerExtensions.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/PlayerExtensions.kt new file mode 100644 index 000000000..ce36bdf3c --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/PlayerExtensions.kt @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.extension + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.exception.NoSuchPlayerException +import eu.thesimplecloud.api.player.ICloudPlayer +import net.md_5.bungee.api.ProxyServer +import net.md_5.bungee.api.connection.ProxiedPlayer +import org.bukkit.Bukkit +import org.bukkit.entity.Player + +/** + * Returns the CloudPlayer found by the players uuid + */ +fun ProxiedPlayer.getCloudPlayer(): ICloudPlayer = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(this.uniqueId) + ?: throw NoSuchPlayerException("Cannot find CloudPlayer by uuid: $uniqueId") + +/** + * Returns the CloudPlayer found by the players uuid + */ +fun Player.getCloudPlayer(): ICloudPlayer = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(this.uniqueId) + ?: throw NoSuchPlayerException("Cannot find CloudPlayer by uuid: $uniqueId") + +/** + * Returns the CloudPlayer found by the players uuid + */ +fun com.velocitypowered.api.proxy.Player.getCloudPlayer(): ICloudPlayer = + CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(this.uniqueId) + ?: throw NoSuchPlayerException("Cannot find CloudPlayer by uuid: $uniqueId") + +/** + * Returns the PrxiedPlayer found by the uuid of the [ICloudPlayer] + */ +fun ICloudPlayer.getProxiedPlayer(): ProxiedPlayer = ProxyServer.getInstance().getPlayer(this.getUniqueId()) + ?: throw NoSuchPlayerException("Cannot find ProxiedPlayer by uuid: ${getUniqueId()}") + +/** + * Returns the bukkit player found by the uuid of the [ICloudPlayer] + */ +fun ICloudPlayer.getBukkitPlayer(): Player = Bukkit.getPlayer(this.getUniqueId()) + ?: throw NoSuchPlayerException("Cannot find bukkit player by uuid: ${getUniqueId()}") \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/SyncExtension.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/SyncExtension.kt new file mode 100644 index 000000000..324a3a837 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/extension/SyncExtension.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.extension + +import eu.thesimplecloud.plugin.proxy.ICloudProxyPlugin +import eu.thesimplecloud.plugin.proxy.bungee.CloudBungeePlugin +import eu.thesimplecloud.plugin.server.CloudSpigotPlugin +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.md_5.bungee.api.ProxyServer +import org.bukkit.Bukkit +import java.util.concurrent.TimeUnit + +fun syncBukkit(function: () -> Unit) = Bukkit.getScheduler().runTask(CloudSpigotPlugin.instance, function) + +fun syncService(function: () -> Unit) { + if (CloudPlugin.instance.cloudServicePlugin is ICloudProxyPlugin) { + ProxyServer.getInstance().scheduler.schedule(CloudBungeePlugin.instance, function, 0, TimeUnit.MILLISECONDS) + } else { + Bukkit.getScheduler().runTask(CloudSpigotPlugin.instance, function) + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudAPIImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudAPIImpl.kt new file mode 100644 index 000000000..d8f509e82 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudAPIImpl.kt @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.eventapi.IEventManager +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.language.ILanguageManager +import eu.thesimplecloud.api.language.LanguageManager +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.api.service.ICloudServiceManager +import eu.thesimplecloud.api.service.version.IServiceVersionHandler +import eu.thesimplecloud.api.service.version.ServiceVersionHandler +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroupManager +import eu.thesimplecloud.api.sync.list.manager.ISynchronizedObjectListManager +import eu.thesimplecloud.api.sync.list.manager.SynchronizedObjectListManager +import eu.thesimplecloud.clientserverapi.lib.bootstrap.ICommunicationBootstrap +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class CloudAPIImpl(private val cloudPlayerManager: ICloudPlayerManager) : CloudAPI() { + + private val cloudServiceManager = CloudServiceManagerImpl() + private val cloudServiceGroupManager = CloudServiceGroupManagerImpl() + private val commandExecuteManagerImpl = CommandExecuteManagerImpl() + private val eventManager = EventManagerImpl() + private val synchronizedObjectListManager = SynchronizedObjectListManager() + private val serviceVersionHandler = ServiceVersionHandler() + private val languageManager = LanguageManager() + + init { + getCacheListManager().registerCacheList(getWrapperManager()) + getCacheListManager().registerCacheList(getCloudServiceManager()) + getCacheListManager().registerCacheList(getCloudServiceGroupManager()) + getCacheListManager().registerCacheList(getTemplateManager()) + getCacheListManager().registerCacheList(getCloudPlayerManager()) + } + + override fun getCloudServiceGroupManager(): ICloudServiceGroupManager = this.cloudServiceGroupManager + + override fun getCloudServiceManager(): ICloudServiceManager = this.cloudServiceManager + + override fun getCloudPlayerManager(): ICloudPlayerManager = this.cloudPlayerManager + + override fun getEventManager(): IEventManager = this.eventManager + + override fun getCommandExecuteManager(): ICommandExecuteManager = this.commandExecuteManagerImpl + + override fun getThisSidesCommunicationBootstrap(): ICommunicationBootstrap = + CloudPlugin.instance.communicationClient + + override fun getSynchronizedObjectListManager(): ISynchronizedObjectListManager = this.synchronizedObjectListManager + + override fun getServiceVersionHandler(): IServiceVersionHandler = this.serviceVersionHandler + + override fun getLanguageManager(): ILanguageManager = this.languageManager + + override fun getThisSidesName(): String = CloudPlugin.instance.thisServiceName + + override fun getThisSidesNetworkComponent(): INetworkComponent { + return CloudPlugin.instance.thisService() + } + + override fun getThisSidesCloudModule(): ICloudModule = CloudPlugin.instance + + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceGroupManagerImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceGroupManagerImpl.kt new file mode 100644 index 000000000..eb0ef9f81 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceGroupManagerImpl.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.network.packets.service.PacketIOStartCloudService +import eu.thesimplecloud.api.network.packets.servicegroup.PacketIOCreateServiceGroup +import eu.thesimplecloud.api.service.start.configuration.IServiceStartConfiguration +import eu.thesimplecloud.api.service.start.future.IServiceStartPromise +import eu.thesimplecloud.api.service.start.future.ServiceStartPromise +import eu.thesimplecloud.api.servicegroup.ICloudServiceGroup +import eu.thesimplecloud.api.servicegroup.impl.AbstractCloudServiceGroupManager +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class CloudServiceGroupManagerImpl : AbstractCloudServiceGroupManager() { + + override fun createServiceGroup(cloudServiceGroup: ICloudServiceGroup): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendQuery(PacketIOCreateServiceGroup(cloudServiceGroup)) + } + + override fun startNewService(serviceStartConfiguration: IServiceStartConfiguration): IServiceStartPromise { + val namePromise = CloudPlugin.instance.connectionToManager + .sendQuery(PacketIOStartCloudService(serviceStartConfiguration)) + val servicePromise = namePromise.then { CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(it)!! } + return ServiceStartPromise(servicePromise) + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceManagerImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceManagerImpl.kt new file mode 100644 index 000000000..89a27f074 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CloudServiceManagerImpl.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl + +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.listenerextension.cloudListener +import eu.thesimplecloud.api.network.packets.service.PacketIOCopyService +import eu.thesimplecloud.api.network.packets.service.PacketIOStopCloudService +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.impl.AbstractCloudServiceManager +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class CloudServiceManagerImpl : AbstractCloudServiceManager() { + + override fun stopService(cloudService: ICloudService): ICommunicationPromise { + CloudPlugin.instance.connectionToManager.sendUnitQuery(PacketIOStopCloudService(cloudService.getName())) + return cloudListener() + .addCondition { it.cloudService == cloudService } + .unregisterAfterCall() + .toUnitPromise() + } + + override fun copyService(cloudService: ICloudService, path: String): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendUnitQuery( + PacketIOCopyService(cloudService, path), + 20 * 1000 + ) + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CommandExecuteManagerImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CommandExecuteManagerImpl.kt new file mode 100644 index 000000000..3414a87a8 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/CommandExecuteManagerImpl.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl + +import eu.thesimplecloud.api.network.component.INetworkComponent +import eu.thesimplecloud.api.network.packets.screen.PacketIOExecuteCommand +import eu.thesimplecloud.api.screen.ICommandExecutable +import eu.thesimplecloud.api.screen.ICommandExecuteManager +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class CommandExecuteManagerImpl : ICommandExecuteManager { + + override fun executeCommand(commandExecutable: ICommandExecutable, command: String) { + if (commandExecutable !is INetworkComponent) return + CloudPlugin.instance.connectionToManager.sendUnitQuery( + PacketIOExecuteCommand( + commandExecutable.getNetworkComponentType(), + commandExecutable.getName(), + command + ) + ) + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/EventManagerImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/EventManagerImpl.kt new file mode 100644 index 000000000..2af1c60bb --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/EventManagerImpl.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl + +import eu.thesimplecloud.api.eventapi.BasicEventManager +import eu.thesimplecloud.api.eventapi.IEvent +import eu.thesimplecloud.api.eventapi.ISynchronizedEvent +import eu.thesimplecloud.api.network.packets.event.PacketIOCallEvent +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class EventManagerImpl : BasicEventManager() { + + override fun call(event: IEvent, fromPacket: Boolean) { + //don't call event if fromPacket is true because the event will be called via the received packet. + if (!fromPacket && event is ISynchronizedEvent) { + CloudPlugin.instance.connectionToManager.sendUnitQuery(PacketIOCallEvent(event)) + } else { + super.call(event, fromPacket) + } + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractCloudPlayerManagerProxy.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractCloudPlayerManagerProxy.kt new file mode 100644 index 000000000..3e4ed86ca --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractCloudPlayerManagerProxy.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl.player + +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.TextComponent +import net.kyori.adventure.text.minimessage.MiniMessage + +/** + * Date: 18.06.22 + * Time: 17:52 + * @author Frederick Baier + * + */ +abstract class AbstractCloudPlayerManagerProxy : AbstractServiceCloudPlayerManager() { + + protected fun getHexColorComponent(message: String): TextComponent { + return Component.textOfChildren(MiniMessage.miniMessage().deserialize(message)) + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractServiceCloudPlayerManager.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractServiceCloudPlayerManager.kt new file mode 100644 index 000000000..59f3b823b --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/impl/player/AbstractServiceCloudPlayerManager.kt @@ -0,0 +1,118 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.impl.player + +import eu.thesimplecloud.api.network.packets.player.* +import eu.thesimplecloud.api.player.* +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.plugin.startup.CloudPlugin +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 15.05.2020 + * Time: 21:52 + */ +abstract class AbstractServiceCloudPlayerManager : AbstractCloudPlayerManager() { + + override fun update( + value: ICloudPlayer, + fromPacket: Boolean, + isCalledFromDelete: Boolean + ): ICommunicationPromise { + super.update(value, fromPacket, isCalledFromDelete) + if (!fromPacket) + return sendUpdateToConnection(value, CloudPlugin.instance.connectionToManager) + return CommunicationPromise.UNIT_PROMISE + } + + override fun getCloudPlayer(uniqueId: UUID): ICommunicationPromise { + val cachedCloudPlayer = getCachedCloudPlayer(uniqueId) + if (cachedCloudPlayer != null) { + return CommunicationPromise.of(cachedCloudPlayer) + } + return CloudPlugin.instance.connectionToManager.sendQuery(PacketIOGetCloudPlayer(uniqueId)) + } + + override fun getCloudPlayer(name: String): ICommunicationPromise { + val cachedCloudPlayer = getCachedCloudPlayer(name) + if (cachedCloudPlayer != null) { + return CommunicationPromise.of(cachedCloudPlayer) + } + return CloudPlugin.instance.connectionToManager.sendQuery(PacketIOGetCloudPlayer(name)) + } + + override fun setUpdates(cloudPlayer: ICloudPlayer, update: Boolean, serviceName: String) { + super.setUpdates(cloudPlayer, update, serviceName) + CloudPlugin.instance.connectionToManager.sendUnitQuery( + PacketIOSetCloudPlayerUpdates( + cloudPlayer, + update, + serviceName + ) + ) + } + + override fun getOfflineCloudPlayer(name: String): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendQuery(PacketIOGetOfflinePlayer(name)) + } + + override fun getOfflineCloudPlayer(uniqueId: UUID): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendQuery(PacketIOGetOfflinePlayer(uniqueId)) + } + + override fun getAllOnlinePlayers(): ICommunicationPromise> { + return CloudPlugin.instance.connectionToManager.sendQuery>(PacketIOGetAllOnlinePlayers()) + .then { it.toList() } + } + + override fun savePlayerToDatabase(offlinePlayer: IOfflineCloudPlayer): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendUnitQuery( + PacketIOSaveOfflinePlayer(offlinePlayer as OfflineCloudPlayer), + 1000 + ) + } + + override fun getNetworkOnlinePlayerCount(): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendQuery( + PacketIOGetNetworkOnlineCount() + ) + } + + override fun getRegisteredPlayerCount(): ICommunicationPromise { + return CloudPlugin.instance.connectionToManager.sendQuery( + PacketIOGetRegisteredPlayerCount() + ) + } + + override fun getPlayersConnectedToService(cloudService: ICloudService): ICommunicationPromise> { + return CloudPlugin.instance.connectionToManager.sendQuery>( + PacketIOGetPlayersConnectedToService(cloudService), 700 + ).then { it.toList() } + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/listener/CloudListener.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/listener/CloudListener.kt new file mode 100644 index 000000000..349214709 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/listener/CloudListener.kt @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.listener + +import eu.thesimplecloud.api.event.service.CloudServiceStartingEvent +import eu.thesimplecloud.api.event.service.CloudServiceUnregisteredEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import eu.thesimplecloud.plugin.proxy.ICloudProxyPlugin +import eu.thesimplecloud.plugin.startup.CloudPlugin + +class CloudListener : IListener { + + @CloudEventHandler + fun on(serviceEvent: CloudServiceStartingEvent) { + val cloudServicePlugin = CloudPlugin.instance.cloudServicePlugin + if (cloudServicePlugin is ICloudProxyPlugin) { + cloudServicePlugin.addServiceToProxy(serviceEvent.cloudService) + } + } + + @CloudEventHandler + fun on(serviceEvent: CloudServiceUnregisteredEvent) { + val cloudServicePlugin = CloudPlugin.instance.cloudServicePlugin + if (cloudServicePlugin is ICloudProxyPlugin) { + cloudServicePlugin.removeServiceFromProxy(serviceEvent.cloudService) + } + } + + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketInGetPlayerOnlineStatus.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketInGetPlayerOnlineStatus.kt new file mode 100644 index 000000000..172f3ea28 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketInGetPlayerOnlineStatus.kt @@ -0,0 +1,52 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.api.service.version.type.ServiceAPIType +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.plugin.proxy.velocity.CloudVelocityPlugin +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.md_5.bungee.api.ProxyServer +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 10.04.2020 + * Time: 21:32 + */ +class PacketInGetPlayerOnlineStatus : ObjectPacket() { + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + val uuid = this.value ?: return contentException("value") + + return if (CloudPlugin.instance.thisService().getServiceVersion().serviceAPIType == ServiceAPIType.VELOCITY) { + success(CloudVelocityPlugin.instance.proxyServer.getPlayer(uuid) != null) + } else { + success(ProxyServer.getInstance().getPlayer(uuid) != null) + } + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutCreateCloudPlayer.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutCreateCloudPlayer.kt new file mode 100644 index 000000000..cf53b13be --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutCreateCloudPlayer.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketOutCreateCloudPlayer() : JsonPacket() { + + constructor(defaultPlayerConnection: DefaultPlayerConnection, proxyName: String) : this() { + this.jsonLib.append("playerConnection", defaultPlayerConnection).append("proxyName", proxyName) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise = unit() +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutGetTabSuggestions.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutGetTabSuggestions.kt new file mode 100644 index 000000000..66a0ac18b --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutGetTabSuggestions.kt @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 14.04.2020 + * Time: 19:05 + */ +class PacketOutGetTabSuggestions() : JsonPacket() { + + constructor(uuid: UUID, command: String) : this() { + this.jsonLib + .append("uuid", uuid) + .append("command", command) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return unit() + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerConnectToServer.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerConnectToServer.kt new file mode 100644 index 000000000..f0cc85e83 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerConnectToServer.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketOutPlayerConnectToServer(playerUniqueId: UUID, serviceName: String) : JsonPacket() { + + init { + this.jsonLib.append("playerUniqueId", playerUniqueId).append("serviceName", serviceName) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise = unit() +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerExecuteCommand.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerExecuteCommand.kt new file mode 100644 index 000000000..17396f523 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerExecuteCommand.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise + +class PacketOutPlayerExecuteCommand() : JsonPacket() { + + constructor(cloudPlayer: ICloudPlayer, command: String) : this() { + this.jsonLib.append("playerUniqueId", cloudPlayer.getUniqueId()).append("command", command) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise { + return unit() + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerLoginRequest.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerLoginRequest.kt new file mode 100644 index 000000000..960498064 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutPlayerLoginRequest.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.ObjectPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketOutPlayerLoginRequest(val uniqueId: UUID) : ObjectPacket(uniqueId) { + + override suspend fun handle(connection: IConnection): ICommunicationPromise = unit() +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutTeleportOtherService.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutTeleportOtherService.kt new file mode 100644 index 000000000..991d727e8 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/network/packets/PacketOutTeleportOtherService.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.network.packets + +import eu.thesimplecloud.api.location.SimpleLocation +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.packet.packettype.JsonPacket +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import java.util.* + +class PacketOutTeleportOtherService(playerUniqueId: UUID, serviceName: String, simpleLocation: SimpleLocation) : + JsonPacket() { + + init { + this.jsonLib.append("playerUniqueId", playerUniqueId).append("serviceName", serviceName) + .append("simpleLocation", simpleLocation) + } + + override suspend fun handle(connection: IConnection): ICommunicationPromise = unit() +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/CancelType.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/CancelType.kt new file mode 100644 index 000000000..fb4edf99d --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/CancelType.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 16.05.2020 + * Time: 00:11 + */ +enum class CancelType { + + MESSAGE, KICK; + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ICloudProxyPlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ICloudProxyPlugin.kt new file mode 100644 index 000000000..380974717 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ICloudProxyPlugin.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy + +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.plugin.ICloudServicePlugin + +interface ICloudProxyPlugin : ICloudServicePlugin { + + fun addServiceToProxy(cloudService: ICloudService) + + fun removeServiceFromProxy(cloudService: ICloudService) + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ProxyEventHandler.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ProxyEventHandler.kt new file mode 100644 index 000000000..cd6ab27f6 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/ProxyEventHandler.kt @@ -0,0 +1,253 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.dto.PlayerLoginRequestResult +import eu.thesimplecloud.api.event.player.CloudPlayerDisconnectEvent +import eu.thesimplecloud.api.event.player.CloudPlayerLoginEvent +import eu.thesimplecloud.api.player.ICloudPlayer +import eu.thesimplecloud.api.player.PlayerServerConnectState +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.api.player.impl.CloudPlayer +import eu.thesimplecloud.api.player.impl.CloudPlayerUpdater +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.clientserverapi.lib.packet.packetsender.sendQuery +import eu.thesimplecloud.clientserverapi.lib.promise.CommunicationPromise +import eu.thesimplecloud.clientserverapi.lib.promise.ICommunicationPromise +import eu.thesimplecloud.plugin.network.packets.PacketOutCreateCloudPlayer +import eu.thesimplecloud.plugin.network.packets.PacketOutGetTabSuggestions +import eu.thesimplecloud.plugin.network.packets.PacketOutPlayerConnectToServer +import eu.thesimplecloud.plugin.network.packets.PacketOutPlayerLoginRequest +import eu.thesimplecloud.plugin.startup.CloudPlugin +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 15.05.2020 + * Time: 23:07 + */ +object ProxyEventHandler { + + private val thisGroup = CloudPlugin.instance.thisService().getServiceGroup() + + fun handleLogin(playerConnection: DefaultPlayerConnection, cancelEvent: (String) -> Unit) { + val thisService = CloudPlugin.instance.thisService() + if (!thisService.isAuthenticated() || !thisService.isOnline()) { + cancelEvent("§cProxy is still starting.") + return + } + val playerPromise = CloudAPI.instance.getCloudPlayerManager() + .getCloudPlayer(playerConnection.getUniqueId()).awaitUninterruptibly() + if (playerPromise.isSuccess) { + handleAlreadyRegistered(playerPromise.getNow()!!) + } + + //send login request + val createPromise = CloudPlugin.instance.connectionToManager + .sendQuery( + PacketOutCreateCloudPlayer(playerConnection, CloudPlugin.instance.thisServiceName), + 1000 + ).awaitUninterruptibly() + if (!createPromise.isSuccess) { + cancelEvent("§cFailed to create player: ${createPromise.cause().message}") + println("Failed to create CloudPlayer:") + throw createPromise.cause() + } + val loginRequestPromise = CloudPlugin.instance.connectionToManager.sendQuery( + PacketOutPlayerLoginRequest(playerConnection.getUniqueId()), 1000 + ).awaitUninterruptibly() + if (!loginRequestPromise.isSuccess) { + loginRequestPromise.cause().printStackTrace() + cancelEvent("§cLogin failed: " + loginRequestPromise.cause().message) + return + } + val loginRequestResult = loginRequestPromise.getBlocking() + if (loginRequestResult.cancel) { + cancelEvent(loginRequestResult.kickMessage) + } + + val cloudPlayer = createPromise.getNow()!! + val permission = thisGroup.getPermission() + if (permission != null && !cloudPlayer.hasPermissionSync(permission)) { + val message = CloudAPI.instance.getLanguageManager().getMessage("ingame.no-permission") + cancelEvent(message) + return + } + + //update player to cache to avoid bugs + CloudAPI.instance.getCloudPlayerManager().update(cloudPlayer, true).awaitUninterruptibly() + } + + private fun handleAlreadyRegistered(player: ICloudPlayer) { + player.kick().awaitUninterruptibly() + CloudAPI.instance.getCloudPlayerManager() + .sendDeleteToConnection(player, CloudPlugin.instance.connectionToManager) + .awaitUninterruptibly() + } + + fun handlePostLogin(uniqueId: UUID, name: String) { + val thisService = CloudPlugin.instance.thisService() + thisService.setOnlineCount(thisService.getOnlineCount() + 1) + thisService.update().awaitUninterruptibly() + + CloudAPI.instance.getEventManager().call(CloudPlayerLoginEvent(uniqueId, name)) + } + + + fun handleDisconnect(uniqueId: UUID, name: String) { + CloudAPI.instance.getEventManager().call(CloudPlayerDisconnectEvent(uniqueId, name)) + + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + cloudPlayer?.let { + cloudPlayer as CloudPlayer + cloudPlayer.setOffline() + CloudAPI.instance.getCloudPlayerManager().delete(cloudPlayer) + //send update that the player is now offline + val connection = CloudPlugin.instance.connectionToManager + CloudAPI.instance.getCloudPlayerManager().sendDeleteToConnection(cloudPlayer, connection) + .awaitUninterruptibly() + } + + subtractOneFromThisServiceOnlineCount() + } + + + fun handleServerPreConnect( + uniqueId: UUID, + serverNameFrom: String?, + serverNameTo: String, + cancelEvent: (String, CancelType) -> Unit + ) { + if (serverNameFrom == serverNameTo) + return + + val cloudService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serverNameTo) + if (cloudService == null) { + val message = CloudAPI.instance.getLanguageManager().getMessage("ingame.service-not-registered") + cancelEvent(message, CancelType.KICK) + return + } + val serviceGroup = cloudService.getServiceGroup() + val cloudPlayer: ICloudPlayer? = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + + if (cloudPlayer == null) { + cancelEvent("§cUnable to find cloud player.", CancelType.KICK) + return + } + + if (serviceGroup.isInMaintenance()) { + if (!cloudPlayer.hasPermissionSync("cloud.maintenance.join")) { + val message = CloudAPI.instance.getLanguageManager().getMessage("ingame.service-in-maintenance") + cancelEvent(message, CancelType.MESSAGE) + return + } + } + + if (serviceGroup is ICloudServerGroup) { + val permission = serviceGroup.getPermission() + if (permission != null && !cloudPlayer.hasPermissionSync(permission)) { + val message = CloudAPI.instance.getLanguageManager().getMessage("ingame.no-permission") + cancelEvent(message, CancelType.MESSAGE) + return + } + } + + if (cloudService.getState() == ServiceState.STARTING) { + val message = CloudAPI.instance.getLanguageManager().getMessage("ingame.server-still-starting") + cancelEvent(message, CancelType.MESSAGE) + return + } + + CloudPlugin.instance.connectionToManager.sendUnitQuery(PacketOutPlayerConnectToServer(uniqueId, serverNameTo)) + .awaitUninterruptibly() + .addFailureListener { + cancelEvent("§cCan't connect to server: " + it.message, CancelType.MESSAGE) + } + + + val playerUpdater = cloudPlayer.getUpdater() + playerUpdater as CloudPlayerUpdater + playerUpdater.setServerConnectState(PlayerServerConnectState.CONNECTING) + playerUpdater.update().awaitUninterruptibly() + } + + + fun handleServerConnect(uniqueId: UUID, serverName: String, cancelEvent: (String) -> Unit) { + val service = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serverName) + if (service == null) { + cancelEvent("§cService does not exist.") + return + } + + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(uniqueId) + cloudPlayer ?: return + val playerUpdater = cloudPlayer.getUpdater() + playerUpdater as CloudPlayerUpdater + playerUpdater.setConnectedServerName(service.getName()) + playerUpdater.setServerConnectState(PlayerServerConnectState.CONNECTED) + playerUpdater.update().awaitUninterruptibly() + } + + fun handleServerKick( + cloudPlayer: ICloudPlayer, + kickReasonString: String, + serverName: String, + cancelEvent: (String, CancelType) -> Unit + ) { + if (kickReasonString.isNotEmpty() && kickReasonString.contains("Outdated server") || kickReasonString.contains("Outdated client")) { + val cloudService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(serverName) + if (cloudService == null || cloudService.isLobby()) { + cancelEvent("§cYou are using an unsupported version.", CancelType.KICK) + return + } + } + val playerUpdater = cloudPlayer.getUpdater() + playerUpdater as CloudPlayerUpdater + if (playerUpdater.getConnectedServerName() != null) { + playerUpdater.setServerConnectState(PlayerServerConnectState.CONNECTED) + playerUpdater.update().awaitUninterruptibly() + } + } + + fun handleTabComplete(uuid: UUID, rawCommand: String): ICommunicationPromise> { + val commandString = rawCommand.replace("/", "") + if (commandString.isEmpty()) return CommunicationPromise.of(emptyArray()) + + return CloudPlugin.instance.connectionToManager.sendQuery( + PacketOutGetTabSuggestions( + uuid, + commandString + ) + ) + } + + private fun subtractOneFromThisServiceOnlineCount() { + val service = CloudPlugin.instance.thisService() + service.setOnlineCount(service.getOnlineCount() - 1) + service.update().awaitUninterruptibly() + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/BungeeComponentExtensions.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/BungeeComponentExtensions.kt new file mode 100644 index 000000000..d34d7e81e --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/BungeeComponentExtensions.kt @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.bungee + +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer +import net.md_5.bungee.api.chat.BaseComponent + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.06.22 + * Time: 15:04 + */ + +fun Component.toBaseComponent(): BaseComponent { + return BungeeComponentSerializer.get().serialize(this)[0] +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/CloudBungeePlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/CloudBungeePlugin.kt new file mode 100644 index 000000000..4c7d8608d --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/CloudBungeePlugin.kt @@ -0,0 +1,191 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.bungee + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.plugin.impl.player.CloudPlayerManagerBungee +import eu.thesimplecloud.plugin.listener.CloudListener +import eu.thesimplecloud.plugin.proxy.ICloudProxyPlugin +import eu.thesimplecloud.plugin.proxy.ProxyEventHandler +import eu.thesimplecloud.plugin.proxy.bungee.command.BungeeCommand +import eu.thesimplecloud.plugin.proxy.bungee.listener.BungeeListener +import eu.thesimplecloud.plugin.proxy.bungee.listener.CloudPlayerDisconnectListener +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.kyori.adventure.platform.bungeecord.BungeeAudiences +import net.md_5.bungee.api.ProxyServer +import net.md_5.bungee.api.plugin.Plugin +import java.net.InetSocketAddress +import java.util.* +import java.util.concurrent.TimeUnit +import kotlin.reflect.KClass + +class CloudBungeePlugin : Plugin(), ICloudProxyPlugin { + + private val registeredIngameCommands = arrayListOf() + + val lobbyConnector = LobbyConnector() + + @Volatile + lateinit var synchronizedIngameCommandsProperty: IProperty> + private set + + companion object { + @JvmStatic + lateinit var instance: CloudBungeePlugin + } + + var bungeeAudiences: BungeeAudiences + + init { + instance = this + bungeeAudiences = BungeeAudiences.create(this) + } + + override fun shutdown() { + ProxyServer.getInstance().stop() + this.bungeeAudiences.close() + } + + override fun addServiceToProxy(cloudService: ICloudService) { + if (ProxyServer.getInstance().getServerInfo(cloudService.getName()) != null) { + throw IllegalArgumentException("Service is already registered!") + } + + if (cloudService.getServiceType().isProxy()) + return + val cloudServiceGroup = cloudService.getServiceGroup() + if ((cloudServiceGroup as ICloudServerGroup).getHiddenAtProxyGroups() + .contains(CloudPlugin.instance.getGroupName()) + ) + return + println("Registered service ${cloudService.getName()}") + val socketAddress = InetSocketAddress(cloudService.getHost(), cloudService.getPort()) + registerService(cloudService.getName(), cloudService.getUniqueId(), socketAddress) + } + + private fun registerFallbackService() { + registerService( + "fallback", + UUID.fromString("00000000-0000-0000-0000-000000000000"), + InetSocketAddress("127.0.0.1", 0) + ) + } + + private fun registerService(name: String, uniqueId: UUID, socketAddress: InetSocketAddress) { + val info = ProxyServer.getInstance().constructServerInfo( + name, socketAddress, + uniqueId.toString(), false + ) + ProxyServer.getInstance().servers[name] = info + } + + override fun removeServiceFromProxy(cloudService: ICloudService) { + ProxyServer.getInstance().servers.remove(cloudService.getName()) + } + + override fun onLoad() { + ProxyServer.getInstance().reconnectHandler = ReconnectHandlerImpl() + CloudPlugin(this) + val synchronizedObjectPromise = + CloudAPI.instance.getGlobalPropertyHolder().requestProperty>("simplecloud-ingamecommands") + synchronizedObjectPromise.addResultListener { + this.synchronizedIngameCommandsProperty = it + }.throwFailure() + } + + override fun onEnable() { + ProxyServer.getInstance().configurationAdapter.servers.clear() + ProxyServer.getInstance().servers.clear() + for (info in ProxyServer.getInstance().configurationAdapter.listeners) { + info.serverPriority.clear() + } + + registerFallbackService() + CloudPlugin.instance.onEnable() + CloudAPI.instance.getCloudServiceManager().getAllCachedObjects().filter { it.isActive() } + .forEach { addServiceToProxy(it) } + CloudAPI.instance.getEventManager().registerListener(CloudPlugin.instance, CloudListener()) + ProxyServer.getInstance().pluginManager.registerListener(this, BungeeListener()) + + registerIngameCommands() + synchronizeOnlineCountTask() + runOfflinePlayerChecker() + + CloudAPI.instance.getEventManager() + .registerListener(CloudPlugin.instance, CloudPlayerDisconnectListener(this.proxy)) + } + + override fun onDisable() { + CloudPlugin.instance.onDisable() + } + + private fun registerIngameCommands() { + val synchronizedObjectPromise = + CloudAPI.instance.getGlobalPropertyHolder().requestProperty>("simplecloud-ingamecommands") + synchronizedObjectPromise.addResultListener { property -> + this.synchronizedIngameCommandsProperty = property + + this.synchronizedIngameCommandsProperty.getValue().forEach { commandName -> + val pluginManager = ProxyServer.getInstance().pluginManager + val bungeeCommand = this.registeredIngameCommands + .firstOrNull { it.commandStart == commandName } ?: return@forEach + pluginManager.unregisterCommand(bungeeCommand) + } + + this.synchronizedIngameCommandsProperty.getValue().forEach { + val pluginManager = ProxyServer.getInstance().pluginManager + val bungeeCommand = BungeeCommand(it) + pluginManager.registerCommand(this, bungeeCommand) + this.registeredIngameCommands.add(bungeeCommand) + } + }.throwFailure() + } + + private fun runOfflinePlayerChecker() { + proxy.scheduler.schedule(this, { + val playersOnThisService = + CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects() + val playersOffline = playersOnThisService.filter { proxy.getPlayer(it.getUniqueId()) == null } + playersOffline.forEach { ProxyEventHandler.handleDisconnect(it.getUniqueId(), it.getName()) } + }, 2, 30, TimeUnit.SECONDS) + } + + private fun synchronizeOnlineCountTask() { + proxy.scheduler.schedule(this, { + val service = CloudPlugin.instance.thisService() + if (service.getOnlineCount() != proxy.onlineCount) { + service.setOnlineCount(proxy.onlineCount) + service.update() + } + }, 0, 30, TimeUnit.SECONDS) + } + + override fun getCloudPlayerManagerClass(): KClass { + return CloudPlayerManagerBungee::class + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/LobbyConnector.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/LobbyConnector.kt new file mode 100644 index 000000000..be9305ac2 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/LobbyConnector.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.bungee + +import eu.thesimplecloud.api.CloudAPI +import net.md_5.bungee.api.ProxyServer +import net.md_5.bungee.api.config.ServerInfo +import net.md_5.bungee.api.connection.ProxiedPlayer + +class LobbyConnector { + + fun getLobbyServer(player: ProxiedPlayer, filterServices: List = emptyList()): ServerInfo? { + val lobbyGroups = CloudAPI.instance.getCloudServiceGroupManager().getLobbyGroups() + val sortedLobbyGroups = lobbyGroups.sortedByDescending { it.getPriority() } + .filter { !it.isInMaintenance() || player.hasPermission("cloud.maintenance.join") } + val groups = sortedLobbyGroups.filter { it.getPermission() == null || player.hasPermission(it.getPermission()) } + val availableServices = + groups.map { group -> group.getAllServices().filter { it.isOnline() }.filter { !it.isFull() } }.flatten() + val serviceToConnectTo = + availableServices.filter { !filterServices.contains(it.getName()) }.minByOrNull { it.getOnlineCount() } + if (serviceToConnectTo == null) println("WARNING: Lobby server was null.") + return serviceToConnectTo?.let { ProxyServer.getInstance().getServerInfo(it.getName()) } + } + + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/ReconnectHandlerImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/ReconnectHandlerImpl.kt new file mode 100644 index 000000000..ebcd41265 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/ReconnectHandlerImpl.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.bungee + +import net.md_5.bungee.api.ProxyServer +import net.md_5.bungee.api.ReconnectHandler +import net.md_5.bungee.api.config.ServerInfo +import net.md_5.bungee.api.connection.ProxiedPlayer + +class ReconnectHandlerImpl : ReconnectHandler { + override fun save() { + } + + override fun getServer(player: ProxiedPlayer): ServerInfo { + return ProxyServer.getInstance().getServerInfo("fallback") + } + + override fun setServer(player: ProxiedPlayer?) { + } + + override fun close() { + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/command/BungeeCommand.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/command/BungeeCommand.kt new file mode 100644 index 000000000..bd569348a --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/command/BungeeCommand.kt @@ -0,0 +1,61 @@ +package eu.thesimplecloud.plugin.proxy.bungee.command + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.player.CloudPlayerCommandExecuteEvent +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import eu.thesimplecloud.plugin.network.packets.PacketOutPlayerExecuteCommand +import eu.thesimplecloud.plugin.proxy.ProxyEventHandler +import eu.thesimplecloud.plugin.proxy.bungee.CloudBungeePlugin +import eu.thesimplecloud.plugin.startup.CloudPlugin +import net.md_5.bungee.api.CommandSender +import net.md_5.bungee.api.connection.ProxiedPlayer +import net.md_5.bungee.api.plugin.Command +import net.md_5.bungee.api.plugin.TabExecutor +import java.util.concurrent.CompletableFuture + +/** + * Created by MrManHD + * Class create at 20.06.2023 15:44 + */ + +class BungeeCommand( + val commandStart: String +) : Command(commandStart), TabExecutor { + + override fun execute(sender: CommandSender, args: Array) { + if (sender !is ProxiedPlayer) + return + + val rawCommand = "$commandStart " + args.joinToString(" ") + + if (CloudBungeePlugin.instance.synchronizedIngameCommandsProperty.getValue() + .contains(this.commandStart.lowercase()) + ) { + CloudPlugin.instance.connectionToManager.sendUnitQuery( + PacketOutPlayerExecuteCommand( + sender.getCloudPlayer(), + rawCommand + ) + ) + } + CloudAPI.instance.getEventManager() + .call(CloudPlayerCommandExecuteEvent(sender.uniqueId, sender.name, rawCommand)) + } + + override fun onTabComplete(sender: CommandSender, args: Array): MutableIterable { + if (sender !is ProxiedPlayer) + return mutableListOf() + val rawCommand = "$commandStart " + args.joinToString(" ") + return getSuggestCompletableFuture(sender, rawCommand).get().sorted().toMutableList() + } + + private fun getSuggestCompletableFuture( + player: ProxiedPlayer, + rawCommand: String + ): CompletableFuture> { + val completableFuture = CompletableFuture>() + ProxyEventHandler.handleTabComplete(player.uniqueId, rawCommand) + .addResultListener { completableFuture.complete(it.toMutableList()) } + return completableFuture + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/BungeeListener.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/BungeeListener.kt new file mode 100644 index 000000000..2c8d56025 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/BungeeListener.kt @@ -0,0 +1,173 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.bungee.listener + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.connection.DefaultPlayerAddress +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import eu.thesimplecloud.plugin.proxy.CancelType +import eu.thesimplecloud.plugin.proxy.ProxyEventHandler +import eu.thesimplecloud.plugin.proxy.bungee.CloudBungeePlugin +import eu.thesimplecloud.plugin.proxy.bungee.toBaseComponent +import net.kyori.adventure.text.Component +import net.md_5.bungee.api.event.* +import net.md_5.bungee.api.plugin.Listener +import net.md_5.bungee.event.EventHandler +import net.md_5.bungee.event.EventPriority + +class BungeeListener : Listener { + + @EventHandler(priority = EventPriority.LOW) + fun on(event: LoginEvent) { + if (event.isCancelled) return + val connection = event.connection + + val playerAddress = DefaultPlayerAddress(connection.address.hostString, connection.address.port) + val playerConnection = DefaultPlayerConnection( + playerAddress, + connection.name, + connection.uniqueId, + connection.isOnlineMode, + connection.version + ) + + + ProxyEventHandler.handleLogin(playerConnection) { + event.isCancelled = true + event.setCancelReason(Component.text(it).toBaseComponent()) + } + + } + + @EventHandler + fun on(event: PostLoginEvent) { + val proxiedPlayer = event.player + proxiedPlayer.reconnectServer = null + + ProxyEventHandler.handlePostLogin(proxiedPlayer.uniqueId, proxiedPlayer.name) + + if (CloudBungeePlugin.instance.lobbyConnector.getLobbyServer(proxiedPlayer) == null) { + event.player.disconnect(Component.text(getNoFallbackServerFoundMessage()).toBaseComponent()) + return + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun on(event: PlayerDisconnectEvent) { + val proxiedPlayer = event.player + + ProxyEventHandler.handleDisconnect(proxiedPlayer.uniqueId, proxiedPlayer.name) + } + + @EventHandler + fun on(event: ServerConnectEvent) { + if (event.isCancelled) return + val proxiedPlayer = event.player + val target = if (event.target.name == "fallback") + CloudBungeePlugin.instance.lobbyConnector.getLobbyServer(proxiedPlayer) + else + event.target + if (target == null) { + event.player.disconnect(Component.text(getNoFallbackServerFoundMessage()).toBaseComponent()) + return + } + event.target = target + + + val name: String? = proxiedPlayer.server?.info?.name + + ProxyEventHandler.handleServerPreConnect( + proxiedPlayer.uniqueId, + name, + target.name + ) { message, cancelMessageType -> + if (cancelMessageType == CancelType.MESSAGE) { + proxiedPlayer.sendMessage(Component.text(message).toBaseComponent()) + } else { + proxiedPlayer.disconnect(Component.text(message).toBaseComponent()) + } + event.isCancelled = true + } + } + + @EventHandler + fun on(event: ServerConnectedEvent) { + val proxiedPlayer = event.player + ProxyEventHandler.handleServerConnect(proxiedPlayer.uniqueId, event.server.info.name) { + proxiedPlayer.disconnect(Component.text("§cService does not exist.").toBaseComponent()) + } + } + + @EventHandler + fun on(event: ServerKickEvent) { + if (event.isCancelled) return + if (isWaterFallCauseLostConnection(event)) return + val kickReasonString: String = if (event.kickReasonComponent.isEmpty()) { + "" + } else { + event.kickReasonComponent[0].toLegacyText() + } + + val proxiedPlayer = event.player + val kickedServerName = event.kickedFrom.name + ProxyEventHandler.handleServerKick( + proxiedPlayer.getCloudPlayer(), + kickReasonString, + kickedServerName + ) { message, cancelMessageType -> + if (cancelMessageType == CancelType.MESSAGE) { + proxiedPlayer.sendMessage(Component.text(message).toBaseComponent()) + } else { + proxiedPlayer.disconnect(Component.text(message).toBaseComponent()) + } + } + + val fallback = CloudBungeePlugin.instance.lobbyConnector.getLobbyServer(proxiedPlayer, listOf(kickedServerName)) + if (fallback == null) { + proxiedPlayer.disconnect(Component.text(getNoFallbackServerFoundMessage()).toBaseComponent()) + return + } + + proxiedPlayer.sendMessage(*event.kickReasonComponent) + event.cancelServer = fallback + event.isCancelled = true + } + + private fun isWaterFallCauseLostConnection(event: ServerKickEvent): Boolean { + try { + val method = ServerKickEvent::class.java.getDeclaredMethod("getCause") + if (method.invoke(event).toString() == "LOST_CONNECTION") { + return true + } + return false + } catch (e: Exception) { + //the method does not exist -> not a waterfall fork + return false + } + } + + private fun getNoFallbackServerFoundMessage(): String { + return CloudAPI.instance.getLanguageManager().getMessage("ingame.no-fallback-server-found") + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/CloudPlayerDisconnectListener.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/CloudPlayerDisconnectListener.kt new file mode 100644 index 000000000..8a23f74b1 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/bungee/listener/CloudPlayerDisconnectListener.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.bungee.listener + +import eu.thesimplecloud.api.event.player.CloudPlayerDisconnectEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import net.md_5.bungee.api.ProxyServer + +class CloudPlayerDisconnectListener( + private val proxyServer: ProxyServer +) : IListener { + + @CloudEventHandler + fun handle(event: CloudPlayerDisconnectEvent) { + val playerUniqueId = event.playerUniqueId + this.proxyServer.players.forEach { + if (playerUniqueId == it.uniqueId) + it.disconnect("§cLogin from another session!") + } + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/CloudVelocityPlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/CloudVelocityPlugin.kt new file mode 100644 index 000000000..4fb4a810c --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/CloudVelocityPlugin.kt @@ -0,0 +1,164 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.velocity + +import com.google.inject.Inject +import com.velocitypowered.api.event.Subscribe +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent +import com.velocitypowered.api.event.proxy.ProxyShutdownEvent +import com.velocitypowered.api.plugin.Plugin +import com.velocitypowered.api.proxy.ProxyServer +import com.velocitypowered.api.proxy.server.ServerInfo +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.api.property.IProperty +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.servicegroup.grouptype.ICloudServerGroup +import eu.thesimplecloud.plugin.impl.player.CloudPlayerManagerVelocity +import eu.thesimplecloud.plugin.listener.CloudListener +import eu.thesimplecloud.plugin.proxy.ICloudProxyPlugin +import eu.thesimplecloud.plugin.proxy.ProxyEventHandler +import eu.thesimplecloud.plugin.proxy.velocity.commands.VelocityCommand +import eu.thesimplecloud.plugin.proxy.velocity.listener.CloudPlayerDisconnectListener +import eu.thesimplecloud.plugin.proxy.velocity.listener.VelocityListener +import eu.thesimplecloud.plugin.startup.CloudPlugin +import java.net.InetSocketAddress +import java.util.concurrent.TimeUnit +import kotlin.reflect.KClass + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 15.05.2020 + * Time: 21:11 + */ + +@Plugin(id = "simplecloud_plugin") +class CloudVelocityPlugin @Inject constructor(val proxyServer: ProxyServer) : ICloudProxyPlugin { + + companion object { + @JvmStatic + lateinit var instance: CloudVelocityPlugin + } + + @Volatile + lateinit var synchronizedIngameCommandsProperty: IProperty> + private set + val lobbyConnector = LobbyConnector() + + init { + instance = this + + CloudPlugin(this) + val synchronizedObjectPromise = + CloudAPI.instance.getGlobalPropertyHolder().requestProperty>("simplecloud-ingamecommands") + synchronizedObjectPromise.addResultListener { property -> + this.synchronizedIngameCommandsProperty = property + + this.synchronizedIngameCommandsProperty.getValue().forEach { + proxyServer.commandManager.unregister(it) + } + + this.synchronizedIngameCommandsProperty.getValue().forEach { + val commandManager = proxyServer.commandManager + commandManager.register(commandManager.metaBuilder(it).build(), VelocityCommand(it)) + } + }.throwFailure() + } + + @Subscribe + fun handleInit(event: ProxyInitializeEvent) { + CloudPlugin.instance.onEnable() + CloudAPI.instance.getCloudServiceManager().getAllCachedObjects().filter { it.isActive() } + .forEach { addServiceToProxy(it) } + CloudAPI.instance.getEventManager().registerListener(CloudPlugin.instance, CloudListener()) + proxyServer.eventManager.register(this, VelocityListener(this)) + + synchronizeOnlineCountTask() + runOfflinePlayerChecker() + + CloudAPI.instance.getEventManager() + .registerListener(CloudPlugin.instance, CloudPlayerDisconnectListener(this.proxyServer)) + } + + + @Subscribe + fun handleShutdown(event: ProxyShutdownEvent) { + CloudPlugin.instance.onDisable() + } + + override fun addServiceToProxy(cloudService: ICloudService) { + if (proxyServer.getServer(cloudService.getName()).isPresent) { + throw IllegalArgumentException("Service is already registered!") + } + if (cloudService.getServiceType().isProxy()) + return + val cloudServiceGroup = cloudService.getServiceGroup() + if ((cloudServiceGroup as ICloudServerGroup).getHiddenAtProxyGroups() + .contains(CloudPlugin.instance.getGroupName()) + ) + return + println("Registered service ${cloudService.getName()}") + val socketAddress = InetSocketAddress(cloudService.getHost(), cloudService.getPort()) + registerService(cloudService.getName(), socketAddress) + } + + private fun registerService(name: String, socketAddress: InetSocketAddress) { + val info = ServerInfo(name, socketAddress) + proxyServer.registerServer(info) + } + + override fun removeServiceFromProxy(cloudService: ICloudService) { + val registeredServer = proxyServer.getServer(cloudService.getName()).orElse(null) ?: return + + proxyServer.unregisterServer(registeredServer.serverInfo) + } + + private fun runOfflinePlayerChecker() { + proxyServer.scheduler.buildTask(this) { + val playersOnThisService = + CloudAPI.instance.getCloudPlayerManager().getAllCachedObjects() + val playersOffline = playersOnThisService.filter { proxyServer.getPlayer(it.getUniqueId()) == null } + playersOffline.forEach { ProxyEventHandler.handleDisconnect(it.getUniqueId(), it.getName()) } + }.delay(2L, TimeUnit.SECONDS).repeat(30L, TimeUnit.SECONDS).schedule() + } + + private fun synchronizeOnlineCountTask() { + proxyServer.scheduler.buildTask(this) { + val service = CloudPlugin.instance.thisService() + if (service.getOnlineCount() != proxyServer.playerCount) { + service.setOnlineCount(proxyServer.playerCount) + service.update() + } + }.repeat(30L, TimeUnit.SECONDS).schedule() + } + + override fun shutdown() { + proxyServer.commandManager.executeAsync(proxyServer.consoleCommandSource, "shutdown") + } + + override fun getCloudPlayerManagerClass(): KClass { + return CloudPlayerManagerVelocity::class + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/LobbyConnector.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/LobbyConnector.kt new file mode 100644 index 000000000..50c457ae4 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/LobbyConnector.kt @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.velocity + +import com.velocitypowered.api.proxy.Player +import com.velocitypowered.api.proxy.server.RegisteredServer +import eu.thesimplecloud.api.CloudAPI + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 15.05.2020 + * Time: 22:34 + */ +class LobbyConnector { + + fun getLobbyServer(player: Player, filterServices: List = emptyList()): RegisteredServer? { + val lobbyGroups = CloudAPI.instance.getCloudServiceGroupManager().getLobbyGroups() + val sortedLobbyGroups = lobbyGroups.sortedByDescending { it.getPriority() } + .filter { !it.isInMaintenance() || player.hasPermission("cloud.maintenance.join") } + val groups = sortedLobbyGroups.filter { it.getPermission() == null || player.hasPermission(it.getPermission()) } + val availableServices = + groups.map { group -> group.getAllServices().filter { it.isOnline() }.filter { !it.isFull() } }.flatten() + val serviceToConnectTo = + availableServices.filter { !filterServices.contains(it.getName()) }.minByOrNull { it.getOnlineCount() } + if (serviceToConnectTo == null) println("WARNING: Lobby server was null.") + return serviceToConnectTo?.let { CloudVelocityPlugin.instance.proxyServer.getServer(it.getName()).orElse(null) } + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/commands/VelocityCommand.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/commands/VelocityCommand.kt new file mode 100644 index 000000000..53766baa1 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/commands/VelocityCommand.kt @@ -0,0 +1,78 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.velocity.commands + +import com.velocitypowered.api.command.RawCommand +import com.velocitypowered.api.proxy.Player +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.player.CloudPlayerCommandExecuteEvent +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import eu.thesimplecloud.plugin.network.packets.PacketOutPlayerExecuteCommand +import eu.thesimplecloud.plugin.proxy.ProxyEventHandler +import eu.thesimplecloud.plugin.proxy.velocity.CloudVelocityPlugin +import eu.thesimplecloud.plugin.startup.CloudPlugin +import java.util.concurrent.CompletableFuture + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 19.05.2020 + * Time: 20:08 + */ +class VelocityCommand(private val commandStart: String) : RawCommand { + + override fun execute(invocation: RawCommand.Invocation) { + val player = invocation.source() as? Player ?: return + val command = "$commandStart " + invocation.arguments() + + if (CloudVelocityPlugin.instance.synchronizedIngameCommandsProperty.getValue() + .contains(commandStart.toLowerCase()) + ) { + CloudPlugin.instance.connectionToManager.sendUnitQuery( + PacketOutPlayerExecuteCommand( + player.getCloudPlayer(), + command + ) + ) + } + CloudAPI.instance.getEventManager() + .call(CloudPlayerCommandExecuteEvent(player.uniqueId, player.username, command)) + } + + override fun suggestAsync(invocation: RawCommand.Invocation?): CompletableFuture> { + val player = invocation?.source() as? Player ?: return CompletableFuture.completedFuture(mutableListOf()) + val rawCommand = "$commandStart " + invocation.arguments() + return getSuggestCompletableFuture(player, rawCommand) + } + + private fun getSuggestCompletableFuture( + player: Player, + rawCommand: String + ): CompletableFuture> { + val completableFuture = CompletableFuture>() + ProxyEventHandler.handleTabComplete(player.uniqueId, rawCommand) + .addResultListener { completableFuture.complete(it.toMutableList()) } + return completableFuture + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/CloudPlayerDisconnectListener.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/CloudPlayerDisconnectListener.kt new file mode 100644 index 000000000..ec85b790c --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/CloudPlayerDisconnectListener.kt @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.velocity.listener + +import com.velocitypowered.api.proxy.ProxyServer +import eu.thesimplecloud.api.event.player.CloudPlayerDisconnectEvent +import eu.thesimplecloud.api.eventapi.CloudEventHandler +import eu.thesimplecloud.api.eventapi.IListener +import net.kyori.adventure.text.Component + + +class CloudPlayerDisconnectListener( + private val proxyServer: ProxyServer +) : IListener { + + @CloudEventHandler + fun handle(event: CloudPlayerDisconnectEvent) { + val playerUniqueId = event.playerUniqueId + this.proxyServer.allPlayers.forEach { + if (playerUniqueId == it.uniqueId) + it.disconnect(Component.text("§cLogin from another session!")) + } + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/VelocityListener.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/VelocityListener.kt new file mode 100644 index 000000000..8749227e9 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/proxy/velocity/listener/VelocityListener.kt @@ -0,0 +1,182 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.proxy.velocity.listener + +import com.velocitypowered.api.event.PostOrder +import com.velocitypowered.api.event.ResultedEvent +import com.velocitypowered.api.event.Subscribe +import com.velocitypowered.api.event.connection.DisconnectEvent +import com.velocitypowered.api.event.connection.LoginEvent +import com.velocitypowered.api.event.connection.PostLoginEvent +import com.velocitypowered.api.event.player.KickedFromServerEvent +import com.velocitypowered.api.event.player.ServerConnectedEvent +import com.velocitypowered.api.event.player.ServerPreConnectEvent +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.connection.DefaultPlayerAddress +import eu.thesimplecloud.api.player.connection.DefaultPlayerConnection +import eu.thesimplecloud.plugin.extension.getCloudPlayer +import eu.thesimplecloud.plugin.proxy.CancelType +import eu.thesimplecloud.plugin.proxy.ProxyEventHandler +import eu.thesimplecloud.plugin.proxy.velocity.CloudVelocityPlugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.TextComponent +import java.util.* + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 15.05.2020 + * Time: 21:32 + */ +class VelocityListener(val plugin: CloudVelocityPlugin) { + + @Subscribe(order = PostOrder.FIRST) + fun handle(event: LoginEvent) { + val player = event.player + + val playerAddress = DefaultPlayerAddress(player.remoteAddress.hostString, player.remoteAddress.port) + val playerConnection = DefaultPlayerConnection( + playerAddress, + player.username, + player.uniqueId, + plugin.proxyServer.configuration.isOnlineMode, + player.protocolVersion.protocol + ) + + + ProxyEventHandler.handleLogin(playerConnection) { + event.result = ResultedEvent.ComponentResult.denied(Component.text(it)) + } + } + + @Subscribe + fun handle(event: PostLoginEvent) { + val player = event.player + + ProxyEventHandler.handlePostLogin(player.uniqueId, player.username) + + if (plugin.lobbyConnector.getLobbyServer(player) == null) { + event.player.disconnect(Component.text(getNoFallbackServerFoundMessage())) + } + } + + + @Subscribe + fun handle(event: DisconnectEvent) { + val player = event.player + + ProxyEventHandler.handleDisconnect(player.uniqueId, player.username) + } + + @Subscribe + fun handle(event: ServerPreConnectEvent) { + if (!event.result.isAllowed) return + val player = event.player + + val target = if (event.originalServer.serverInfo.name == "fallback") + plugin.lobbyConnector.getLobbyServer(player) + else + event.originalServer + if (target == null) { + event.player.disconnect(Component.text(getNoFallbackServerFoundMessage())) + return + } + val serverNameTo = target.serverInfo.name + event.result = + ServerPreConnectEvent.ServerResult.allowed(plugin.proxyServer.getServer(serverNameTo).orElse(null)) + + var serverNameFrom: String? = null + + val currentServer = player.currentServer + if (currentServer.isPresent) { + serverNameFrom = currentServer.get().serverInfo.name + } + + ProxyEventHandler.handleServerPreConnect( + player.uniqueId, + serverNameFrom, + serverNameTo + ) { message, cancelMessageType -> + if (cancelMessageType == CancelType.MESSAGE) { + player.sendMessage(Component.text(message)) + } else { + player.disconnect(Component.text(message)) + } + event.result = ServerPreConnectEvent.ServerResult.denied() + } + } + + @Subscribe + fun handle(event: ServerConnectedEvent) { + val player = event.player + ProxyEventHandler.handleServerConnect(player.uniqueId, event.server.serverInfo.name) { + player.disconnect(Component.text("§cService does not exist.")) + } + } + + @Subscribe + fun handle(event: KickedFromServerEvent) { + val kickReasonString: String + var kickReasonComponent = event.serverKickReason + if (!kickReasonComponent.isPresent) { + kickReasonString = "" + kickReasonComponent = Optional.of(Component.empty()) + } else { + val component = kickReasonComponent.get() + kickReasonString = if (component is TextComponent) { + component.content() + } else { + "§cYou were kicked from the server" + } + } + + val player = event.player + val kickedServerName = event.server.serverInfo.name + ProxyEventHandler.handleServerKick( + player.getCloudPlayer(), + kickReasonString, + kickedServerName + ) { message, cancelMessageType -> + if (cancelMessageType == CancelType.MESSAGE) { + player.sendMessage(Component.text(message)) + } else { + event.result = KickedFromServerEvent.DisconnectPlayer.create(kickReasonComponent.get()) + } + } + + val fallback = plugin.lobbyConnector.getLobbyServer(player, listOf(kickedServerName)) + if (fallback == null) { + event.result = KickedFromServerEvent.DisconnectPlayer.create( + Component.text(getNoFallbackServerFoundMessage()) + ) + return + } + + event.result = KickedFromServerEvent.RedirectPlayer.create(fallback) + } + + private fun getNoFallbackServerFoundMessage(): String { + return CloudAPI.instance.getLanguageManager().getMessage("ingame.no-fallback-server-found") + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/CloudSpigotPlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/CloudSpigotPlugin.kt new file mode 100644 index 000000000..934b95b00 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/CloudSpigotPlugin.kt @@ -0,0 +1,90 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.server + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.player.ICloudPlayerManager +import eu.thesimplecloud.plugin.impl.player.CloudPlayerManagerSpigot +import eu.thesimplecloud.plugin.listener.CloudListener +import eu.thesimplecloud.plugin.server.listener.ReloadCommandBlocker +import eu.thesimplecloud.plugin.server.listener.SpigotListener +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import org.bukkit.plugin.java.JavaPlugin +import org.bukkit.scheduler.BukkitRunnable +import kotlin.reflect.KClass + +class CloudSpigotPlugin : JavaPlugin(), ICloudServerPlugin { + + companion object { + @JvmStatic + lateinit var instance: CloudSpigotPlugin + } + + init { + instance = this + } + + override fun onLoad() { + CloudPlugin(this) + } + + override fun onEnable() { + CloudPlugin.instance.onEnable() + CloudAPI.instance.getEventManager().registerListener(CloudPlugin.instance, CloudListener()) + server.pluginManager.registerEvents(SpigotListener(), this) + server.pluginManager.registerEvents(ReloadCommandBlocker(), this) + synchronizeOnlineCountTask() + } + + override fun onBeforeFirstUpdate() { + //Service will be updated after this function was called + val motd = Bukkit.getServer().motd + CloudPlugin.instance.thisService().setMOTD(motd) + } + + override fun onDisable() { + CloudPlugin.instance.onDisable() + } + + override fun shutdown() { + Bukkit.getServer().shutdown() + } + + override fun getCloudPlayerManagerClass(): KClass { + return CloudPlayerManagerSpigot::class + } + + private fun synchronizeOnlineCountTask() { + object : BukkitRunnable() { + override fun run() { + val service = CloudPlugin.instance.thisService() + if (service.getOnlineCount() != server.onlinePlayers.size) { + service.setOnlineCount(server.onlinePlayers.size) + service.update() + } + } + }.runTaskTimerAsynchronously(this, 20 * 30, 20 * 30) + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/ICloudServerPlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/ICloudServerPlugin.kt new file mode 100644 index 000000000..1df65d043 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/ICloudServerPlugin.kt @@ -0,0 +1,28 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.server + +import eu.thesimplecloud.plugin.ICloudServicePlugin + +interface ICloudServerPlugin : ICloudServicePlugin { +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/ReloadCommandBlocker.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/ReloadCommandBlocker.kt new file mode 100644 index 000000000..1608fa72e --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/ReloadCommandBlocker.kt @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.server.listener + +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerCommandPreprocessEvent +import org.bukkit.event.server.ServerCommandEvent + +/** + * Created by IntelliJ IDEA. + * Date: 24.12.2020 + * Time: 10:50 + * @author Frederick Baier + */ +class ReloadCommandBlocker : Listener { + + @EventHandler(priority = EventPriority.HIGHEST) + fun handle(event: PlayerCommandPreprocessEvent) { + val message = event.message + val player = event.player + if (isCommandBlocked("/$message")) { + if (player.hasPermission("bukkit.command.reload")) { + event.isCancelled = true + player.sendMessage("§cCloud-Servers cannot be reloaded") + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun handle(event: ServerCommandEvent) { + if (isCommandBlocked(event.command)) { + event.isCancelled = true + } + } + + private fun isCommandBlocked(message: String): Boolean { + return message.equals("rl", true) || + message.equals("reload", true) || + message.equals("rl confirm", true) || + message.equals("reload confirm", true) + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/SpigotListener.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/SpigotListener.kt new file mode 100644 index 000000000..a8558cb85 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/server/listener/SpigotListener.kt @@ -0,0 +1,100 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.server.listener + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.event.player.CloudPlayerMessageEvent +import eu.thesimplecloud.plugin.startup.CloudPlugin +import org.bukkit.Bukkit +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.player.AsyncPlayerChatEvent +import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerKickEvent +import org.bukkit.event.player.PlayerLoginEvent +import org.bukkit.event.player.PlayerQuitEvent + +class SpigotListener : Listener { + + private val UNKNOWN_ADRESS = "§cYou are connected from an unknown address!" + private val NOT_REGISTERED = "§cYou are not registered on the network!" + + @EventHandler + fun on(event: PlayerLoginEvent) { + val player = event.player + + val hostAddress = event.realAddress.hostAddress + if (hostAddress != "127.0.0.1" && !CloudAPI.instance.getWrapperManager().getAllCachedObjects() + .any { it.getHost() == hostAddress } + ) { + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, UNKNOWN_ADRESS) + return + } + + if (CloudAPI.instance.getCloudPlayerManager().getCachedCloudPlayer(player.uniqueId) == null) { + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, NOT_REGISTERED) + } + } + + @EventHandler(priority = EventPriority.LOWEST) + fun handleAsyncChat(event: AsyncPlayerChatEvent) { + val cloudPlayer = CloudAPI.instance.getCloudPlayerManager() + .getCachedCloudPlayer(event.player.uniqueId) ?: return + val event = CloudPlayerMessageEvent(cloudPlayer, event.message, CloudPlugin.instance.thisService()) + CloudAPI.instance.getEventManager().call(event) + } + + @EventHandler + fun onJoin(event: PlayerJoinEvent) { + updateCurrentOnlineCountTo(Bukkit.getOnlinePlayers().size) + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun on(event: PlayerQuitEvent) { + onPlayerDisconnected(event.player) + } + + @EventHandler(priority = EventPriority.HIGHEST) + fun on(event: PlayerKickEvent) { + onPlayerDisconnected(event.player) + } + + private fun onPlayerDisconnected(player: Player) { + val playerManager = CloudAPI.instance.getCloudPlayerManager() + val cloudPlayer = playerManager.getCachedCloudPlayer(player.uniqueId) + + if (cloudPlayer != null && !cloudPlayer.isUpdatesEnabled()) { + playerManager.delete(cloudPlayer) + } + updateCurrentOnlineCountTo(Bukkit.getOnlinePlayers().size - 1) + } + + private fun updateCurrentOnlineCountTo(count: Int) { + val thisService = CloudPlugin.instance.thisService() + thisService.setOnlineCount(count) + thisService.update() + } + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/CloudPlugin.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/CloudPlugin.kt new file mode 100644 index 000000000..28a668296 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/CloudPlugin.kt @@ -0,0 +1,155 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.startup + +import eu.thesimplecloud.api.CloudAPI +import eu.thesimplecloud.api.client.NetworkComponentType +import eu.thesimplecloud.api.external.ICloudModule +import eu.thesimplecloud.api.service.ICloudService +import eu.thesimplecloud.api.service.ServiceState +import eu.thesimplecloud.client.packets.PacketOutCloudClientLogin +import eu.thesimplecloud.clientserverapi.client.INettyClient +import eu.thesimplecloud.clientserverapi.client.NettyClient +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.jsonlib.JsonLib +import eu.thesimplecloud.plugin.ICloudServicePlugin +import eu.thesimplecloud.plugin.impl.CloudAPIImpl +import java.io.File +import kotlin.concurrent.thread + + +class CloudPlugin(val cloudServicePlugin: ICloudServicePlugin) : ICloudModule { + + companion object { + @JvmStatic + lateinit var instance: CloudPlugin + private set + } + + @Volatile + private var thisService: ICloudService? = null + + @Volatile + lateinit var communicationClient: INettyClient + private set + + @Volatile + lateinit var connectionToManager: IConnection + private set + + @Volatile + lateinit var thisServiceName: String + private set + + @Volatile + private var nettyThread: Thread + + init { + println("<---------- Starting SimpleCloud-Plugin ---------->") + instance = this + if (!loadConfig()) + cloudServicePlugin.shutdown() + println("<---------- Service-Name: $thisServiceName ---------->") + CloudAPIImpl(cloudServicePlugin.getCloudPlayerManagerClass().java.newInstance()) + + this.communicationClient.setPacketSearchClassLoader(this::class.java.classLoader) + this.communicationClient.addPacketsByPackage("eu.thesimplecloud.plugin.network.packets") + this.communicationClient.addPacketsByPackage("eu.thesimplecloud.client.packets") + this.communicationClient.addPacketsByPackage("eu.thesimplecloud.api.network.packets") + + nettyThread = thread(true, isDaemon = false, contextClassLoader = this::class.java.classLoader) { + println("<------Starting cloud client----------->") + this.communicationClient.start().then { + println("<-------- Connection is now set up -------->") + this.connectionToManager.sendUnitQuery( + PacketOutCloudClientLogin( + NetworkComponentType.SERVICE, + thisServiceName + ), 10000 + ) + .addFailureListener { throw it } + }.addFailureListener { println("<-------- Failed to connect to server -------->") } + .addFailureListener { throw it } + } + + UsedMemoryUpdater().startUpdater() + + Runtime.getRuntime().addShutdownHook(Thread { + try { + this.communicationClient.shutdown() + } catch (e: Exception) { + } + + }) + } + + /** + * Returns whether the config was loaded successful + */ + private fun loadConfig(): Boolean { + val jsonLib = JsonLib.fromJsonFile(File("SIMPLE-CLOUD.json")) ?: return false + thisServiceName = jsonLib.getString("serviceName") ?: return false + val host = jsonLib.getString("managerHost") ?: return false + val port = jsonLib.getInt("managerPort") ?: return false + this.communicationClient = NettyClient(host, port, ConnectionHandlerImpl()) + this.connectionToManager = this.communicationClient.getConnection() + return true + } + + @Synchronized + fun thisService(): ICloudService { + if (this.thisService == null) this.thisService = + CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(thisServiceName) + while (this.thisService == null || !this.thisService!!.isAuthenticated()) { + Thread.sleep(10) + if (this.thisService == null) + this.thisService = CloudAPI.instance.getCloudServiceManager().getCloudServiceByName(thisServiceName) + } + return this.thisService!! + } + + override fun onEnable() { + if (thisService().getServiceGroup() + .isStateUpdatingEnabled() && thisService().getState() == ServiceState.STARTING + ) { + thisService().setState(ServiceState.VISIBLE) + cloudServicePlugin.onBeforeFirstUpdate() + updateThisService() + } + } + + override fun onDisable() { + } + + @Synchronized + fun updateThisService() { + thisService().update() + } + + fun getGroupName(): String { + val array = this.thisServiceName.split("-".toRegex()) + return array.dropLast(1).joinToString("-") + } + + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/ConnectionHandlerImpl.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/ConnectionHandlerImpl.kt new file mode 100644 index 000000000..d1bdf1db6 --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/ConnectionHandlerImpl.kt @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.startup + +import eu.thesimplecloud.clientserverapi.lib.connection.IConnection +import eu.thesimplecloud.clientserverapi.lib.handler.IConnectionHandler + +class ConnectionHandlerImpl : IConnectionHandler { + override fun onConnectionActive(connection: IConnection) { + } + + override fun onConnectionInactive(connection: IConnection) { + } + + override fun onFailure(connection: IConnection, ex: Throwable) { + println("[SimpleCloud] an error occurred:") + ex.printStackTrace() + } +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/UsedMemoryUpdater.kt b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/UsedMemoryUpdater.kt new file mode 100644 index 000000000..846e0da7d --- /dev/null +++ b/simplecloud-plugin/src/main/kotlin/eu/thesimplecloud/plugin/startup/UsedMemoryUpdater.kt @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.plugin.startup + +import eu.thesimplecloud.api.service.impl.DefaultCloudService +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +/** + * Created by IntelliJ IDEA. + * Date: 26.09.2020 + * Time: 13:33 + * @author Frederick Baier + */ +class UsedMemoryUpdater { + + fun startUpdater() { + GlobalScope.launch { + val thisService = CloudPlugin.instance.thisService() as DefaultCloudService + while (true) { + delay(2000) + val usedMemory = getUsedMemoryInMB(Runtime.getRuntime()) + if (thisService.getUsedMemory() != usedMemory) { + thisService.setUsedMemory(usedMemory) + thisService.update() + } + } + } + } + + private fun getUsedMemoryInMB(runtime: Runtime): Int { + val totalMemory = runtime.totalMemory() + val freeMemory = runtime.freeMemory() + val usedMemoryInMB = (totalMemory - freeMemory).toDouble() / (1024 * 1024).toDouble() + return usedMemoryInMB.toInt() + } + + +} \ No newline at end of file diff --git a/simplecloud-plugin/src/main/resources/bungee.yml b/simplecloud-plugin/src/main/resources/bungee.yml new file mode 100644 index 000000000..2cce36e9f --- /dev/null +++ b/simplecloud-plugin/src/main/resources/bungee.yml @@ -0,0 +1,5 @@ +name: SimpleCloud-Plugin +version: 1.0 +author: Wetterbericht + +main: eu.thesimplecloud.plugin.proxy.bungee.CloudBungeePlugin \ No newline at end of file diff --git a/simplecloud-plugin/src/main/resources/plugin.yml b/simplecloud-plugin/src/main/resources/plugin.yml new file mode 100644 index 000000000..ed978a8b7 --- /dev/null +++ b/simplecloud-plugin/src/main/resources/plugin.yml @@ -0,0 +1,9 @@ +name: SimpleCloud-Plugin +version: 1.0 +author: Wetterbericht + +main: eu.thesimplecloud.plugin.server.CloudSpigotPlugin + +api-version: 1.13 + +commands: diff --git a/simplecloud-plugin/src/main/resources/velocity-plugin.json b/simplecloud-plugin/src/main/resources/velocity-plugin.json new file mode 100644 index 000000000..dccdaa2fd --- /dev/null +++ b/simplecloud-plugin/src/main/resources/velocity-plugin.json @@ -0,0 +1,9 @@ +{ + "id": "simplecloud_plugin", + "name": "SimpleCloud-Plugin", + "version": "1.0", + "authors": [ + "Fllip" + ], + "main": "eu.thesimplecloud.plugin.proxy.velocity.CloudVelocityPlugin" +} \ No newline at end of file diff --git a/simplecloud-runner/build.gradle b/simplecloud-runner/build.gradle new file mode 100644 index 000000000..98c3e4934 --- /dev/null +++ b/simplecloud-runner/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'java' + id 'org.jetbrains.kotlin.jvm' +} + +repositories { + mavenCentral() +} + +dependencies { + api "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + testApi group: 'junit', name: 'junit', version: '4.12' + api(group: 'eu.thesimplecloud.jsonlib', name: 'json-lib', version: "1.0.8") +} + +shadowJar { + archiveFileName.set("runner.jar") +} + +compileKotlin { + kotlinOptions.jvmTarget = 1.8 +} + +jar { + dependsOn ':simplecloud-dependency-loader:jar' + manifest { + attributes( + 'Main-Class': 'eu.thesimplecloud.runner.RunnerClassLoaderInitMainKt', + 'Implementation-Version': project.version, + ) + } +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoader.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoader.kt new file mode 100644 index 000000000..a1f257732 --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoader.kt @@ -0,0 +1,34 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner + +import java.net.URL +import java.net.URLClassLoader + +/** + * Created by IntelliJ IDEA. + * Date: 29.08.2020 + * Time: 08:03 + * @author Frederick Baier + */ +class RunnerClassLoader(urls: Array) : URLClassLoader(urls, getSystemClassLoader()) diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoaderInitMain.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoaderInitMain.kt new file mode 100644 index 000000000..46feb1cd0 --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerClassLoaderInitMain.kt @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner + +import eu.thesimplecloud.runner.dependency.AdvancedCloudDependency +import eu.thesimplecloud.runner.dependency.DependencyLoaderStartup +import java.io.File +import java.net.URL +import java.net.URLClassLoader + +/** + * Created by IntelliJ IDEA. + * Date: 29.08.2020 + * Time: 07:46 + * @author Frederick Baier + */ + +private val copiedDependencyLoaderFile = File("storage", "dependency-loader.jar") +private val copiedSimpleCloudPluginFile = File("storage/pluginJars", "SimpleCloud-Plugin-${getCloudVersion()}.jar") + +fun main(args: Array) { + val version = getCloudVersion() + if (!version.contains("SNAPSHOT")) { + if (!copiedDependencyLoaderFile.exists()) + downloadJarFromDependency("simplecloud-dependency-loader", copiedDependencyLoaderFile) + if (!copiedSimpleCloudPluginFile.exists()) + downloadJarFromDependency("simplecloud-plugin", copiedSimpleCloudPluginFile) + } + + val dependencyLoaderStartup = DependencyLoaderStartup() + + val loadedDependencyFiles = dependencyLoaderStartup.loadDependenciesToResolveDependencies() + val loadedDependencyUrls = loadedDependencyFiles.map { it.toURI().toURL() }.toTypedArray() + + val classLoader = initClassLoader(loadedDependencyUrls) + Thread.currentThread().contextClassLoader = classLoader + + executeDependencyLoaderMain(classLoader, args) +} + +private fun getCloudVersion(): String { + return RunnerClassLoader::class.java.`package`.implementationVersion +} + +private fun downloadJarFromDependency(artifactId: String, file: File) { + val dependency = AdvancedCloudDependency("eu.thesimplecloud.simplecloud", artifactId, getCloudVersion()) + dependency.download("https://repo.thesimplecloud.eu/artifactory/gradle-release-local/", file) +} + +private fun executeDependencyLoaderMain(classLoader: URLClassLoader, args: Array) { + val loadedClass = classLoader.loadClass("eu.thesimplecloud.loader.dependency.DependencyLoaderMainKt") + val method = loadedClass.getMethod("main", Array::class.java) + method.invoke(null, args) +} + +private fun initClassLoader(loadedDependencies: Array): URLClassLoader { + return RunnerClassLoader( + arrayOf(copiedDependencyLoaderFile.toURI().toURL(), *loadedDependencies) + ) +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerFileProvider.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerFileProvider.kt new file mode 100644 index 000000000..f0493c1eb --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/RunnerFileProvider.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner + +import java.io.File + +/** + * Created by IntelliJ IDEA. + * Date: 29.08.2020 + * Time: 13:28 + * @author Frederick Baier + */ +object RunnerFileProvider { + + val RUNNER_FILE = File(this::class.java.protectionDomain.codeSource.location.toURI()) + +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/AdvancedCloudDependency.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/AdvancedCloudDependency.kt new file mode 100644 index 000000000..c7e3199cb --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/AdvancedCloudDependency.kt @@ -0,0 +1,125 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner.dependency + +import eu.thesimplecloud.runner.utils.Downloader +import eu.thesimplecloud.runner.utils.WebContentLoader +import java.io.File +import java.io.IOException + +/** + * Created by IntelliJ IDEA. + * Date: 04.09.2020 + * Time: 16:45 + * @author Frederick Baier + */ +class AdvancedCloudDependency(groupId: String, artifactId: String, version: String) : + CloudDependency(groupId, artifactId, version) { + + private fun getDownloadURL(repoUrl: String): String { + return getUrlWithoutExtension(repoUrl) + ".jar" + } + + fun getDownloadedFile(): File { + return File(DEPENDENCIES_DIR, "${getName()}.jar") + } + + fun getDownloadedInfoFile(): File { + return File(DEPENDENCY_INFO_DIR, "${getName()}.info") + } + + fun existInRepo(repoUrl: String): Boolean { + return WebContentLoader().loadContent(getDownloadURL(repoUrl)) != null + } + + @Throws(IOException::class) + fun download(repoUrl: String) { + return download(repoUrl, getDownloadedFile()) + } + + @Throws(IOException::class) + fun download(repoUrl: String, downloadFile: File) { + Downloader().userAgentDownload(this.getDownloadURL(repoUrl), downloadFile) + } + + private fun getMainURL(repoUrl: String): String { + return repoUrl + groupId.replace("\\.".toRegex(), "/") + "/" + artifactId + "/" + } + + private fun getUrlWithoutExtension(repoUrl: String): String { + return getMainURL(repoUrl) + version + "/" + artifactId + "-" + version + } + + fun getDependencyWithNewerVersion(other: AdvancedCloudDependency): AdvancedCloudDependency { + val dependencyVersion = getVersionStringAsIntArray(this.version) + val otherDependencyVersion = getVersionStringAsIntArray(other.version) + if (dependencyVersion[0] > otherDependencyVersion[0]) return this + if (otherDependencyVersion[0] > dependencyVersion[0]) return other + + if (dependencyVersion[1] > otherDependencyVersion[1]) return this + if (otherDependencyVersion[1] > dependencyVersion[1]) return other + + if (dependencyVersion[2] > otherDependencyVersion[2]) return this + if (otherDependencyVersion[2] > dependencyVersion[2]) return other + + return this + } + + private fun getVersionStringAsIntArray(version: String): Array { + val versionParts = version.split(".") + val major = versionParts[0].toInt() + val minor = parseVersionPart(versionParts.getOrNull(1)) + val patch = parseVersionPart(versionParts.getOrNull(2)) + return arrayOf(major, minor, patch) + } + + private fun parseVersionPart(part: String?): Int { + if (part == null) return 0 + val charArray = part.toCharArray() + val numbers = mutableListOf() + for (char in charArray) { + if (char.isDigit()) { + numbers.add(char.toInt()) + } else { + break + } + } + if (numbers.isEmpty()) return 0 + return numbers.joinToString("").toInt() + } + + + companion object { + + val DEPENDENCIES_DIR = File("dependencies/") + + val DEPENDENCY_INFO_DIR = File("dependencies/info/") + + + fun fromCoords(coords: String): AdvancedCloudDependency { + val split = coords.split(":") + require(split.size == 3) + return AdvancedCloudDependency(split[0], split[1], split[2]) + } + } +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/CloudDependency.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/CloudDependency.kt new file mode 100644 index 000000000..254fd8d23 --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/CloudDependency.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner.dependency + +open class CloudDependency(val groupId: String, val artifactId: String, val version: String) { + + fun getName() = "$artifactId-$version" + + override fun equals(other: Any?): Boolean { + if (other == null) return false + if (other !is CloudDependency) return false + return this.groupId == other.groupId && this.artifactId == other.artifactId && this.version == other.version + } + + override fun hashCode(): Int { + var result = groupId.hashCode() + result = 31 * result + artifactId.hashCode() + result = 31 * result + version.hashCode() + return result + } + +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/DependencyLoaderStartup.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/DependencyLoaderStartup.kt new file mode 100644 index 000000000..ee512c2ee --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/DependencyLoaderStartup.kt @@ -0,0 +1,76 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner.dependency + +import eu.thesimplecloud.jsonlib.JsonLib +import java.io.File + +/** + * Created by IntelliJ IDEA. + * User: Philipp.Eistrach + * Date: 11.06.2021 + * Time: 21:02 + */ +class DependencyLoaderStartup { + + fun loadDependenciesToResolveDependencies(): Set { + println("Loading dependencies...") + val downloader = SimpleDependencyDownloader(listOf("https://repo.maven.apache.org/maven2/")) + + val dependencies = listOf( + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-impl:1.1.0"), + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-api:1.1.0"), + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-spi:1.1.0"), + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-util:1.1.0"), + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-connector-basic:1.1.0"), + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-transport-file:1.1.0"), + AdvancedCloudDependency.fromCoords("org.eclipse.aether:aether-transport-http:1.1.0"), + AdvancedCloudDependency.fromCoords("org.apache.httpcomponents:httpclient:4.3.5"), + AdvancedCloudDependency.fromCoords("org.apache.httpcomponents:httpcore:4.3.2"), + AdvancedCloudDependency.fromCoords("commons-logging:commons-logging:1.1.3"), + AdvancedCloudDependency.fromCoords("commons-codec:commons-codec:1.6"), + AdvancedCloudDependency.fromCoords("org.apache.maven:maven-aether-provider:3.3.9"), + AdvancedCloudDependency.fromCoords("org.apache.maven:maven-model:3.3.9"), + AdvancedCloudDependency.fromCoords("org.codehaus.plexus:plexus-utils:3.0.22"), + AdvancedCloudDependency.fromCoords("org.apache.commons:commons-lang3:3.4"), + AdvancedCloudDependency.fromCoords("org.apache.maven:maven-model-builder:3.3.9"), + AdvancedCloudDependency.fromCoords("org.codehaus.plexus:plexus-interpolation:1.21"), + AdvancedCloudDependency.fromCoords("org.codehaus.plexus:plexus-component-annotations:1.6"), + AdvancedCloudDependency.fromCoords("org.apache.maven:maven-artifact:3.3.9"), + AdvancedCloudDependency.fromCoords("org.apache.maven:maven-builder-support:3.3.9"), + AdvancedCloudDependency.fromCoords("com.google.guava:guava:21.0"), + AdvancedCloudDependency.fromCoords("org.apache.maven:maven-repository-metadata:3.3.9"), + ) + + dependencies.forEach { downloader.downloadOnlyJar(it) } + dependencies.forEach { createEmptyInfoFile(it) } + + return dependencies.map { it.getDownloadedFile() }.toSet() + } + + private fun createEmptyInfoFile(dependency: AdvancedCloudDependency) { + //creates an empty info file for the specified dependency to avoid bugs when the dependency is loaded again by another dependency + JsonLib.fromObject(emptyArray()).saveAsFile(dependency.getDownloadedInfoFile()) + } + +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/SimpleDependencyDownloader.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/SimpleDependencyDownloader.kt new file mode 100644 index 000000000..ea81238d6 --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/dependency/SimpleDependencyDownloader.kt @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner.dependency + + +/** + * Created by IntelliJ IDEA. + * Date: 31.08.2020 + * Time: 15:39 + * @author Frederick Baier + */ +open class SimpleDependencyDownloader(protected val repositories: List) { + + fun downloadOnlyJar(dependency: AdvancedCloudDependency) { + if (dependency.getDownloadedFile().exists()) return + this.repositories.forEach { repoUrl -> + if (dependency.existInRepo(repoUrl)) { + dependency.download(repoUrl) + } + } + } + +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/Downloader.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/Downloader.kt new file mode 100644 index 000000000..b79452e0b --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/Downloader.kt @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner.utils + +import java.io.File +import java.io.IOException +import java.net.URL +import java.nio.file.Files +import java.nio.file.Paths +import java.nio.file.StandardCopyOption + +class Downloader { + + @Throws(IOException::class) + fun userAgentDownload(url: String, file: File) { + file.parentFile?.mkdirs() + val urlConnection = URL(url).openConnection() + urlConnection.setRequestProperty( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0" + ) + urlConnection.connect() + Files.copy(urlConnection.getInputStream(), Paths.get(file.absolutePath), StandardCopyOption.REPLACE_EXISTING) + } + +} \ No newline at end of file diff --git a/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/WebContentLoader.kt b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/WebContentLoader.kt new file mode 100644 index 000000000..3e49377e2 --- /dev/null +++ b/simplecloud-runner/src/main/kotlin/eu/thesimplecloud/runner/utils/WebContentLoader.kt @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.runner.utils + +import java.io.BufferedReader +import java.io.InputStreamReader +import java.net.HttpURLConnection +import java.net.URL + +class WebContentLoader { + + fun loadContent(urlstring: String): String? { + return runCatching { + val url = URL(urlstring) + val connection = url.openConnection() as HttpURLConnection + connection.requestMethod = "GET" + connection.setRequestProperty( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0" + ) + connection.connect() + val responseCode = connection.responseCode + if (responseCode != 200) { + connection.disconnect() + return@runCatching null + } + val reader = BufferedReader(InputStreamReader(connection.inputStream)) + + // write the output to stdout + var line = "" + reader.lines().forEach { line += it } + reader.close() + connection.disconnect() + return@runCatching line + }.getOrNull() + } + +} \ No newline at end of file diff --git a/simplecloud-updater/build.gradle b/simplecloud-updater/build.gradle new file mode 100644 index 000000000..b2b99dfa2 --- /dev/null +++ b/simplecloud-updater/build.gradle @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (C) 2020 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +jar { + manifest { + attributes( + 'Main-Class': 'eu.thesimplecloud.updater.UpdaterMain' + ) + } +} \ No newline at end of file diff --git a/simplecloud-updater/src/main/java/eu/thesimplecloud/updater/UpdaterMain.java b/simplecloud-updater/src/main/java/eu/thesimplecloud/updater/UpdaterMain.java new file mode 100644 index 000000000..5ce79cc7d --- /dev/null +++ b/simplecloud-updater/src/main/java/eu/thesimplecloud/updater/UpdaterMain.java @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (C) 2020-2022 The SimpleCloud authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eu.thesimplecloud.updater; + + +import java.io.*; + +public class UpdaterMain { + + /** + * First argument: delay to wait before replacing + * Second argument: File to be replaced + * Third argument: File to replace with + * Fourth argument: Launcher file to delete + */ + public static void main(String[] args) { + try { + + long timeToWait = Long.parseLong(args[0]); + File fileToBeReplaced = new File(args[1]); + File fileToReplaceWith = new File(args[2]); + File launcherFileToDelete = new File(args[3]); + Thread.sleep(timeToWait); + while (fileToBeReplaced.exists()) { + try { + fileToBeReplaced.delete(); + } catch (Exception ex) { + Thread.sleep(100); + } + } + copyFileUsingStream(fileToReplaceWith, fileToBeReplaced); + fileToReplaceWith.delete(); + launcherFileToDelete.delete(); + + String filePathToDependencyLoader = getFilePathToDependencyLoader(args); + if (filePathToDependencyLoader != null) { + new File(filePathToDependencyLoader).delete(); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private static String getFilePathToDependencyLoader(String[] args) { + try { + return args[4]; + } catch (Exception e) { + return null; + } + } + + private static void copyFileUsingStream(File source, File dest) throws IOException { + try (InputStream is = new FileInputStream(source); OutputStream os = new FileOutputStream(dest)) { + byte[] buffer = new byte[1024]; + int length; + while ((length = is.read(buffer)) > 0) { + os.write(buffer, 0, length); + } + } + } + +} diff --git a/start-files/start.bat b/start-files/start.bat new file mode 100644 index 000000000..f6b0003b3 --- /dev/null +++ b/start-files/start.bat @@ -0,0 +1 @@ +java -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -Xmx512m -Xms256m -jar runner.jar \ No newline at end of file diff --git a/start-files/start.sh b/start-files/start.sh new file mode 100644 index 000000000..712bd923f --- /dev/null +++ b/start-files/start.sh @@ -0,0 +1,23 @@ +# +# MIT License +# +# Copyright (C) 2020-2022 The SimpleCloud authors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +# documentation files (the "Software"), to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +screen -S SimpleCloud java -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -Xmx512m -Xms256m -jar runner.jar \ No newline at end of file