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(); |
|
|
|
|
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(); |
|
|
|
|
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
|
|
|
|