Arakne /
Araknemu
| 1 | /* |
||
| 2 | * This file is part of Araknemu. |
||
| 3 | * |
||
| 4 | * Araknemu is free software: you can redistribute it and/or modify |
||
| 5 | * it under the terms of the GNU Lesser General Public License as published by |
||
| 6 | * the Free Software Foundation, either version 3 of the License, or |
||
| 7 | * (at your option) any later version. |
||
| 8 | * |
||
| 9 | * Araknemu is distributed in the hope that it will be useful, |
||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 12 | * GNU Lesser General Public License for more details. |
||
| 13 | * |
||
| 14 | * You should have received a copy of the GNU Lesser General Public License |
||
| 15 | * along with Araknemu. If not, see <https://www.gnu.org/licenses/>. |
||
| 16 | * |
||
| 17 | * Copyright (c) 2017-2020 Vincent Quatrevieux |
||
| 18 | */ |
||
| 19 | |||
| 20 | package fr.quatrevieux.araknemu; |
||
| 21 | |||
| 22 | import fr.quatrevieux.araknemu.core.BootException; |
||
| 23 | import fr.quatrevieux.araknemu.core.Service; |
||
| 24 | import fr.quatrevieux.araknemu.core.config.Configuration; |
||
| 25 | import fr.quatrevieux.araknemu.core.config.ConfigurationLoader; |
||
| 26 | import fr.quatrevieux.araknemu.core.dbal.DatabaseConfiguration; |
||
| 27 | import fr.quatrevieux.araknemu.core.dbal.DatabaseHandler; |
||
| 28 | import fr.quatrevieux.araknemu.core.dbal.DefaultDatabaseHandler; |
||
| 29 | import fr.quatrevieux.araknemu.core.di.Container; |
||
| 30 | import fr.quatrevieux.araknemu.core.di.ItemPoolContainer; |
||
| 31 | import fr.quatrevieux.araknemu.data.living.repository.implementation.sql.SqlLivingRepositoriesModule; |
||
| 32 | import fr.quatrevieux.araknemu.data.world.repository.implementation.sql.SqlWorldRepositoriesModule; |
||
| 33 | import fr.quatrevieux.araknemu.game.GameModule; |
||
| 34 | import fr.quatrevieux.araknemu.game.GameService; |
||
| 35 | import fr.quatrevieux.araknemu.game.admin.AdminModule; |
||
| 36 | import fr.quatrevieux.araknemu.game.connector.LocalModule; |
||
| 37 | import fr.quatrevieux.araknemu.realm.RealmModule; |
||
| 38 | import fr.quatrevieux.araknemu.realm.RealmService; |
||
| 39 | import org.apache.logging.log4j.LogManager; |
||
| 40 | import org.apache.logging.log4j.Logger; |
||
| 41 | import org.checkerframework.checker.nullness.qual.EnsuresNonNull; |
||
| 42 | import org.checkerframework.checker.nullness.qual.MonotonicNonNull; |
||
| 43 | import org.checkerframework.checker.nullness.qual.Nullable; |
||
| 44 | |||
| 45 | import java.sql.SQLException; |
||
| 46 | import java.time.Instant; |
||
| 47 | import java.util.ArrayList; |
||
| 48 | import java.util.List; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Startup class |
||
| 52 | */ |
||
| 53 | public class Araknemu { |
||
| 54 | /** |
||
| 55 | * Get the current version of the server (retrieved from pom.xml) |
||
| 56 | */ |
||
| 57 | 1 | public static final @Nullable String VERSION = Araknemu.class.getPackage() != null ? Araknemu.class.getPackage().getImplementationVersion() : null; |
|
| 58 | public static final String NAME = "Araknemu"; |
||
| 59 | public static final String YEAR = "2017-2021"; |
||
| 60 | public static final String AUTHOR = "Vincent Quatrevieux"; |
||
| 61 | |||
| 62 | 1 | private final Logger logger = LogManager.getLogger(getClass()); |
|
| 63 | |||
| 64 | private final Configuration configuration; |
||
| 65 | private final DatabaseHandler database; |
||
| 66 | 1 | private final List<Service> services = new ArrayList<>(); |
|
| 67 | 1 | private boolean started = false; |
|
| 68 | private @MonotonicNonNull Instant startDate; |
||
| 69 | |||
| 70 | 1 | public Araknemu(Configuration configuration, DatabaseHandler database) { |
|
| 71 | 1 | this.configuration = configuration; |
|
| 72 | 1 | this.database = database; |
|
| 73 | 1 | } |
|
| 74 | |||
| 75 | /** |
||
| 76 | * Boot all services |
||
| 77 | */ |
||
| 78 | @EnsuresNonNull("startDate") |
||
| 79 | public void boot() throws BootException { |
||
| 80 | 1 | System.out.println(NAME + " Copyright (c) " + YEAR + " " + AUTHOR); |
|
| 81 | 1 | System.out.println("This program comes with ABSOLUTELY NO WARRANTY."); |
|
| 82 | 1 | System.out.println("This is free software, and you are welcome to redistribute it under certain conditions."); |
|
| 83 | |||
| 84 | 1 | logger.info("Starting {} v{}", NAME, VERSION != null ? VERSION : "DEV"); |
|
| 85 | 1 | logger.info("Booting services"); |
|
| 86 | |||
| 87 | 1 | for (Service service : services) { |
|
| 88 | service.boot(); |
||
| 89 | } |
||
| 90 | |||
| 91 | 1 | logger.info("Running garbage collector"); |
|
| 92 | 1 | System.gc(); |
|
|
0 ignored issues
–
show
Comprehensibility
introduced
by
Loading history...
|
|||
| 93 | |||
| 94 | 1 | started = true; |
|
| 95 | 1 | startDate = Instant.now(); |
|
| 96 | 1 | logger.info("Araknemu started"); |
|
| 97 | 1 | } |
|
| 98 | |||
| 99 | /** |
||
| 100 | * Stop all services |
||
| 101 | */ |
||
| 102 | public void shutdown() { |
||
| 103 | 1 | if (!started) { |
|
| 104 | 1 | return; |
|
| 105 | } |
||
| 106 | |||
| 107 | 1 | logger.info("Shutdown requested..."); |
|
| 108 | 1 | started = false; |
|
| 109 | |||
| 110 | 1 | for (Service service : services) { |
|
| 111 | 1 | service.shutdown(); |
|
| 112 | 1 | } |
|
| 113 | |||
| 114 | 1 | services.clear(); |
|
| 115 | 1 | database.stop(); |
|
| 116 | 1 | System.gc(); |
|
|
0 ignored issues
–
show
|
|||
| 117 | |||
| 118 | 1 | logger.info("Araknemu successfully stopped"); |
|
| 119 | 1 | } |
|
| 120 | |||
| 121 | /** |
||
| 122 | * Add a new service |
||
| 123 | */ |
||
| 124 | public void add(Service service) { |
||
| 125 | 1 | services.add(service); |
|
| 126 | 1 | } |
|
| 127 | |||
| 128 | /** |
||
| 129 | * Get the application configuration |
||
| 130 | */ |
||
| 131 | public Configuration configuration() { |
||
| 132 | 1 | return configuration; |
|
| 133 | } |
||
| 134 | |||
| 135 | /** |
||
| 136 | * Get the database handler |
||
| 137 | */ |
||
| 138 | public DatabaseHandler database() { |
||
| 139 | 1 | return database; |
|
| 140 | } |
||
| 141 | |||
| 142 | /** |
||
| 143 | * Check if the server is started |
||
| 144 | */ |
||
| 145 | public boolean started() { |
||
| 146 | 1 | return started; |
|
| 147 | } |
||
| 148 | |||
| 149 | /** |
||
| 150 | * Get the server start date |
||
| 151 | */ |
||
| 152 | public Instant startDate() { |
||
| 153 | 1 | if (startDate == null) { |
|
| 154 | throw new IllegalStateException("Server not started"); |
||
| 155 | } |
||
| 156 | |||
| 157 | 1 | return startDate; |
|
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * Application entry point |
||
| 162 | */ |
||
| 163 | public static void main(String[] args) throws Exception { |
||
| 164 | final ConfigurationLoader configurationLoader = new ConfigurationLoader(); |
||
| 165 | |||
| 166 | if (args.length > 0) { |
||
| 167 | configurationLoader.configFileName(args[0]); |
||
| 168 | } |
||
| 169 | |||
| 170 | final Configuration configuration = configurationLoader.load(); |
||
| 171 | |||
| 172 | final Araknemu app = new Araknemu( |
||
| 173 | configuration, |
||
| 174 | new DefaultDatabaseHandler( |
||
| 175 | configuration.module(DatabaseConfiguration.MODULE), |
||
| 176 | LogManager.getLogger(DatabaseHandler.class) |
||
| 177 | ) |
||
| 178 | ); |
||
| 179 | |||
| 180 | final Container realmContainer = makeRealmContainer(app); |
||
| 181 | final Container gameContainer = makeGameContainer(app, realmContainer); |
||
| 182 | |||
| 183 | app.add(realmContainer.get(RealmService.class)); |
||
| 184 | app.add(gameContainer.get(GameService.class)); |
||
| 185 | |||
| 186 | app.boot(); |
||
| 187 | |||
| 188 | Runtime.getRuntime().addShutdownHook(new Thread(app::shutdown)); |
||
| 189 | } |
||
| 190 | |||
| 191 | private static Container makeRealmContainer(Araknemu app) throws SQLException { |
||
| 192 | final Container container = new ItemPoolContainer(); |
||
| 193 | |||
| 194 | container.register(new SqlLivingRepositoriesModule( |
||
| 195 | app.database().get("realm") |
||
| 196 | )); |
||
| 197 | container.register(new RealmModule(app)); |
||
| 198 | |||
| 199 | return container; |
||
| 200 | } |
||
| 201 | |||
| 202 | private static Container makeGameContainer(Araknemu app, Container realmContainer) throws SQLException { |
||
| 203 | final Container container = new ItemPoolContainer(); |
||
| 204 | |||
| 205 | container.register(new SqlLivingRepositoriesModule( |
||
| 206 | app.database().get("game") |
||
| 207 | )); |
||
| 208 | container.register(new SqlWorldRepositoriesModule( |
||
| 209 | app.database().get("game") |
||
| 210 | )); |
||
| 211 | container.register(new GameModule(app)); |
||
| 212 | container.register(new AdminModule(app)); |
||
| 213 | container.register(new LocalModule(realmContainer)); |
||
| 214 | |||
| 215 | return container; |
||
| 216 | } |
||
| 217 | } |
||
| 218 |