├── .gitignore
├── .idea
├── codeStyleSettings.xml
├── compiler.xml
├── dbnavigator.xml
├── description.html
├── inspectionProfiles
│ └── Project_Default.xml
├── kotlinc.xml
├── misc.xml
├── modules.xml
├── project-template.xml
└── vcs.xml
├── LICENSE
├── README.md
├── pom.xml
├── private-server.iml
└── src
└── main
├── java
└── royaleserver
│ ├── Main.java
│ ├── Server.java
│ ├── ServerException.java
│ ├── assets
│ ├── ApkAssetManager.java
│ ├── Asset.java
│ ├── AssetManager.java
│ ├── AssetManagerWrapper.java
│ ├── FolderAssetManager.java
│ └── ZipAssetManager.java
│ ├── config
│ └── Config.java
│ ├── crypto
│ ├── ClientCrypto.java
│ ├── Crypto.java
│ ├── Nonce.java
│ ├── ServerCrypto.java
│ └── TweetNaCl.java
│ ├── csv
│ ├── Column.java
│ ├── Row.java
│ ├── Table.java
│ └── Value.java
│ ├── database
│ ├── DataManager.java
│ ├── DataServices.java
│ ├── entity
│ │ ├── ArenaEntity.java
│ │ ├── AssetEntity.java
│ │ ├── CardEntity.java
│ │ ├── ChestEntity.java
│ │ ├── ClanBadgeEntity.java
│ │ ├── ClanEntity.java
│ │ ├── ClanRoleEntity.java
│ │ ├── ClanType.java
│ │ ├── ExpLevelEntity.java
│ │ ├── HomeChestEntity.java
│ │ ├── HomeChestStatus.java
│ │ ├── LogicEntity.java
│ │ ├── PlayerCardEntity.java
│ │ ├── PlayerDeckCardEntity.java
│ │ ├── PlayerEntity.java
│ │ └── UnlockCodeEntity.java
│ ├── service
│ │ ├── ArenaService.java
│ │ ├── AssetService.java
│ │ ├── CardService.java
│ │ ├── ChestService.java
│ │ ├── ClanBadgeService.java
│ │ ├── ClanRoleService.java
│ │ ├── ClanService.java
│ │ ├── ExpLevelService.java
│ │ ├── HomeChestService.java
│ │ ├── LogicService.java
│ │ ├── PlayerCardService.java
│ │ ├── PlayerDeckCardService.java
│ │ ├── PlayerService.java
│ │ ├── RestfulService.java
│ │ ├── Service.java
│ │ └── UnlockCodeService.java
│ └── util
│ │ ├── AssignedIdentityGenerator.java
│ │ ├── CloseableTransaction.java
│ │ ├── Identifiable.java
│ │ └── Transaction.java
│ ├── game
│ ├── ChestGenerator.java
│ ├── Clan.java
│ ├── CodeEnterPlayer.java
│ ├── Deck.java
│ ├── OpeningChest.java
│ ├── Player.java
│ └── PlayerCard.java
│ ├── logic
│ ├── Arena.java
│ ├── Card.java
│ ├── Chest.java
│ ├── ClanBadge.java
│ ├── ClanRole.java
│ ├── DBLogic.java
│ ├── ExpLevel.java
│ ├── GameMode.java
│ ├── Logic.java
│ ├── NamedLogic.java
│ └── Rarity.java
│ ├── network
│ ├── Filler.java
│ ├── NetworkServer.java
│ ├── NetworkSession.java
│ ├── NetworkSessionHandler.java
│ ├── PacketDecoder.java
│ ├── PacketEncoder.java
│ ├── PlayerHandler.java
│ ├── PlayerInitializer.java
│ ├── UnhandledMessageException.java
│ └── protocol
│ │ ├── Command.java
│ │ ├── Commands.java
│ │ ├── Factory.java
│ │ ├── FactoryTarget.java
│ │ ├── Handler.java
│ │ ├── Message.java
│ │ ├── MessageHeader.java
│ │ ├── Messages.java
│ │ ├── client
│ │ ├── ClientCommand.java
│ │ ├── ClientCommandFactory.java
│ │ ├── ClientCommandHandler.java
│ │ ├── ClientMessage.java
│ │ ├── ClientMessageFactory.java
│ │ ├── ClientMessageHandler.java
│ │ ├── commands
│ │ │ ├── CardUpgrade.java
│ │ │ ├── ChallengeBuy.java
│ │ │ ├── ChestBuy.java
│ │ │ ├── ChestCardNext.java
│ │ │ ├── ChestDraftCardSelect.java
│ │ │ ├── ChestOpen.java
│ │ │ ├── ChestSeasonRewardOpen.java
│ │ │ ├── DeckChange.java
│ │ │ ├── DeckChangeCard.java
│ │ │ └── FightStart.java
│ │ └── messages
│ │ │ ├── AccountUnlock.java
│ │ │ ├── ClanAskData.java
│ │ │ ├── ClanAskJoinable.java
│ │ │ ├── ClanChatMessage.java
│ │ │ ├── ClanCreate.java
│ │ │ ├── ClanJoin.java
│ │ │ ├── ClanLeave.java
│ │ │ ├── ClanSearch.java
│ │ │ ├── ClientCommands.java
│ │ │ ├── ClientHello.java
│ │ │ ├── ConnectionInfo.java
│ │ │ ├── HomeAskData.java
│ │ │ ├── HomeAskDataOwn.java
│ │ │ ├── InboxAsk.java
│ │ │ ├── Login.java
│ │ │ ├── MatchmakeCancel.java
│ │ │ ├── MatchmakeStart.java
│ │ │ ├── NameChange.java
│ │ │ ├── NameCheck.java
│ │ │ ├── Ping.java
│ │ │ └── TournamentAskJoinable.java
│ │ └── server
│ │ ├── ServerCommand.java
│ │ ├── ServerCommandFactory.java
│ │ ├── ServerMessage.java
│ │ ├── ServerMessageFactory.java
│ │ ├── commands
│ │ ├── ChestOpenOk.java
│ │ ├── ClanCreateOk.java
│ │ ├── ClanLeaveOk.java
│ │ └── NameSet.java
│ │ ├── components
│ │ ├── Card.java
│ │ ├── ChestItem.java
│ │ ├── ClanHeader.java
│ │ ├── ClanMember.java
│ │ ├── Deck.java
│ │ ├── GameCard.java
│ │ ├── GameDeck.java
│ │ ├── HomeChest.java
│ │ ├── HomeResources.java
│ │ └── PlayerClan.java
│ │ └── messages
│ │ ├── AccountUnlockFailed.java
│ │ ├── AccountUnlockOk.java
│ │ ├── ClanData.java
│ │ ├── ClanEvent.java
│ │ ├── ClanJoinableResponse.java
│ │ ├── ClanMemberAdd.java
│ │ ├── ClanMemberRemove.java
│ │ ├── ClanOnlineUpdate.java
│ │ ├── CommandResponse.java
│ │ ├── Disconnected.java
│ │ ├── HomeData.java
│ │ ├── HomeDataOwn.java
│ │ ├── HomeDataVisited.java
│ │ ├── LoginFailed.java
│ │ ├── LoginOk.java
│ │ ├── MatchmakeCancelOk.java
│ │ ├── MatchmakeInfo.java
│ │ ├── NameCheckOk.java
│ │ ├── Pong.java
│ │ ├── SectorState.java
│ │ └── ServerHello.java
│ └── utils
│ ├── Bitset.java
│ ├── CSVConverter.java
│ ├── ChildLogger.java
│ ├── DataStream.java
│ ├── Dumper.java
│ ├── GsonUtils.java
│ ├── Hex.java
│ ├── IO.java
│ ├── LogLevel.java
│ ├── LogManager.java
│ ├── Logger.java
│ ├── MainLogger.java
│ ├── Pair.java
│ ├── SCID.java
│ ├── StringUtils.java
│ └── Tag.java
└── resources
├── config.json
└── hibernate.cfg.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # User-specific stuff:
2 | .idea/**/workspace.xml
3 | .idea/**/tasks.xml
4 | .idea/dictionaries
5 |
6 | # Sensitive or high-churn files:
7 | .idea/**/dataSources/
8 | .idea/**/dataSources.ids
9 | .idea/**/dataSources.xml
10 | .idea/**/dataSources.local.xml
11 | .idea/**/sqlDataSources.xml
12 | .idea/**/dynamic.xml
13 | .idea/**/uiDesigner.xml
14 |
15 | # Gradle:
16 | .idea/**/gradle.xml
17 | .idea/**/libraries
18 |
19 |
20 | /temp
21 | /server.log
22 | /workdir/server.log
23 | /target
24 | /out
25 |
26 | /config.json
27 | /clashroyale.db
28 |
29 | /user
30 |
--------------------------------------------------------------------------------
/.idea/codeStyleSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/description.html:
--------------------------------------------------------------------------------
1 | Simple Java application that includes a class with main()
method
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/project-template.xml:
--------------------------------------------------------------------------------
1 |
2 | IJ_BASE_PACKAGE
3 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Clash Royale Private Server
2 | ## Warning. The server has been abandoned. Please do not ask anything about it. We won't answer.
3 | We do not see perspective of development, because we can't do battles. There are needed checksum, that is very hard to get it.
4 | The way to do it is to load `libg.so` and write wrapper for it, it's also very hard.
5 | Thanks for patience.
6 |
7 | Authors:
8 | - https://vk.com/tarik02_coder
9 | - https://vk.com/xset_official
10 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | royaleleaks
8 | private-server
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 |
14 | org.apache.maven.plugins
15 | maven-compiler-plugin
16 | 3.1
17 |
18 |
19 | compile
20 | compile
21 |
22 | compile
23 |
24 |
25 |
26 | testCompile
27 | test-compile
28 |
29 | testCompile
30 |
31 |
32 |
33 |
34 | 1.8
35 | 1.8
36 |
37 |
38 |
39 |
40 |
41 |
42 | 5.2.10.Final
43 | 4.1.6.Final
44 |
45 |
46 |
47 |
48 | com.google.code.gson
49 | gson
50 | 2.8.0
51 |
52 |
53 | com.google.guava
54 | guava
55 | 20.0
56 |
57 |
58 | org.javassist
59 | javassist
60 | 3.21.0-GA
61 |
62 |
63 | com.caligollc
64 | nacl
65 | 1.0.2
66 |
67 |
68 | ove
69 | ove.blake2b
70 | alpha.0
71 |
72 |
73 | org.reflections
74 | reflections
75 | 0.9.11
76 |
77 |
78 | org.tukaani
79 | xz
80 | 1.6
81 |
82 |
83 | org.hibernate
84 | hibernate-core
85 | ${hibernate.version}
86 |
87 |
88 | org.hibernate
89 | hibernate-c3p0
90 | ${hibernate.version}
91 |
92 |
93 | mysql
94 | mysql-connector-java
95 | 5.1.6
96 |
97 |
98 | io.netty
99 | netty-all
100 | ${netty.version}
101 |
102 |
103 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/Main.java:
--------------------------------------------------------------------------------
1 | package royaleserver;
2 |
3 | import royaleserver.utils.LogManager;
4 | import royaleserver.utils.Logger;
5 |
6 | public class Main {
7 | private static Logger logger = LogManager.getLogger(Main.class);
8 |
9 | public static void main(String[] args) throws Throwable {
10 | try {
11 | Server server = new Server();
12 | try {
13 | if (server.start()) {
14 | System.gc();
15 | server.loop();
16 | }
17 | } finally {
18 | server.stop();
19 | }
20 | } catch (Throwable e) {
21 | logger.fatal(e.getMessage(), e);
22 | }
23 |
24 | LogManager.shutdown();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/ServerException.java:
--------------------------------------------------------------------------------
1 | package royaleserver;
2 |
3 | public class ServerException extends Exception {
4 | public ServerException(String message) {
5 | super(message);
6 | }
7 |
8 | public ServerException(String message, Throwable e) {
9 | super(message, e);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/assets/ApkAssetManager.java:
--------------------------------------------------------------------------------
1 | package royaleserver.assets;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.zip.ZipFile;
6 |
7 | public class ApkAssetManager extends ZipAssetManager {
8 | public ApkAssetManager(File file) throws IOException {
9 | super(new ZipFile(file), "assets/");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/assets/Asset.java:
--------------------------------------------------------------------------------
1 | package royaleserver.assets;
2 |
3 | import royaleserver.csv.Table;
4 | import royaleserver.database.entity.AssetEntity;
5 | import royaleserver.utils.IO;
6 | import royaleserver.utils.StringUtils;
7 |
8 | import java.io.InputStream;
9 | import java.util.Date;
10 |
11 | public abstract class Asset {
12 | public abstract InputStream open();
13 | public abstract String name();
14 | public abstract long lastUpdated();
15 |
16 | public final byte[] bytes() {
17 | return IO.getByteArray(open());
18 | }
19 |
20 | public final String content() {
21 | return StringUtils.from(open());
22 | }
23 |
24 | public final Table csv() {
25 | return new Table(bytes());
26 | }
27 |
28 | public final boolean isNewerThan(long time) {
29 | return lastUpdated() < time;
30 | }
31 |
32 | public final boolean isNewerThan(Date date) {
33 | return isNewerThan(date.getTime());
34 | }
35 |
36 | public final boolean isNewerThan(AssetEntity assetEntity) {
37 | return isNewerThan(assetEntity.getLastUpdated());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/assets/AssetManager.java:
--------------------------------------------------------------------------------
1 | package royaleserver.assets;
2 |
3 | public abstract class AssetManager {
4 | public abstract Asset open(String path);
5 | public abstract void close();
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/assets/AssetManagerWrapper.java:
--------------------------------------------------------------------------------
1 | package royaleserver.assets;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class AssetManagerWrapper extends AssetManager {
7 | private final List assetManagers = new ArrayList<>();
8 |
9 | /**
10 | * The first added manager has the highest priority.
11 | * @param assetManager AssetManager instance to use
12 | */
13 | public void add(AssetManager assetManager) {
14 | assetManagers.add(assetManager);
15 | }
16 |
17 | public AssetManager simplify() {
18 | if (assetManagers.size() == 1) {
19 | return assetManagers.get(0);
20 | }
21 |
22 | return this;
23 | }
24 |
25 | @Override
26 | public Asset open(String path) {
27 | for (AssetManager assetManager : assetManagers) {
28 | Asset asset = assetManager.open(path);
29 | if (asset != null) {
30 | return asset;
31 | }
32 | }
33 |
34 | return null;
35 | }
36 |
37 | @Override
38 | public void close() {
39 | for (AssetManager assetManager : assetManagers) {
40 | assetManager.close();
41 | }
42 |
43 | assetManagers.clear();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/assets/FolderAssetManager.java:
--------------------------------------------------------------------------------
1 | package royaleserver.assets;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.InputStream;
7 |
8 | public class FolderAssetManager extends AssetManager {
9 | private final File root;
10 |
11 | public FolderAssetManager(File root) {
12 | this.root = root;
13 | }
14 |
15 | @Override
16 | public Asset open(String path) {
17 | File file = new File(root, path);
18 | if (file.exists()) {
19 | return new FileAsset(file.getAbsolutePath().substring(root.getAbsolutePath().length() + File.pathSeparator.length()), file);
20 | }
21 |
22 | return null;
23 | }
24 |
25 | @Override
26 | public void close() {
27 | }
28 |
29 | private static class FileAsset extends Asset {
30 | private final String name;
31 | private final File file;
32 |
33 | public FileAsset(String name, File file) {
34 | this.name = name;
35 | this.file = file;
36 | }
37 |
38 | @Override
39 | public InputStream open() {
40 | try {
41 | return new FileInputStream(file);
42 | } catch (FileNotFoundException ignored) {}
43 |
44 | return null;
45 | }
46 |
47 | @Override
48 | public String name() {
49 | return this.name;
50 | }
51 |
52 | @Override
53 | public long lastUpdated() {
54 | return file.lastModified();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/assets/ZipAssetManager.java:
--------------------------------------------------------------------------------
1 | package royaleserver.assets;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.zip.ZipEntry;
6 | import java.util.zip.ZipFile;
7 |
8 | public class ZipAssetManager extends AssetManager {
9 | private final ZipFile file;
10 | private final String root;
11 |
12 | public ZipAssetManager(ZipFile file) {
13 | this(file, "");
14 | }
15 |
16 | public ZipAssetManager(ZipFile file, String root) {
17 | if (file == null) {
18 | throw new IllegalArgumentException("file");
19 | }
20 |
21 | if (root == null) {
22 | throw new IllegalArgumentException("root");
23 | }
24 |
25 | if (root.length() != 0 && !root.endsWith("/")) {
26 | root = root + "/";
27 | }
28 |
29 | this.file = file;
30 | this.root = root;
31 | }
32 |
33 | @Override
34 | public Asset open(String path) {
35 | ZipEntry entry = file.getEntry(root + path);
36 | if (entry == null) {
37 | return null;
38 | }
39 |
40 | return new ZipEntryAsset(path, file, entry);
41 | }
42 |
43 | @Override
44 | public void close() {
45 | try {
46 | file.close();
47 | } catch (IOException e) {
48 | e.printStackTrace();
49 | }
50 | }
51 |
52 | private static class ZipEntryAsset extends Asset {
53 | private final String name;
54 | private final ZipFile file;
55 | private final ZipEntry entry;
56 |
57 | public ZipEntryAsset(String name, ZipFile file, ZipEntry entry) {
58 | this.name = name;
59 | this.file = file;
60 | this.entry = entry;
61 | }
62 |
63 | @Override
64 | public InputStream open() {
65 | try {
66 | return file.getInputStream(entry);
67 | } catch (IOException e) {
68 | e.printStackTrace();
69 | }
70 |
71 | return null;
72 | }
73 |
74 | @Override
75 | public String name() {
76 | return name;
77 | }
78 |
79 | @Override
80 | public long lastUpdated() {
81 | return entry.getLastModifiedTime().toMillis();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/config/Config.java:
--------------------------------------------------------------------------------
1 | package royaleserver.config;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.JsonElement;
5 | import com.google.gson.JsonObject;
6 | import com.google.gson.JsonParser;
7 | import com.google.gson.stream.JsonWriter;
8 | import royaleserver.ServerException;
9 | import royaleserver.utils.GsonUtils;
10 | import royaleserver.utils.IO;
11 | import royaleserver.utils.LogManager;
12 | import royaleserver.utils.Logger;
13 |
14 | import java.io.*;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 | import java.util.function.Function;
18 |
19 | public final class Config {
20 | private static final Logger logger = LogManager.getLogger(Config.class);
21 |
22 | private Map map = new HashMap<>();
23 |
24 | public Config(JsonObject json) {
25 | fill("", json);
26 | }
27 |
28 | public JsonElement get(String key) {
29 | return get(key, null);
30 | }
31 |
32 | public JsonElement get(String key, JsonElement def) {
33 | return map.getOrDefault(key, def);
34 | }
35 |
36 | public static Config load(int configVersion, File configFile, Function defaultConfigFactory) throws ServerException {
37 | try {
38 | int version = 0;
39 |
40 | JsonObject configObject = null;
41 | if (configFile.exists()) {
42 | try {
43 | configObject = new JsonParser().parse(new InputStreamReader(new FileInputStream(configFile))).getAsJsonObject();
44 | JsonElement jversion = configObject.get("_version");
45 | if (jversion != null && !jversion.isJsonNull()) {
46 | version = jversion.getAsInt();
47 | }
48 | } catch (Exception ignored) {}
49 | }
50 |
51 | if (version == 0 || version < configVersion) {
52 | InputStream configInputStream = defaultConfigFactory.apply(null);
53 | if (configInputStream == null) {
54 | throw new ServerException("Failed to get default config resource.");
55 | }
56 |
57 | if (version == 0) {
58 | logger.warn("Resetting your config...");
59 |
60 | final byte[] bytes = IO.getByteArray(configInputStream, true);
61 | if (bytes == null) {
62 | throw new ServerException("Failed to get default config.");
63 | }
64 |
65 | configObject = new JsonParser().parse(new InputStreamReader(new ByteArrayInputStream(bytes))).getAsJsonObject();
66 | try (OutputStream os = new FileOutputStream(configFile)) {
67 | os.write(bytes);
68 | }
69 | } else if (version < configVersion) {
70 | JsonObject defaultConfig = new JsonParser().parse(new InputStreamReader(configInputStream)).getAsJsonObject();
71 | GsonUtils.extendJsonObject(defaultConfig, GsonUtils.ConflictStrategy.PREFER_FIRST_OBJ, configObject);
72 | configObject = defaultConfig;
73 | }
74 |
75 | configObject.addProperty("_version", configVersion);
76 |
77 | logger.warn("Saving config...");
78 | JsonWriter writer = new JsonWriter(new FileWriter(configFile));
79 | writer.setIndent("\t");
80 | new Gson().toJson(configObject, writer);
81 | writer.close();
82 |
83 | logger.warn("Check out your config and start the server.");
84 | return null;
85 | }
86 |
87 | return new Config(configObject);
88 | } catch (Throwable e) {
89 | logger.fatal("Cannot read config.", e);
90 | throw new ServerException("Cannot read config.");
91 | }
92 | }
93 |
94 | private void fill(String prefix, JsonObject json) {
95 | for (Map.Entry child : json.entrySet()) {
96 | String key = child.getKey();
97 | JsonElement element = child.getValue();
98 |
99 | if (element instanceof JsonObject) {
100 | fill(prefix + key + ".", (JsonObject)element);
101 | } else {
102 | map.put(prefix + key, element);
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/crypto/ClientCrypto.java:
--------------------------------------------------------------------------------
1 | package royaleserver.crypto;
2 |
3 | import royaleserver.network.protocol.Messages;
4 | import royaleserver.network.protocol.MessageHeader;
5 |
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.IOException;
8 | import java.nio.ByteBuffer;
9 | import java.nio.ByteOrder;
10 | import java.util.Arrays;
11 |
12 | public class ClientCrypto extends Crypto {
13 | protected ServerCrypto server;
14 |
15 | public ClientCrypto(byte[] serverKey) {
16 | super();
17 |
18 | TweetNaCl.crypto_sign_keypair(privateKey, clientKey, false);
19 | this.serverKey = serverKey;
20 |
21 | sharedKey = Curve25519.scalarMult(privateKey, serverKey);
22 | sharedKey = Salsa.HSalsa20(new byte[16], sharedKey, Salsa.SIGMA);
23 |
24 | encryptNonce = new Nonce();
25 | }
26 |
27 | public void setServer(ServerCrypto server) {
28 | this.server = server;
29 | }
30 |
31 | @Override
32 | public void decryptPacket(MessageHeader message) {
33 | switch (message.id) {
34 | case Messages.SERVER_HELLO:
35 | case Messages.LOGIN_FAILED:
36 | int len = ByteBuffer.wrap(message.payload, 0, 4).order(ByteOrder.LITTLE_ENDIAN).getInt(0);
37 | sessionKey = Arrays.copyOfRange(message.payload, 4, 4 + len);
38 | message.decrypted = message.payload;
39 | break;
40 | case Messages.LOGIN_OK:
41 | Nonce nonce = new Nonce(clientKey, serverKey, encryptNonce.getBytes());
42 | message.decrypted = decrypt(message.payload, nonce);
43 |
44 | if (message.decrypted != null) {
45 | try {
46 | decryptNonce = new Nonce(Arrays.copyOfRange(message.decrypted, 0, 24));
47 | server.encryptNonce = new Nonce(Arrays.copyOfRange(message.decrypted, 0, 24));
48 | } catch (Exception e) {
49 | e.printStackTrace();
50 | }
51 |
52 | sharedKey = Arrays.copyOfRange(message.decrypted, 24, 56);
53 |
54 | message.decrypted = Arrays.copyOfRange(message.decrypted, 56, message.decrypted.length);
55 | }
56 | break;
57 | default:
58 | message.decrypted = decrypt(message.payload);
59 | }
60 | }
61 |
62 | @Override
63 | public void encryptPacket(MessageHeader message) {
64 | switch (message.id) {
65 | case Messages.CLIENT_HELLO:
66 | message.payload = message.decrypted;
67 | break;
68 | case Messages.LOGIN:
69 | Nonce nonce = new Nonce(clientKey, serverKey);
70 | ByteArrayOutputStream toEncrypt = new ByteArrayOutputStream();
71 |
72 | try {
73 | toEncrypt.write(sessionKey);
74 | toEncrypt.write(encryptNonce.getBytes());
75 | toEncrypt.write(message.decrypted);
76 | } catch (IOException ignored) {}
77 |
78 | ByteArrayOutputStream encrypted = new ByteArrayOutputStream();
79 |
80 | try {
81 | encrypted.write(clientKey);
82 | encrypted.write(encrypt(toEncrypt.toByteArray(), nonce));
83 | } catch (IOException ignored) {}
84 |
85 | message.payload = encrypted.toByteArray();
86 | break;
87 | default:
88 | message.payload = encrypt(message.decrypted);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/crypto/Crypto.java:
--------------------------------------------------------------------------------
1 | package royaleserver.crypto;
2 |
3 | import royaleserver.network.protocol.MessageHeader;
4 | import royaleserver.utils.LogManager;
5 | import royaleserver.utils.Logger;
6 |
7 | public abstract class Crypto {
8 | public static class CryptoException extends Exception {
9 | public CryptoException(String message) {
10 | super(message);
11 | }
12 | }
13 |
14 | private static Logger logger = LogManager.getLogger(Crypto.class);
15 |
16 | protected byte[] privateKey = new byte[TweetNaCl.SIGN_PUBLIC_KEY_BYTES];
17 | protected byte[] serverKey;
18 | protected byte[] clientKey = new byte[TweetNaCl.SIGN_SECRET_KEY_BYTES];
19 | protected byte[] sharedKey;
20 | protected Nonce decryptNonce = new Nonce();
21 | protected Nonce encryptNonce = new Nonce();
22 | protected byte[] sessionKey;
23 |
24 | public byte[] getSessionKey() {
25 | return sessionKey;
26 | }
27 |
28 | public void setSessionKey(byte[] sessionKey) {
29 | this.sessionKey = sessionKey;
30 | }
31 |
32 | public byte[] getSharedKey() {
33 | return sharedKey;
34 | }
35 |
36 | public void setSharedKey(byte[] sharedKey) throws CryptoException {
37 | if (sharedKey.length != 32) {
38 | throw new CryptoException("sharedKey.length must be 32");
39 | }
40 |
41 | this.sharedKey = sharedKey;
42 | }
43 |
44 | public byte[] encrypt(byte[] message) {
45 | return encrypt(message, null);
46 | }
47 |
48 | public byte[] encrypt(byte[] message, Nonce nonce) {
49 | if (nonce == null) {
50 | encryptNonce.increment();
51 | nonce = encryptNonce;
52 | }
53 |
54 | return TweetNaCl.secretbox(message, nonce.getBytes(), sharedKey);
55 | }
56 |
57 | public byte[] decrypt(byte[] message) {
58 | return decrypt(message, null);
59 | }
60 |
61 | public byte[] decrypt(byte[] message, Nonce nonce) {
62 | if (nonce == null) {
63 | decryptNonce.increment();
64 | nonce = decryptNonce;
65 | }
66 |
67 | return TweetNaCl.secretbox_open(message, nonce.getBytes(), sharedKey);
68 | }
69 |
70 | public abstract void decryptPacket(MessageHeader message);
71 | public abstract void encryptPacket(MessageHeader message);
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/crypto/Nonce.java:
--------------------------------------------------------------------------------
1 | package royaleserver.crypto;
2 |
3 | import ove.crypto.digest.Blake2b;
4 |
5 | import java.nio.ByteBuffer;
6 | import java.nio.ByteOrder;
7 | import java.security.SecureRandom;
8 |
9 | public class Nonce {
10 | public static class NonceException extends Exception {
11 | public NonceException(String message) {
12 | super(message);
13 | }
14 | }
15 |
16 | private byte[] bytes;
17 |
18 | public Nonce() {
19 | bytes = new byte[24];
20 | SecureRandom r = new SecureRandom();
21 | r.nextBytes(bytes);
22 | }
23 |
24 | public Nonce(byte[] nonce) throws NonceException {
25 | if (nonce.length != 24) {
26 | throw new NonceException("nonce.length must be 24");
27 | }
28 |
29 | bytes = nonce;
30 | }
31 |
32 | public Nonce(byte[] clientKey, byte[] serverKey) {
33 | this(clientKey, serverKey, null);
34 | }
35 |
36 | public Nonce(byte[] clientKey, byte[] serverKey, byte[] nonce) {
37 | final Blake2b hash = Blake2b.Digest.newInstance(24);
38 | if (nonce != null) {
39 | hash.update(nonce);
40 | }
41 |
42 | hash.update(clientKey);
43 | hash.update(serverKey);
44 |
45 | bytes = hash.digest();
46 | }
47 |
48 | public void increment() {
49 | ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, 2);
50 | buffer.order(ByteOrder.LITTLE_ENDIAN);
51 | short val = buffer.getShort(0);
52 | val += 2;
53 | buffer.putShort(0, val);
54 |
55 | bytes[0] = buffer.get(0);
56 | bytes[1] = buffer.get(1);
57 | }
58 |
59 | public byte[] getBytes() {
60 | return bytes;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/crypto/ServerCrypto.java:
--------------------------------------------------------------------------------
1 | package royaleserver.crypto;
2 |
3 | import royaleserver.network.protocol.Messages;
4 | import royaleserver.network.protocol.MessageHeader;
5 | import royaleserver.utils.Hex;
6 |
7 | import java.io.ByteArrayOutputStream;
8 | import java.io.IOException;
9 | import java.util.Arrays;
10 |
11 | public class ServerCrypto extends Crypto {
12 | protected ClientCrypto client;
13 | protected Nonce nonce;
14 |
15 | public ServerCrypto() {
16 | privateKey = Hex.toByteArray("1891d401fadb51d25d3a9174d472a9f691a45b974285d47729c45c6538070d85");
17 | serverKey = Hex.toByteArray("72f1a4a4c48e44da0c42310f800e96624e6dc6a641a9d41c3b5039d8dfadc27e");
18 | }
19 |
20 | public void setClient(ClientCrypto client) {
21 | this.client = client;
22 | sharedKey = client.sharedKey;
23 | }
24 |
25 | @Override
26 | public void decryptPacket(MessageHeader message) {
27 | switch (message.id) {
28 | case Messages.CLIENT_HELLO:
29 | message.decrypted = message.payload;
30 | break;
31 | case Messages.LOGIN:
32 | clientKey = Arrays.copyOfRange(message.payload, 0, 32);
33 | byte[] cipherText = Arrays.copyOfRange(message.payload, 32, message.payload.length);
34 |
35 | sharedKey = Curve25519.scalarMult(privateKey, clientKey);
36 | sharedKey = Salsa.HSalsa20(new byte[16], sharedKey, Salsa.SIGMA);
37 |
38 | Nonce nonce = new Nonce(clientKey, serverKey);
39 | message.decrypted = decrypt(cipherText, nonce);
40 |
41 | if (message.decrypted != null) {
42 | sessionKey = Arrays.copyOfRange(message.decrypted, 0, 24);
43 | try {
44 | decryptNonce = new Nonce(Arrays.copyOfRange(message.decrypted, 24, 48));
45 | client.encryptNonce = new Nonce(Arrays.copyOfRange(message.decrypted, 24, 48));
46 | } catch (Exception e) {
47 | e.printStackTrace();
48 | }
49 |
50 | message.decrypted = Arrays.copyOfRange(message.decrypted, 48, message.decrypted.length);
51 | }
52 | break;
53 | default:
54 | message.decrypted = decrypt(message.payload);
55 | }
56 | }
57 |
58 | @Override
59 | public void encryptPacket(MessageHeader message) {
60 | switch (message.id) {
61 | case Messages.SERVER_HELLO:
62 | message.payload = message.decrypted;
63 | break;
64 | case Messages.LOGIN_FAILED:
65 | if(nonce != null) {
66 | message.payload = encrypt(message.decrypted);
67 | break;
68 | }
69 | case Messages.LOGIN_OK:
70 | nonce = new Nonce(clientKey, serverKey, decryptNonce.getBytes());
71 | ByteArrayOutputStream toEncrypt = new ByteArrayOutputStream();
72 |
73 | try {
74 | toEncrypt.write(encryptNonce.getBytes());
75 | toEncrypt.write(sharedKey);
76 | toEncrypt.write(message.decrypted);
77 | } catch (IOException ignored) {}
78 |
79 | message.payload = encrypt(toEncrypt.toByteArray(), nonce);
80 | break;
81 | default:
82 | message.payload = encrypt(message.decrypted);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/csv/Column.java:
--------------------------------------------------------------------------------
1 | package royaleserver.csv;
2 |
3 | public class Column {
4 | private Table table;
5 | private int index;
6 |
7 | public Column(Table table, int index) {
8 | this.table = table;
9 | this.index = index;
10 | }
11 |
12 | public Table getTable() {
13 | return table;
14 | }
15 |
16 | public int getIndex() {
17 | return index;
18 | }
19 |
20 | public String getName() {
21 | return table.getColumnName(index);
22 | }
23 |
24 | public String getType() {
25 | return table.getColumnType(index);
26 | }
27 |
28 | public Value getValue(int row) {
29 | return table.getValue(index, row);
30 | }
31 |
32 | public Value getValue(Row row) {
33 | if (table != row.getTable()) {
34 | return null;
35 | }
36 |
37 | return table.getValue(index, row.getIndex());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/csv/Row.java:
--------------------------------------------------------------------------------
1 | package royaleserver.csv;
2 |
3 | public class Row {
4 | private Table table;
5 | private int index;
6 |
7 | public Row(Table table, int index) {
8 | this.table = table;
9 | this.index = index;
10 | }
11 |
12 | public Table getTable() {
13 | return table;
14 | }
15 |
16 | public int getIndex() {
17 | return index;
18 | }
19 |
20 | public Value getValue(int row) {
21 | return table.getValue(row, index);
22 | }
23 |
24 | public Value getValue(Column column) {
25 | if (table != column.getTable()) {
26 | return null;
27 | }
28 |
29 | return table.getValue(column.getIndex(), index);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/csv/Value.java:
--------------------------------------------------------------------------------
1 | package royaleserver.csv;
2 |
3 | public class Value {
4 | private Table table;
5 | private int column, row;
6 |
7 | public Value(Table table, int column, int row) {
8 | this.table = table;
9 | this.column = column;
10 | this.row = row;
11 | }
12 |
13 | public int getColumnId() {
14 | return column;
15 | }
16 |
17 | public int getRowId() {
18 | return row;
19 | }
20 |
21 | public Column getColumn() {
22 | return table.getColumn(column);
23 | }
24 |
25 | public Row getRow() {
26 | return table.getRow(row);
27 | }
28 |
29 | public String getType() {
30 | return table.getColumnType(column);
31 | }
32 |
33 | public String getValue() {
34 | return table.getValueValue(column, row);
35 | }
36 |
37 | public String[] getValues() {
38 | return getValue().split("\n");
39 | }
40 |
41 |
42 | public boolean empty() {
43 | return getValue().trim().length() == 0;
44 | }
45 |
46 | public String asString() {
47 | return asString(false);
48 | }
49 |
50 | public String asString(boolean nullIfEmpty) {
51 | return (nullIfEmpty && empty()) ? null : getValue();
52 | }
53 |
54 | public String asString(String def) {
55 | return empty() ? def : asString();
56 | }
57 |
58 | public boolean asBoolean() {
59 | return getValue().equalsIgnoreCase("TRUE");
60 | }
61 |
62 | public boolean asBoolean(boolean def) {
63 | return empty() ? def : asBoolean();
64 | }
65 |
66 | public int asInt() {
67 | return Integer.valueOf(getValue());
68 | }
69 |
70 | public int asInt(int def) {
71 | return empty() ? def : asInt();
72 | }
73 |
74 | public Integer asIntNullable() {
75 | return empty() ? null : Integer.valueOf(getValue());
76 | }
77 |
78 | public float asFloat() {
79 | return Float.valueOf(getValue());
80 | }
81 |
82 | public float asFloat(float def) {
83 | return empty() ? def : asFloat();
84 | }
85 |
86 | public Float asFloatNullable() {
87 | return empty() ? null : Float.valueOf(getValue());
88 | }
89 |
90 |
91 | public String[] asStringArray() {
92 | return getValues();
93 | }
94 |
95 | public boolean[] asBooleanArray() {
96 | String[] values = getValues();
97 | boolean[] results = new boolean[values.length];
98 |
99 | for (int i = 0; i < values.length; ++i) {
100 | results[i] = values[i].equalsIgnoreCase("TRUE");
101 | }
102 |
103 | return results;
104 | }
105 |
106 | public int[] asIntArray() {
107 | String[] values = getValues();
108 | int[] results = new int[values.length];
109 |
110 | for (int i = 0; i < values.length; ++i) {
111 | results[i] = Integer.valueOf(values[i]);
112 | }
113 |
114 | return results;
115 | }
116 |
117 | public float[] asFloatArray() {
118 | String[] values = getValues();
119 | float[] results = new float[values.length];
120 |
121 | for (int i = 0; i < values.length; ++i) {
122 | results[i] = Float.valueOf(values[i]);
123 | }
124 |
125 | return results;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/DataServices.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.service.*;
5 |
6 | /**
7 | * A class that contains all the services.
8 | */
9 | public final class DataServices {
10 | public final ArenaService arenaService;
11 | public final AssetService assetService;
12 | public final CardService cardService;
13 | public final ChestService chestService;
14 | public final ClanBadgeService clanBadgeService;
15 | public final ClanRoleService clanRoleService;
16 | public final ClanService clanService;
17 | public final ExpLevelService expLevelService;
18 | public final HomeChestService homeChestService;
19 | public final PlayerCardService playerCardService;
20 | public final PlayerDeckCardService playerDeckCardService;
21 | public final PlayerService playerService;
22 | public final UnlockCodeService unlockCodeService;
23 |
24 | public DataServices(SessionFactory sessionFactory) {
25 | arenaService = new ArenaService(sessionFactory);
26 | assetService = new AssetService(sessionFactory);
27 | cardService = new CardService(sessionFactory);
28 | chestService = new ChestService(sessionFactory);
29 | clanBadgeService = new ClanBadgeService(sessionFactory);
30 | clanRoleService = new ClanRoleService(sessionFactory);
31 | clanService = new ClanService(sessionFactory);
32 | expLevelService = new ExpLevelService(sessionFactory);
33 | homeChestService = new HomeChestService(sessionFactory);
34 | playerCardService = new PlayerCardService(sessionFactory);
35 | playerDeckCardService = new PlayerDeckCardService(sessionFactory);
36 | playerService = new PlayerService(sessionFactory);
37 | unlockCodeService = new UnlockCodeService(sessionFactory);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ArenaEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.Entity;
4 | import javax.persistence.NamedQuery;
5 | import javax.persistence.Table;
6 |
7 | @Entity
8 | @Table(name = "arenas")
9 | @NamedQuery(name = "ArenaEntity.all", query = "SELECT arenaEntity FROM ArenaEntity arenaEntity")
10 | public class ArenaEntity extends LogicEntity {
11 | public ArenaEntity() {}
12 |
13 | public ArenaEntity(String name) {
14 | super(name);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/AssetEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.*;
4 | import java.util.Date;
5 |
6 | @Entity
7 | @Table(name = "assets")
8 | @NamedQuery(name = "AssetEntity.byName", query = "SELECT assetEntity FROM AssetEntity assetEntity WHERE assetEntity.name = :name")
9 | public class AssetEntity {
10 | @Id
11 | @GeneratedValue(strategy = GenerationType.IDENTITY)
12 | private long id;
13 |
14 | @Column(length = 128, unique = true, nullable = false)
15 | private String name;
16 |
17 | @Column(nullable = false, columnDefinition = "TIMESTAMP")
18 | @Temporal(value = TemporalType.TIMESTAMP)
19 | private Date lastUpdated;
20 |
21 | public long getId() {
22 | return id;
23 | }
24 |
25 | public AssetEntity setId(long id) {
26 | this.id = id;
27 | return this;
28 | }
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public AssetEntity setName(String name) {
35 | this.name = name;
36 | return this;
37 | }
38 |
39 | public Date getLastUpdated() {
40 | return lastUpdated;
41 | }
42 |
43 | public AssetEntity setLastUpdated(Date lastUpdated) {
44 | this.lastUpdated = lastUpdated;
45 | return this;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/CardEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.Entity;
4 | import javax.persistence.NamedQuery;
5 | import javax.persistence.Table;
6 |
7 | @Entity
8 | @Table(name = "cards")
9 | @NamedQuery(name = "CardEntity.all", query = "SELECT cardEntity FROM CardEntity cardEntity")
10 | public class CardEntity extends LogicEntity {
11 | public CardEntity() {}
12 |
13 | public CardEntity(String name) {
14 | super(name);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ChestEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.Entity;
4 | import javax.persistence.NamedQuery;
5 | import javax.persistence.Table;
6 |
7 | @Entity
8 | @Table(name = "chests")
9 | @NamedQuery(name = "ChestEntity.all", query = "SELECT chestEntity FROM ChestEntity chestEntity")
10 | public class ChestEntity extends LogicEntity {
11 | public ChestEntity() {}
12 |
13 | public ChestEntity(String name) {
14 | super(name);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ClanBadgeEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.Entity;
4 | import javax.persistence.NamedQuery;
5 | import javax.persistence.Table;
6 |
7 | @Entity
8 | @Table(name = "clan_badges")
9 | @NamedQuery(name = "ClanBadgeEntity.all", query = "SELECT clanBadgeEntity FROM ClanBadgeEntity clanBadgeEntity")
10 | public class ClanBadgeEntity extends LogicEntity {
11 | public ClanBadgeEntity() {}
12 |
13 | public ClanBadgeEntity(String name) {
14 | super(name);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ClanEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import royaleserver.logic.ClanBadge;
4 |
5 | import javax.persistence.*;
6 | import java.util.HashSet;
7 | import java.util.Set;
8 |
9 | @Entity
10 | @Table(name = "clans")
11 |
12 | @NamedQueries(value = {
13 | @NamedQuery(name = "ClanEntity.byId", query = "SELECT clan from ClanEntity clan WHERE clan.id = :id"),
14 | @NamedQuery(name = "ClanEntity.byName", query = "SELECT clan FROM ClanEntity clan WHERE LOWER(clan.name) LIKE LOWER(:name)")
15 | })
16 | public class ClanEntity {
17 | @Id
18 | @GeneratedValue(strategy = GenerationType.IDENTITY)
19 | private long id;
20 |
21 | @Column(nullable = false)
22 | private String name = "";
23 |
24 | @Column(nullable = false, columnDefinition = "TEXT")
25 | private String description = "";
26 |
27 | @ManyToOne(optional = false)
28 | @JoinColumn(name = "badge_id")
29 | private ClanBadgeEntity badge;
30 |
31 | @Column(nullable = false)
32 | private int score = 0;
33 |
34 | @Column(nullable = false)
35 | private int donationsPerWeek = 0;
36 |
37 | @Column(nullable = false)
38 | @Enumerated(EnumType.ORDINAL)
39 | private ClanType type = ClanType.OPEN;
40 |
41 | @Column(nullable = false)
42 | private int requiredTrophies = 0;
43 |
44 | // TODO: Location
45 |
46 | @OneToMany(fetch = FetchType.LAZY, mappedBy = "clan")
47 | private Set members = new HashSet<>();
48 |
49 |
50 | public long getId() {
51 | return id;
52 | }
53 |
54 | public ClanEntity setId(long id) {
55 | this.id = id;
56 | return this;
57 | }
58 |
59 | public String getName() {
60 | return name;
61 | }
62 |
63 | public ClanEntity setName(String name) {
64 | this.name = name;
65 | return this;
66 | }
67 |
68 | public String getDescription() {
69 | return description;
70 | }
71 |
72 | public ClanEntity setDescription(String description) {
73 | this.description = description;
74 | return this;
75 | }
76 |
77 | public ClanBadgeEntity getBadge() {
78 | return badge;
79 | }
80 |
81 | public ClanEntity setBadge(ClanBadgeEntity badge) {
82 | this.badge = badge;
83 | return this;
84 | }
85 |
86 | public int getScore() {
87 | return score;
88 | }
89 |
90 | public ClanEntity setScore(int score) {
91 | this.score = score;
92 | return this;
93 | }
94 |
95 | public int getDonationsPerWeek() {
96 | return donationsPerWeek;
97 | }
98 |
99 | public ClanEntity setDonationsPerWeek(int donationsPerWeek) {
100 | this.donationsPerWeek = donationsPerWeek;
101 | return this;
102 | }
103 |
104 | public ClanType getType() {
105 | return type;
106 | }
107 |
108 | public ClanEntity setType(ClanType type) {
109 | this.type = type;
110 | return this;
111 | }
112 |
113 | public int getRequiredTrophies() {
114 | return requiredTrophies;
115 | }
116 |
117 | public ClanEntity setRequiredTrophies(int requiredTrophies) {
118 | this.requiredTrophies = requiredTrophies;
119 | return this;
120 | }
121 |
122 | public Set getMembers() {
123 | return members;
124 | }
125 |
126 | public ClanEntity setMembers(Set players) {
127 | this.members = players;
128 | return this;
129 | }
130 |
131 |
132 | public ClanBadge getLogicBadge() {
133 | return ClanBadge.byDB(badge.getId());
134 | }
135 |
136 | public ClanEntity setLogicBadge(ClanBadge badge) {
137 | return setBadge(badge.getDbEntity());
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ClanRoleEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.Entity;
4 | import javax.persistence.NamedQuery;
5 | import javax.persistence.Table;
6 |
7 | @Entity
8 | @Table(name = "clan_roles")
9 | @NamedQuery(name = "ClanRoleEntity.all", query = "SELECT clanRoleEntity FROM ClanRoleEntity clanRoleEntity")
10 | public class ClanRoleEntity extends LogicEntity {
11 | public ClanRoleEntity() {}
12 |
13 | public ClanRoleEntity(String name) {
14 | super(name);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ClanType.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | public enum ClanType {
4 | OPEN,
5 | INVITE,
6 | CLOSED,
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/ExpLevelEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.Entity;
4 | import javax.persistence.NamedQuery;
5 | import javax.persistence.Table;
6 |
7 | @Entity
8 | @Table(name = "exp_levels")
9 | @NamedQuery(name = "ExpLevelEntity.all", query = "SELECT expLevelEntity FROM ExpLevelEntity expLevelEntity")
10 | public class ExpLevelEntity extends LogicEntity {
11 | public ExpLevelEntity() {}
12 |
13 | public ExpLevelEntity(String name) {
14 | super(name);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/HomeChestEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import royaleserver.logic.Chest;
4 |
5 | import javax.persistence.*;
6 | import java.util.Date;
7 |
8 | @Entity
9 | @Table(name = "home_chest", indexes = {
10 | @Index(unique = true, columnList = "player_id,slot")
11 | })
12 | public class HomeChestEntity implements java.io.Serializable {
13 | @Id
14 | @ManyToOne
15 | @PrimaryKeyJoinColumn(name = "player_id", referencedColumnName = "id")
16 | private PlayerEntity player;
17 |
18 | @Id
19 | private int slot;
20 |
21 | @ManyToOne
22 | @PrimaryKeyJoinColumn(name = "chest_id", referencedColumnName = "id")
23 | private ChestEntity chest;
24 |
25 | @Enumerated(EnumType.ORDINAL)
26 | @Column(nullable = false)
27 | private HomeChestStatus status;
28 |
29 | @Column(nullable = true)
30 | @Temporal(value = TemporalType.TIMESTAMP)
31 | private Date openStart = null;
32 |
33 | @Column(nullable = true)
34 | @Temporal(value = TemporalType.TIMESTAMP)
35 | private Date openEnd = null;
36 |
37 |
38 | public PlayerEntity getPlayer() {
39 | return player;
40 | }
41 |
42 | public HomeChestEntity setPlayer(PlayerEntity player) {
43 | this.player = player;
44 | return this;
45 | }
46 |
47 | public int getSlot() {
48 | return slot;
49 | }
50 |
51 | public HomeChestEntity setSlot(int slot) {
52 | this.slot = slot;
53 | return this;
54 | }
55 |
56 | public ChestEntity getChest() {
57 | return chest;
58 | }
59 |
60 | public HomeChestEntity setChest(ChestEntity chest) {
61 | this.chest = chest;
62 | return this;
63 | }
64 |
65 | public HomeChestStatus getStatus() {
66 | return status;
67 | }
68 |
69 | public HomeChestEntity setStatus(HomeChestStatus status) {
70 | this.status = status;
71 | return this;
72 | }
73 |
74 | public Date getOpenStart() {
75 | return openStart;
76 | }
77 |
78 | public HomeChestEntity setOpenStart(Date openStart) {
79 | this.openStart = openStart;
80 | return this;
81 | }
82 |
83 | public Date getOpenEnd() {
84 | return openEnd;
85 | }
86 |
87 | public HomeChestEntity setOpenEnd(Date openEnd) {
88 | this.openEnd = openEnd;
89 | return this;
90 | }
91 |
92 | public Chest getLogicChest() {
93 | return Chest.byDB(chest.getId());
94 | }
95 |
96 | public HomeChestEntity setLogicChest(Chest chest) {
97 | return setChest(chest.getDbEntity());
98 | }
99 |
100 | @Override
101 | public boolean equals(Object o) {
102 | if (this == o) {
103 | return true;
104 | }
105 | if (!(o instanceof HomeChestEntity)) {
106 | return false;
107 | }
108 |
109 | HomeChestEntity that = (HomeChestEntity)o;
110 |
111 | return slot == that.slot && player.equals(that.player);
112 | }
113 |
114 | @Override
115 | public int hashCode() {
116 | int result = player.hashCode();
117 | result = 31 * result + slot;
118 | return result;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/HomeChestStatus.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | public enum HomeChestStatus {
4 | IDLE,
5 | OPENING,
6 | OPENED
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/LogicEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.*;
4 |
5 | @MappedSuperclass
6 | public abstract class LogicEntity {
7 | @Id
8 | @GeneratedValue(strategy = GenerationType.IDENTITY)
9 | private long id;
10 |
11 | @Column(nullable = false, unique = true)
12 | private String name;
13 |
14 | public LogicEntity() {}
15 |
16 | public LogicEntity(String name) {
17 | this.name = name;
18 | }
19 |
20 | public long getId() {
21 | return id;
22 | }
23 |
24 | public String getName() {
25 | return name;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/PlayerCardEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import royaleserver.logic.Card;
4 |
5 | import javax.persistence.*;
6 | import java.io.Serializable;
7 |
8 | @Entity
9 | @Table(name = "player_card", indexes = {
10 | @Index(unique = true, columnList = "player_id,card_id")
11 | })
12 | public class PlayerCardEntity implements Serializable {
13 | @Id
14 | @ManyToOne
15 | @PrimaryKeyJoinColumn(name = "player_id", referencedColumnName = "id")
16 | private PlayerEntity player;
17 |
18 | @Id
19 | @ManyToOne
20 | @PrimaryKeyJoinColumn(name = "card_id", referencedColumnName = "id")
21 | private CardEntity card;
22 |
23 | @Column(nullable = false)
24 | private int level = 1;
25 |
26 | @Column(nullable = false)
27 | private int count = 0;
28 |
29 | public PlayerCardEntity() {
30 | }
31 |
32 | public PlayerCardEntity(PlayerEntity player, CardEntity card, int level, int count) {
33 | this.player = player;
34 | this.card = card;
35 | this.level = level;
36 | this.count = count;
37 | }
38 |
39 | public PlayerEntity getPlayer() {
40 | return player;
41 | }
42 |
43 | public CardEntity getCard() {
44 | return card;
45 | }
46 |
47 | public int getLevel() {
48 | return level;
49 | }
50 |
51 | public PlayerCardEntity setLevel(int level) {
52 | this.level = level;
53 | return this;
54 | }
55 |
56 | public int getCount() {
57 | return count;
58 | }
59 |
60 | public PlayerCardEntity setCount(int count) {
61 | this.count = count;
62 | return this;
63 | }
64 |
65 | public Card getLogicCard() {
66 | return Card.byDB(card.getId());
67 | }
68 |
69 | @Override
70 | public boolean equals(Object o) {
71 | if (this == o) {
72 | return true;
73 | }
74 | if (!(o instanceof PlayerCardEntity)) {
75 | return false;
76 | }
77 |
78 | PlayerCardEntity that = (PlayerCardEntity)o;
79 |
80 | if (player != null ? !player.equals(that.player) : that.player != null) {
81 | return false;
82 | }
83 | return card != null ? card.equals(that.card) : that.card == null;
84 | }
85 |
86 | @Override
87 | public int hashCode() {
88 | int result = player != null ? player.hashCode() : 0;
89 | result = 31 * result + (card != null ? card.hashCode() : 0);
90 | return result;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/PlayerDeckCardEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import royaleserver.logic.Card;
4 |
5 | import javax.persistence.*;
6 | import java.io.Serializable;
7 |
8 | @Entity
9 | @Table(name = "player_deck_card", indexes = {
10 | @Index(unique = true, columnList = "player_id,deck_slot,card_slot")
11 | })
12 | public class PlayerDeckCardEntity implements Serializable {
13 | @Id
14 | @ManyToOne
15 | @PrimaryKeyJoinColumn(name = "player_id", referencedColumnName = "id")
16 | private PlayerEntity player;
17 |
18 | @Id
19 | @Column(name = "deck_slot")
20 | private int deckSlot;
21 |
22 | @Id
23 | @Column(name = "card_slot")
24 | private int cardSlot;
25 |
26 | @ManyToOne(optional = false, fetch = FetchType.LAZY)
27 | private CardEntity card;
28 |
29 | public PlayerDeckCardEntity() {
30 | }
31 |
32 | public PlayerDeckCardEntity(PlayerEntity player, int deckSlot, int cardSlot, CardEntity card) {
33 | this.player = player;
34 | this.deckSlot = deckSlot;
35 | this.cardSlot = cardSlot;
36 | this.card = card;
37 | }
38 |
39 | public PlayerEntity getPlayer() {
40 | return player;
41 | }
42 |
43 | public int getDeckSlot() {
44 | return deckSlot;
45 | }
46 |
47 | public int getCardSlot() {
48 | return cardSlot;
49 | }
50 |
51 | public CardEntity getCard() {
52 | return card;
53 | }
54 |
55 | public void setCard(CardEntity card) {
56 | this.card = card;
57 | }
58 |
59 | public Card getLogicCard() {
60 | return Card.byDB(card.getId());
61 | }
62 |
63 | public void setLogicCard(Card card) {
64 | setCard(card.getDbEntity());
65 | }
66 |
67 | @Override
68 | public boolean equals(Object o) {
69 | if (this == o) {
70 | return true;
71 | }
72 | if (!(o instanceof PlayerDeckCardEntity)) {
73 | return false;
74 | }
75 |
76 | PlayerDeckCardEntity that = (PlayerDeckCardEntity)o;
77 |
78 | if (deckSlot != that.deckSlot) {
79 | return false;
80 | }
81 | if (cardSlot != that.cardSlot) {
82 | return false;
83 | }
84 | return player != null ? player.equals(that.player) : that.player == null;
85 | }
86 |
87 | @Override
88 | public int hashCode() {
89 | int result = player != null ? player.hashCode() : 0;
90 | result = 31 * result + deckSlot;
91 | result = 31 * result + cardSlot;
92 | return result;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/entity/UnlockCodeEntity.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.entity;
2 |
3 | import javax.persistence.*;
4 |
5 | @Entity
6 | @Table(name = "unlock_codes")
7 | @NamedQueries({
8 | @NamedQuery(name = "UnlockCodeEntity.use", query = "DELETE FROM UnlockCodeEntity unlockCode WHERE unlockCode.code=:code")
9 | })
10 | public class UnlockCodeEntity {
11 | public static final int CODE_LENGTH = 12;
12 |
13 | @Id
14 | @Column(unique = true, nullable = false, length = CODE_LENGTH, updatable = false)
15 | private String code;
16 |
17 | public UnlockCodeEntity() {
18 | }
19 |
20 | public UnlockCodeEntity(String code) {
21 | assert code.length() == CODE_LENGTH;
22 | this.code = code;
23 | }
24 |
25 | public String getCode() {
26 | return code;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/ArenaService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.ArenaEntity;
5 |
6 | public class ArenaService extends LogicService {
7 | public ArenaService(SessionFactory sessionFactory) {
8 | super(sessionFactory, ArenaEntity.class);
9 | }
10 |
11 | @Override
12 | protected ArenaEntity createEntity(String name) {
13 | return new ArenaEntity(name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/AssetService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.entity.AssetEntity;
6 | import royaleserver.database.util.Transaction;
7 |
8 | import javax.persistence.NoResultException;
9 | import java.util.Date;
10 |
11 | public class AssetService extends Service {
12 | public AssetService(SessionFactory sessionFactory) {
13 | super(sessionFactory);
14 | }
15 |
16 | public AssetEntity get(String name) {
17 | AssetEntity entity;
18 |
19 | try (Session session = session()) {
20 | try {
21 | entity = session.createNamedQuery("AssetEntity.byName", AssetEntity.class)
22 | .setParameter("name", name)
23 | .getSingleResult();
24 | } catch (NoResultException ignored) {
25 | entity = new AssetEntity();
26 | entity.setName(name);
27 | entity.setLastUpdated(new Date(System.currentTimeMillis()));
28 | }
29 | }
30 |
31 | return entity;
32 | }
33 |
34 | public void update(AssetEntity entity) {
35 | entity.setLastUpdated(new Date(System.currentTimeMillis()));
36 |
37 | try (Session session = session(); Transaction transaction = transaction(session)) {
38 | session.merge(entity);
39 | transaction.commit();
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/CardService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.CardEntity;
5 |
6 | public class CardService extends LogicService {
7 | public CardService(SessionFactory sessionFactory) {
8 | super(sessionFactory, CardEntity.class);
9 | }
10 |
11 | @Override
12 | protected CardEntity createEntity(String name) {
13 | return new CardEntity(name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/ChestService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.ChestEntity;
5 |
6 | public class ChestService extends LogicService {
7 | public ChestService(SessionFactory sessionFactory) {
8 | super(sessionFactory, ChestEntity.class);
9 | }
10 |
11 | @Override
12 | protected ChestEntity createEntity(String name) {
13 | return new ChestEntity(name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/ClanBadgeService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.ClanBadgeEntity;
5 |
6 | public class ClanBadgeService extends LogicService {
7 | public ClanBadgeService(SessionFactory sessionFactory) {
8 | super(sessionFactory, ClanBadgeEntity.class);
9 | }
10 |
11 | @Override
12 | protected ClanBadgeEntity createEntity(String name) {
13 | return new ClanBadgeEntity(name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/ClanRoleService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.ClanRoleEntity;
5 |
6 | public class ClanRoleService extends LogicService {
7 | public ClanRoleService(SessionFactory sessionFactory) {
8 | super(sessionFactory, ClanRoleEntity.class);
9 | }
10 |
11 | @Override
12 | protected ClanRoleEntity createEntity(String name) {
13 | return new ClanRoleEntity(name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/ClanService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.entity.ClanEntity;
6 | import royaleserver.database.entity.ClanType;
7 | import royaleserver.database.util.Transaction;
8 |
9 | import javax.persistence.criteria.CriteriaBuilder;
10 | import javax.persistence.criteria.CriteriaQuery;
11 | import javax.persistence.criteria.Root;
12 | import java.util.List;
13 |
14 | public class ClanService extends Service {
15 | public ClanService(SessionFactory sessionFactory) {
16 | super(sessionFactory);
17 | }
18 |
19 | public ClanEntity add(ClanEntity entity){
20 | try (Session session = session(); Transaction transaction = transaction(session)) {
21 | ClanEntity fromDB = (ClanEntity)session.merge(entity);
22 | transaction.commit();
23 | return fromDB;
24 | }
25 | }
26 |
27 | public void remove(ClanEntity entity) {
28 | try (Session session = session(); Transaction transaction = transaction(session)) {
29 | session.remove(entity);
30 | transaction.commit();
31 | }
32 | }
33 |
34 | public ClanEntity searchById(long id) {
35 | try (Session session = session()) {
36 | return session.createNamedQuery("ClanEntity.byId", ClanEntity.class).setParameter("id", id).getSingleResult();
37 | }
38 | }
39 |
40 | public List searchByName(String name) {
41 | try (Session session = session()) {
42 | return session.createNamedQuery("ClanEntity.byName", ClanEntity.class).setParameter("name", name).getResultList();
43 | }
44 | }
45 |
46 | public List search(String name, int minMembers, int maxMembers, int minTrophies, boolean onlyJoinable) {
47 | try (Session session = session()) {
48 | CriteriaBuilder builder = session.getCriteriaBuilder();
49 | CriteriaQuery query = builder.createQuery(ClanEntity.class);
50 | Root root = query.from(ClanEntity.class);
51 | query.select(root);
52 |
53 | if (name != null && !name.isEmpty()) {
54 | query.where(builder.like(root.get("name"), "%" + name + "%"));
55 | }
56 |
57 | // TODO: Check min and max members
58 |
59 | if (minTrophies != 0) {
60 | query.where(builder.greaterThan(root.get("score"), minTrophies));
61 | }
62 |
63 | if (onlyJoinable) {
64 | query.where(builder.equal(root.get("type"), builder.literal(ClanType.OPEN)));
65 | // TODO: Check members
66 | }
67 |
68 | return session.createQuery(query).getResultList();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/ExpLevelService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.ExpLevelEntity;
5 |
6 | public class ExpLevelService extends LogicService {
7 | public ExpLevelService(SessionFactory sessionFactory) {
8 | super(sessionFactory, ExpLevelEntity.class);
9 | }
10 |
11 | @Override
12 | protected ExpLevelEntity createEntity(String name) {
13 | return new ExpLevelEntity(name);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/HomeChestService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.entity.HomeChestEntity;
6 | import royaleserver.database.util.Transaction;
7 |
8 | public class HomeChestService extends Service {
9 | public HomeChestService(SessionFactory sessionFactory) {
10 | super(sessionFactory);
11 | }
12 |
13 | public void put(HomeChestEntity entity) {
14 | try (Session session = session(); Transaction transaction = transaction(session)) {
15 | session.merge(entity);
16 | transaction.commit();
17 | }
18 | }
19 |
20 | public void delete(HomeChestEntity entity) {
21 | try (Session session = session(); Transaction transaction = transaction(session)) {
22 | session.remove(entity);
23 | transaction.commit();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/LogicService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.entity.LogicEntity;
6 | import royaleserver.database.util.Transaction;
7 |
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | public abstract class LogicService extends Service {
12 | private final Class entityClass;
13 | private final String entityClassName;
14 |
15 | public LogicService(SessionFactory sessionFactory, Class entityClass) {
16 | super(sessionFactory);
17 |
18 | this.entityClass = entityClass;
19 | this.entityClassName = entityClass.getSimpleName();
20 | }
21 |
22 | protected abstract EntityType createEntity(String name);
23 |
24 | public List all() {
25 | try (Session session = session()) {
26 | return session.createNamedQuery(entityClassName + ".all", entityClass).getResultList();
27 | }
28 | }
29 |
30 | public void store(Map entries) {
31 | try (Session session = session(); Transaction transaction = transaction(session)) {
32 | for (Map.Entry entry : entries.entrySet()) {
33 | EntityType entity = createEntity(entry.getKey());
34 | session.save(entity);
35 | entry.setValue(entity);
36 | }
37 |
38 | transaction.commit();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/PlayerCardService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.PlayerCardEntity;
5 |
6 | public class PlayerCardService extends RestfulService {
7 | public PlayerCardService(SessionFactory sessionFactory) {
8 | super(sessionFactory);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/PlayerDeckCardService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.SessionFactory;
4 | import royaleserver.database.entity.PlayerDeckCardEntity;
5 |
6 | public class PlayerDeckCardService extends RestfulService {
7 | public PlayerDeckCardService(SessionFactory sessionFactory) {
8 | super(sessionFactory);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/PlayerService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.entity.PlayerEntity;
6 | import royaleserver.database.util.Transaction;
7 | import royaleserver.logic.Arena;
8 | import royaleserver.logic.ExpLevel;
9 | import royaleserver.utils.StringUtils;
10 |
11 | import java.util.Random;
12 |
13 | public class PlayerService extends Service {
14 | private final Random random = new Random(System.currentTimeMillis());
15 |
16 | public PlayerService(SessionFactory sessionFactory) {
17 | super(sessionFactory);
18 | }
19 |
20 | public PlayerEntity create() {
21 | PlayerEntity playerEntity = new PlayerEntity();
22 | playerEntity.setPassToken(StringUtils.randomString(32, 64));
23 | playerEntity.setTrophies(6400);
24 | playerEntity.setLogicArena(Arena.by("Arena_L9"));
25 | playerEntity.setLogicLastExpLevel(ExpLevel.by(13));
26 | playerEntity.setLogicExpLevel(ExpLevel.by(13));
27 | playerEntity.setGold(10000);
28 | playerEntity.setGems(100000);
29 | playerEntity.setRandomSeed(random.nextLong());
30 | playerEntity.setRareChance(random.nextFloat());
31 | playerEntity.setEpicChance(random.nextFloat());
32 | playerEntity.setLegendaryChance(random.nextFloat());
33 | return add(playerEntity);
34 | }
35 |
36 | public PlayerEntity add(PlayerEntity entity){
37 | try (Session session = session(); Transaction transaction = transaction(session)) {
38 | PlayerEntity fromDB = (PlayerEntity)session.merge(entity);
39 | transaction.commit();
40 | return fromDB;
41 | }
42 | }
43 |
44 | public PlayerEntity get(long id){
45 | try (Session session = session()) {
46 | return session.find(PlayerEntity.class, id);
47 | }
48 | }
49 |
50 | public void update(PlayerEntity entity){
51 | try (Session session = session(); Transaction transaction = transaction(session)) {
52 | session.update(entity);
53 | transaction.commit();
54 | }
55 | }
56 |
57 | public void clear() {
58 | try (Session session = session(); Transaction transaction = transaction(session)) {
59 | session.createNamedQuery(".clear").executeUpdate();
60 | transaction.commit();
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/Service.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.util.CloseableTransaction;
6 | import royaleserver.database.util.Transaction;
7 |
8 | public abstract class Service {
9 | protected final SessionFactory sessionFactory;
10 |
11 | protected Service(SessionFactory sessionFactory) {
12 | this.sessionFactory = sessionFactory;
13 | }
14 |
15 | protected Session session() {
16 | return sessionFactory.openSession();
17 | }
18 |
19 | protected Transaction transaction(Session session) {
20 | return new CloseableTransaction(session.beginTransaction());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/service/UnlockCodeService.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.service;
2 |
3 | import org.hibernate.Session;
4 | import org.hibernate.SessionFactory;
5 | import royaleserver.database.entity.UnlockCodeEntity;
6 | import royaleserver.database.util.Transaction;
7 | import royaleserver.utils.StringUtils;
8 |
9 | public class UnlockCodeService extends Service {
10 | public UnlockCodeService(SessionFactory sessionFactory) {
11 | super(sessionFactory);
12 | }
13 |
14 | /**
15 | * Generate, store, and return random unlock key.
16 | * @return Generated key
17 | */
18 | public String generate() {
19 | String code = StringUtils.randomString(UnlockCodeEntity.CODE_LENGTH);
20 |
21 | try (Session session = session(); Transaction transaction = transaction(session)) {
22 | session.merge(new UnlockCodeEntity(code));
23 | transaction.commit();
24 | }
25 |
26 | return code;
27 | }
28 |
29 | public boolean use(String code) {
30 | boolean result;
31 | try (Session session = session(); Transaction transaction = transaction(session)) {
32 | try {
33 | result = session.createNamedQuery("UnlockCodeEntity.use")
34 | .setParameter("code", code)
35 | .executeUpdate() == 1;
36 | transaction.commit();
37 | } catch (Throwable e) {
38 | e.printStackTrace();
39 | result = false;
40 | }
41 | }
42 |
43 | return result;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/util/AssignedIdentityGenerator.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.util;
2 |
3 | import org.hibernate.engine.spi.SharedSessionContractImplementor;
4 | import org.hibernate.id.IdentityGenerator;
5 |
6 | import java.io.Serializable;
7 |
8 | public class AssignedIdentityGenerator extends IdentityGenerator {
9 | @Override
10 | public Serializable generate(SharedSessionContractImplementor session, Object obj) {
11 | if (obj instanceof Identifiable) {
12 | Identifiable identifiable = (Identifiable)obj;
13 | Serializable id = identifiable.getId();
14 | if (id != null) {
15 | return id;
16 | }
17 | }
18 |
19 | return super.generate(session, obj);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/util/CloseableTransaction.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.util;
2 |
3 | import org.hibernate.Transaction;
4 |
5 | public class CloseableTransaction extends royaleserver.database.util.Transaction {
6 | private final Transaction transaction;
7 |
8 | public CloseableTransaction(Transaction transaction) {
9 | this.transaction = transaction;
10 | }
11 |
12 | @Override
13 | public void commit() {
14 | transaction.commit();
15 | }
16 |
17 | @Override
18 | public void rollback() {
19 | transaction.rollback();
20 | }
21 |
22 | @Override
23 | public void close() {
24 | if (transaction.isActive()) {
25 | transaction.rollback();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/util/Identifiable.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.util;
2 |
3 | import java.io.Serializable;
4 |
5 | public interface Identifiable {
6 | T getId();
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/database/util/Transaction.java:
--------------------------------------------------------------------------------
1 | package royaleserver.database.util;
2 |
3 | public abstract class Transaction implements AutoCloseable {
4 | public abstract void commit();
5 | public abstract void rollback();
6 | public abstract void close();
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/game/CodeEnterPlayer.java:
--------------------------------------------------------------------------------
1 | package royaleserver.game;
2 |
3 | import royaleserver.Server;
4 | import royaleserver.database.entity.PlayerEntity;
5 | import royaleserver.network.NetworkSession;
6 | import royaleserver.network.NetworkSessionHandler;
7 | import royaleserver.network.protocol.client.ClientMessageHandler;
8 | import royaleserver.network.protocol.client.messages.AccountUnlock;
9 | import royaleserver.network.protocol.client.messages.Ping;
10 | import royaleserver.network.protocol.server.messages.AccountUnlockFailed;
11 | import royaleserver.network.protocol.server.messages.AccountUnlockOk;
12 | import royaleserver.network.protocol.server.messages.LoginFailed;
13 |
14 | public class CodeEnterPlayer extends NetworkSession implements ClientMessageHandler {
15 | public CodeEnterPlayer(Server server, NetworkSessionHandler session) {
16 | super(server, session);
17 |
18 | LoginFailed loginFailed = new LoginFailed();
19 | loginFailed.errorCode = LoginFailed.ERROR_CODE_ACCOUNT_BLOCKED;
20 | loginFailed.resourceFingerprintData = "";
21 | loginFailed.redirectDomain = "";
22 | loginFailed.contentURL = "";
23 | loginFailed.updateURL = "";
24 | loginFailed.reason = "";
25 | loginFailed.secondsUntilMaintenanceEnd = 0;
26 | loginFailed.unknown_7 = (byte)0;
27 | loginFailed.unknown_8 = "";
28 | session.sendMessage(loginFailed);
29 | }
30 |
31 | @Override
32 | public boolean handleAccountUnlock(AccountUnlock message) throws Throwable {
33 | if (server.getDataManager().getUnlockCodeService().use(message.unlockCode)) {
34 | AccountUnlockOk response = new AccountUnlockOk();
35 | session.sendMessage(response);
36 |
37 | PlayerEntity playerEntity = server.getDataManager().getPlayerService().create();
38 | session.replace(new Player(playerEntity, server, session));
39 | } else {
40 | AccountUnlockFailed response = new AccountUnlockFailed();
41 | session.sendMessage(response);
42 | }
43 |
44 | return true;
45 | }
46 |
47 | @Override
48 | public boolean handlePing(Ping message) throws Throwable {
49 | // Server do not have to response ping message, when account activation window is opened, so ignore it.
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/game/Deck.java:
--------------------------------------------------------------------------------
1 | package royaleserver.game;
2 |
3 | import royaleserver.database.entity.PlayerDeckCardEntity;
4 |
5 | public final class Deck {
6 | public static final int DECK_CARDS_COUNT = 8;
7 |
8 | private final PlayerCard[] cards = new PlayerCard[DECK_CARDS_COUNT];
9 | private final PlayerDeckCardEntity[] entities = new PlayerDeckCardEntity[DECK_CARDS_COUNT];
10 | private boolean changed = false;
11 |
12 | public Deck() {
13 |
14 | }
15 |
16 | public boolean changed() {
17 | return changed;
18 | }
19 |
20 | /**
21 | * Marks changed to false
22 | * @return old changed value
23 | */
24 | public boolean markUnchanged() {
25 | boolean changed = this.changed;
26 | this.changed = false;
27 | return changed;
28 | }
29 |
30 | public boolean hasCard(PlayerCard card) {
31 | for (int i = 0; i < DECK_CARDS_COUNT; ++i) {
32 | if (cards[i] == card) {
33 | return true;
34 | }
35 | }
36 |
37 | return false;
38 | }
39 |
40 | public PlayerCard getCard(int slot) {
41 | if (slot < 0 || slot >= DECK_CARDS_COUNT) {
42 | throw new IllegalArgumentException("slot");
43 | }
44 |
45 | return cards[slot];
46 | }
47 |
48 | public void swapCards(int slot1, int slot2) {
49 | changed = true;
50 |
51 | if (slot1 < 0 || slot1 >= DECK_CARDS_COUNT) {
52 | throw new IllegalArgumentException("slot1");
53 | }
54 |
55 | if (slot2 < 0 || slot2 >= DECK_CARDS_COUNT) {
56 | throw new IllegalArgumentException("slot2");
57 | }
58 |
59 | PlayerCard temp = cards[slot1];
60 | cards[slot1] = cards[slot2];
61 | cards[slot2] = temp;
62 | }
63 |
64 | public PlayerCard swapCard(int slot, PlayerCard targetCard) {
65 | changed = true;
66 |
67 | if (slot < 0 || slot >= DECK_CARDS_COUNT) {
68 | throw new IllegalArgumentException("slot");
69 | }
70 |
71 | if (targetCard == null) {
72 | throw new IllegalArgumentException("targetCard");
73 | }
74 |
75 | PlayerCard result = cards[slot];
76 | cards[slot] = targetCard;
77 | return result;
78 | }
79 |
80 | public PlayerDeckCardEntity getEntity(int slot) {
81 | if (slot < 0 || slot >= DECK_CARDS_COUNT) {
82 | throw new IllegalArgumentException("slot");
83 | }
84 |
85 | return entities[slot];
86 | }
87 |
88 | public void setEntity(int slot, PlayerDeckCardEntity entity) {
89 | if (slot < 0 || slot >= DECK_CARDS_COUNT) {
90 | throw new IllegalArgumentException("slot");
91 | }
92 |
93 | entities[slot] = entity;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/game/OpeningChest.java:
--------------------------------------------------------------------------------
1 | package royaleserver.game;
2 |
3 | import royaleserver.logic.Card;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.Comparator;
8 | import java.util.List;
9 |
10 | public class OpeningChest {
11 | public static class CardStack {
12 | public final Card card;
13 | public final int count;
14 |
15 | public CardStack(Card card, int count) {
16 | this.card = card;
17 | this.count = count;
18 | }
19 | }
20 |
21 | public static class Builder {
22 | private final int optionSize;
23 |
24 | private final List cards = new ArrayList<>();
25 | private int gold = 0;
26 | private int gems = 0;
27 |
28 | private Builder(int optionSize) {
29 | this.optionSize = optionSize;
30 | }
31 |
32 | public int optionSize() {
33 | return optionSize;
34 | }
35 |
36 | public Builder add(CardStack[] option) {
37 | if (option.length != optionSize) {
38 | throw new RuntimeException("Option length is not right.");
39 | }
40 |
41 | cards.add(option);
42 | return this;
43 | }
44 |
45 | public Builder gold(int gold) {
46 | this.gold = gold;
47 | return this;
48 | }
49 |
50 | public Builder gems(int gems) {
51 | this.gems = gems;
52 | return this;
53 | }
54 |
55 | public OpeningChest build() {
56 | cards.sort(Comparator.comparingInt(a -> a[0].card.getRarity().getSortCapacity() * a[0].count));
57 | return new OpeningChest(cards, gold, gems);
58 | }
59 | }
60 |
61 | private final List cards;
62 | private final List selectedCards;
63 | private final int gold, gems;
64 | private int currentCard = 0;
65 |
66 | private OpeningChest(List cards, int gold, int gems) {
67 | this.cards = Collections.unmodifiableList(cards);
68 | this.selectedCards = new ArrayList<>(cards.size());
69 | this.gold = gold;
70 | this.gems = gems;
71 | }
72 |
73 | public int optionSize() {
74 | return cards.size() == 0 ? 0 : cards.get(0).length;
75 | }
76 |
77 | public List cards() {
78 | return cards;
79 | }
80 |
81 | public List selectedCards() {
82 | return selectedCards;
83 | }
84 |
85 | public int gold() {
86 | return gold;
87 | }
88 |
89 | public int gems() {
90 | return gems;
91 | }
92 |
93 | public CardStack next(int selection) {
94 | CardStack card = null;
95 | if (hasCards()) {
96 | this.selectedCards.add(currentCard, card = cards.get(currentCard)[selection >= optionSize() ? 0 : selection]);
97 | ++currentCard;
98 | }
99 |
100 | return card;
101 | }
102 |
103 | public boolean hasCards() {
104 | return currentCard < cards.size();
105 | }
106 |
107 | public void end() {
108 | while (next(0) != null);
109 | }
110 |
111 | public static Builder builder(boolean draft) {
112 | return new Builder(draft ? 2 : 1);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/game/PlayerCard.java:
--------------------------------------------------------------------------------
1 | package royaleserver.game;
2 |
3 | import royaleserver.logic.Card;
4 | import royaleserver.database.entity.PlayerCardEntity;
5 |
6 | public final class PlayerCard {
7 | private Card card;
8 | private int level;
9 | private int count;
10 |
11 | private PlayerCardEntity entity;
12 |
13 | public PlayerCard(Card card, int level, int count) {
14 | this(card, level, count, null);
15 | }
16 |
17 | public PlayerCard(Card card, int level, int count, PlayerCardEntity entity) {
18 | this.card = card;
19 | this.level = level;
20 | this.count = count;
21 | this.entity = entity;
22 | }
23 |
24 | public Card getCard() {
25 | return card;
26 | }
27 |
28 | public int getLevel() {
29 | return level;
30 | }
31 |
32 | public PlayerCard setLevel(int level) {
33 | this.level = level;
34 | return this;
35 | }
36 |
37 | public int getCount() {
38 | return count;
39 | }
40 |
41 | public PlayerCard setCount(int count) {
42 | this.count = count;
43 | return this;
44 | }
45 |
46 | public PlayerCard addCount(int count) {
47 | this.count += count;
48 | return this;
49 | }
50 |
51 | public PlayerCardEntity getEntity() {
52 | return entity;
53 | }
54 |
55 | public void setEntity(PlayerCardEntity entity) {
56 | this.entity = entity;
57 | }
58 |
59 | @Override
60 | public boolean equals(Object o) {
61 | if (this == o) {
62 | return true;
63 | }
64 | if (!(o instanceof PlayerCard)) {
65 | return false;
66 | }
67 |
68 | PlayerCard that = (PlayerCard)o;
69 |
70 | return card.equals(that.card);
71 | }
72 |
73 | @Override
74 | public int hashCode() {
75 | return card.hashCode();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/logic/ClanBadge.java:
--------------------------------------------------------------------------------
1 | package royaleserver.logic;
2 |
3 | import royaleserver.Server;
4 | import royaleserver.ServerException;
5 | import royaleserver.csv.Column;
6 | import royaleserver.csv.Row;
7 | import royaleserver.csv.Table;
8 | import royaleserver.database.entity.ClanBadgeEntity;
9 | import royaleserver.utils.SCID;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public final class ClanBadge extends DBLogic {
15 | public static final int SCID_HIGH = 16;
16 |
17 | private SCID scid;
18 |
19 | private ClanBadge() {}
20 |
21 | public SCID getScid() {
22 | return scid;
23 | }
24 |
25 |
26 | private static boolean initialized = false;
27 | private static List values = new ArrayList<>();
28 |
29 | public static void init(Server server) throws ServerException {
30 | if (initialized) {
31 | return;
32 | }
33 |
34 | Table csv_badges = server.getAssetManager().open("csv_logic/alliance_badges.csv").csv();
35 | Column csv_Name = csv_badges.getColumn("Name");
36 |
37 | int i = 0;
38 | for (Row csv_badge : csv_badges.getRows()) {
39 | ClanBadge badge = new ClanBadge();
40 |
41 | badge.scid = new SCID(SCID_HIGH, i++);
42 | badge.name = csv_badge.getValue(csv_Name).asString();
43 |
44 | values.add(badge);
45 | }
46 |
47 | init(values, server.getDataManager().getClanBadgeService());
48 |
49 | initialized = true;
50 | }
51 |
52 | public static ClanBadge by(String name) {
53 | for (ClanBadge badge : values) {
54 | if (badge.name.equals(name)) {
55 | return badge;
56 | }
57 | }
58 |
59 | return null;
60 | }
61 |
62 | public static ClanBadge by(SCID scid) {
63 | for (ClanBadge badge : values) {
64 | if (badge.scid.equals(scid)) {
65 | return badge;
66 | }
67 | }
68 |
69 | return null;
70 | }
71 |
72 | public static ClanBadge byDB(long id) {
73 | for (ClanBadge badge : values) {
74 | if (badge.dbId == id) {
75 | return badge;
76 | }
77 | }
78 |
79 | return null;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/logic/DBLogic.java:
--------------------------------------------------------------------------------
1 | package royaleserver.logic;
2 |
3 | import royaleserver.database.entity.LogicEntity;
4 | import royaleserver.database.service.LogicService;
5 |
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | public abstract class DBLogic extends NamedLogic {
11 | protected long dbId;
12 | protected Entity dbEntity;
13 |
14 | public final long getDbId() {
15 | return dbId;
16 | }
17 |
18 | public final Entity getDbEntity() {
19 | return dbEntity;
20 | }
21 |
22 | protected static <
23 | Logic extends DBLogic,
24 | Entity extends LogicEntity,
25 | Service extends LogicService
26 | > void init(List values, Service service) {
27 | final Map entities = new HashMap<>();
28 | final HashMap entitiesToAdd = new HashMap<>();
29 | for (Entity entity : service.all()) {
30 | entities.put(entity.getName(), entity);
31 | }
32 |
33 | for (Logic logic : values) {
34 | LogicEntity entity = entities.getOrDefault(logic.getName(), null);
35 | if (entity == null) {
36 | entitiesToAdd.put(logic.getName(), null);
37 | } else {
38 | logic.dbId = entity.getId();
39 | logic.dbEntity = entity;
40 | }
41 | }
42 |
43 | if (entitiesToAdd.size() > 0) {
44 | service.store(entitiesToAdd);
45 | for (Map.Entry entry : entitiesToAdd.entrySet()) {
46 | for (Logic logic : values) {
47 | if (logic.name.equals(entry.getKey())) {
48 | logic.dbEntity = entry.getValue();
49 | logic.dbId = logic.dbEntity.getId();
50 | break;
51 | }
52 | }
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/logic/ExpLevel.java:
--------------------------------------------------------------------------------
1 | package royaleserver.logic;
2 |
3 | import royaleserver.Server;
4 | import royaleserver.ServerException;
5 | import royaleserver.csv.Column;
6 | import royaleserver.csv.Row;
7 | import royaleserver.csv.Table;
8 | import royaleserver.database.entity.ExpLevelEntity;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public final class ExpLevel extends DBLogic {
14 | private int index;
15 | private int numericName;
16 | private int expToNextLevel;
17 | private int totalExp;
18 |
19 | private ExpLevel() {}
20 |
21 | public int getIndex() {
22 | return index;
23 | }
24 |
25 | public int getNumericName() {
26 | return numericName;
27 | }
28 |
29 | public int getExpToNextLevel() {
30 | return expToNextLevel;
31 | }
32 |
33 | public int getTotalExp() {
34 | return totalExp;
35 | }
36 |
37 | private static boolean initialized = false;
38 | private static List values = new ArrayList<>();
39 |
40 | public static void init(Server server) throws ServerException {
41 | if (initialized) {
42 | return;
43 | }
44 |
45 | Table csv_levels = server.getAssetManager().open("csv_logic/exp_levels.csv").csv();
46 | Column csv_Name = csv_levels.getColumn("Name");
47 | Column csv_ExpToNextLevel = csv_levels.getColumn("ExpToNextLevel");
48 |
49 | int i = 1, totalExp = 0;
50 | for (Row csv_level : csv_levels.getRows()) {
51 | ExpLevel expLevel = new ExpLevel();
52 |
53 | expLevel.index = i++;
54 | expLevel.name = String.valueOf(expLevel.numericName = csv_level.getValue(csv_Name).asInt());
55 | expLevel.expToNextLevel = csv_level.getValue(csv_ExpToNextLevel).asInt();
56 | expLevel.totalExp = totalExp;
57 | totalExp += expLevel.expToNextLevel;
58 |
59 | values.add(expLevel);
60 | }
61 |
62 | init(values, server.getDataManager().getExpLevelService());
63 |
64 | initialized = true;
65 | }
66 |
67 | public static ExpLevel by(int name) {
68 | for (ExpLevel expLevel : values) {
69 | if (expLevel.numericName == name) {
70 | return expLevel;
71 | }
72 | }
73 |
74 | return null;
75 | }
76 |
77 | public static ExpLevel byIndex(int index) {
78 | for (ExpLevel expLevel : values) {
79 | if (expLevel.index == index) {
80 | return expLevel;
81 | }
82 | }
83 |
84 | return null;
85 | }
86 |
87 | public static ExpLevel byDB(long id) {
88 | for (ExpLevel expLevel : values) {
89 | if (expLevel.dbId == id) {
90 | return expLevel;
91 | }
92 | }
93 |
94 | return null;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/logic/Logic.java:
--------------------------------------------------------------------------------
1 | package royaleserver.logic;
2 |
3 | public abstract class Logic {
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/logic/NamedLogic.java:
--------------------------------------------------------------------------------
1 | package royaleserver.logic;
2 |
3 | public abstract class NamedLogic extends Logic {
4 | protected String name;
5 |
6 | public String getName() {
7 | return name;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/network/NetworkServer.java:
--------------------------------------------------------------------------------
1 | package royaleserver.network;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelOption;
6 | import io.netty.channel.EventLoopGroup;
7 | import io.netty.channel.nio.NioEventLoopGroup;
8 | import io.netty.channel.socket.nio.NioServerSocketChannel;
9 | import royaleserver.Server;
10 | import royaleserver.config.Config;
11 | import royaleserver.network.protocol.client.ClientCommandFactory;
12 | import royaleserver.network.protocol.client.ClientMessageFactory;
13 | import royaleserver.network.protocol.server.ServerCommandFactory;
14 | import royaleserver.network.protocol.server.ServerMessageFactory;
15 | import royaleserver.utils.Hex;
16 | import royaleserver.utils.LogManager;
17 | import royaleserver.utils.Logger;
18 |
19 | public final class NetworkServer {
20 | private static final Logger logger = LogManager.getLogger(NetworkServer.class);
21 | public static final byte[] SERVER_KEY = Hex.toByteArray("9e6657f2b419c237f6aeef37088690a642010586a7bd9018a15652bab8370f4f");
22 | public static final byte[] SESSION_KEY = Hex.toByteArray("74794DE40D62A03AC6F6E86A9815C6262AA12BEDD518F883");
23 |
24 | private final Server server;
25 | private EventLoopGroup bossGroup;
26 | private EventLoopGroup workerGroup;
27 | private Channel channel;
28 |
29 | private final boolean requireLoginCode;
30 |
31 | public NetworkServer(Server server, Config config) {
32 | this.server = server;
33 |
34 | requireLoginCode = config.get("server.require_login_code").getAsBoolean();
35 |
36 | ClientCommandFactory.instance.init();
37 | ClientMessageFactory.instance.init();
38 | ServerCommandFactory.instance.init();
39 | ServerMessageFactory.instance.init();
40 | }
41 |
42 | public void start() {
43 | bossGroup = new NioEventLoopGroup();
44 | workerGroup = new NioEventLoopGroup();
45 |
46 | ServerBootstrap bootstrap = new ServerBootstrap();
47 | bootstrap
48 | .group(bossGroup, workerGroup)
49 | .channel(NioServerSocketChannel.class)
50 | .option(ChannelOption.SO_BACKLOG, 1024)
51 | .childOption(ChannelOption.SO_KEEPALIVE, true)
52 | .childHandler(new PlayerInitializer(this));
53 |
54 | try {
55 | channel = bootstrap.bind(server.getConfig().get("server.port").getAsShort()).sync().channel();
56 | } catch (InterruptedException e) {
57 | e.printStackTrace();
58 | }
59 | }
60 |
61 | public void stop() {
62 | }
63 |
64 | public void close() {
65 | try {
66 | channel.closeFuture().sync();
67 | } catch (InterruptedException e) {
68 | e.printStackTrace();
69 | }
70 |
71 | bossGroup.shutdownGracefully();
72 | workerGroup.shutdownGracefully();
73 | }
74 |
75 | public Server getServer() {
76 | return server;
77 | }
78 |
79 | public boolean isRequireLoginCode() {
80 | return requireLoginCode;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/network/NetworkSessionHandler.java:
--------------------------------------------------------------------------------
1 | package royaleserver.network;
2 |
3 | import royaleserver.network.protocol.Message;
4 |
5 | public interface NetworkSessionHandler {
6 | void sendMessage(Message message);
7 | void replace(NetworkSession newSession);
8 | void close();
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/royaleserver/network/PacketDecoder.java:
--------------------------------------------------------------------------------
1 | package royaleserver.network;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.handler.codec.ByteToMessageDecoder;
6 | import royaleserver.crypto.ServerCrypto;
7 | import royaleserver.network.protocol.MessageHeader;
8 | import royaleserver.network.protocol.Messages;
9 | import royaleserver.network.protocol.client.ClientMessage;
10 | import royaleserver.network.protocol.client.ClientMessageFactory;
11 | import royaleserver.utils.DataStream;
12 | import royaleserver.utils.Hex;
13 | import royaleserver.utils.LogManager;
14 | import royaleserver.utils.Logger;
15 |
16 | import java.util.List;
17 |
18 | public class PacketDecoder extends ByteToMessageDecoder {
19 | private static final Logger logger = LogManager.getLogger(PacketDecoder.class);
20 |
21 | private final ServerCrypto crypto;
22 |
23 | private boolean hasHeader = false;
24 | private final MessageHeader header = new MessageHeader();
25 |
26 | public PacketDecoder(ServerCrypto crypto) {
27 | this.crypto = crypto;
28 | }
29 |
30 | @Override
31 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List