1
Fork 0
mirror of https://github.com/Quackster/Havana.git synced 2025-07-02 20:57:47 +00:00

Merge branch 'develop'

This commit is contained in:
Quackster 2023-09-10 11:52:38 +10:00
commit afeed4fd3c
25 changed files with 1034 additions and 240 deletions

View file

@ -12,6 +12,8 @@ import org.alexdev.havana.game.catalogue.collectables.CollectablesManager;
import org.alexdev.havana.game.commands.CommandManager;
import org.alexdev.havana.game.ecotron.EcotronManager;
import org.alexdev.havana.game.effects.EffectsManager;
import org.alexdev.havana.game.encryption.Cryptography;
import org.alexdev.havana.game.encryption.HugeInt15;
import org.alexdev.havana.game.events.EventsManager;
import org.alexdev.havana.game.fuserights.FuserightsManager;
import org.alexdev.havana.game.games.GameManager;
@ -29,9 +31,11 @@ import org.alexdev.havana.game.texts.TextsManager;
import org.alexdev.havana.game.wordfilter.WordfilterManager;
import org.alexdev.havana.messages.MessageHandler;
import org.alexdev.havana.server.mus.MusServer;
import org.alexdev.havana.server.netty.NettyPlayerNetwork;
import org.alexdev.havana.server.netty.NettyServer;
import org.alexdev.havana.server.rcon.RconServer;
import org.alexdev.havana.util.DateUtil;
import org.alexdev.havana.util.StringUtil;
import org.alexdev.havana.util.config.GameConfiguration;
import org.alexdev.havana.util.config.LoggingConfiguration;
import org.alexdev.havana.util.config.ServerConfiguration;
@ -42,9 +46,11 @@ import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import java.io.IOException;
import java.math.BigInteger;
import java.net.UnknownHostException;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;

View file

@ -0,0 +1,178 @@
package org.alexdev.havana.game.encryption;
import java.util.ArrayList;
import java.util.HashMap;
public class Cryptography {
private int[] pR3hu24v5;
private int[] artificialKey;
private int[] tKey;
private int j, i, q;
private String pTableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private HashMap<Integer, Integer> pTableList = new HashMap<>();
public Cryptography(int[] tMyKey) {
//String tMyKeyS = String.valueOf(tMyKey);
this.pR3hu24v5 = new int[256];
this.tKey = new int[256];
this.artificialKey = new int[]{204, 53, 74, 109, 63, 4, 163, 182, 210, 186, 19, 162, 160, 115, 139, 83, 235, 177, 14, 15, 11, 127, 4, 210, 222, 138, 10, 138, 151, 236, 158, 186, 67, 1, 168, 69, 139, 214, 243, 32, 157, 161, 211, 155, 20, 192, 214, 155, 12, 153, 192, 112, 98, 146, 33, 30, 22, 131, 81, 161, 105, 142, 103, 204, 112, 9, 167, 185, 176, 51, 27, 166, 249, 228, 24, 165, 197, 25, 166, 216, 74, 14, 104, 15, 77, 49, 6, 50, 65, 126, 10, 187, 15, 17, 189, 155, 246, 221, 92, 104, 79, 87, 186, 88, 80, 50, 223, 126, 148, 217, 81, 223, 91, 70, 165, 237, 150, 95, 195, 205, 199, 176, 156, 122, 187, 232, 252, 230, 169, 94, 157, 194, 44, 164, 208, 22, 141, 139, 167, 236, 201, 42, 130, 14, 44, 57, 253, 224, 130, 118, 242, 226, 146, 202, 154, 40, 201, 171, 160, 91, 143, 144, 150, 197, 169, 204, 121, 131, 139, 112, 214, 196, 74, 123, 159, 220, 77, 176, 151, 73, 125, 135, 166, 26, 176, 31, 255, 234, 91, 30, 218, 41, 121, 17, 45, 3, 234, 35, 185, 52, 112, 108, 65, 72, 184, 93, 225, 113, 62, 0, 110, 38, 43, 15, 44, 114, 162, 167, 69, 40, 103, 144, 114, 215, 228, 47, 112, 235, 179, 211, 116, 237, 70, 167, 36, 224, 183, 11, 0, 74, 145, 241, 153, 40, 151, 211, 231, 199, 235, 176, 109, 95, 160, 141, 137, 236, 39, 17, 246, 97, 120, 227, 12, 1, 195, 239, 150, 169, 85, 226, 23, 58, 145, 157, 37, 218, 132, 168, 94, 15, 240, 24, 152, 230, 249, 80, 145, 208, 209, 144, 154, 228, 197, 40, 6, 248, 90, 15, 1, 82, 145, 77, 220, 27, 167, 0, 149, 0, 103, 53, 226, 242, 175, 9, 177, 130, 65, 216, 107, 4, 194, 71, 135, 231, 151, 178, 188, 220, 33, 152, 120, 165, 73, 124, 32, 215, 127, 130, 29, 40, 20, 3, 212, 254, 106, 42, 98, 7, 8, 129, 195, 30, 74, 118, 169, 81, 88, 235, 149, 232, 181, 182, 206, 82, 163, 26, 116, 37, 41, 50, 63, 185, 165, 2, 81, 10, 149, 103, 211, 168, 34, 55, 32, 233, 16, 238, 219, 235, 170, 255, 244, 12, 89, 211, 88, 33, 24, 38, 190, 75, 70, 86, 89, 2, 189, 134, 207, 65, 6, 148, 124, 22, 57, 21, 118, 227, 173, 21, 236, 236, 139, 189, 230, 153, 153, 182, 230, 216, 26, 0, 9, 50, 32, 189, 97, 3, 208, 201, 103, 163, 96, 0, 42, 11, 173, 98, 102, 76, 31, 243, 59, 71, 223, 252, 186, 157, 231, 90, 212, 83, 10, 69, 69, 165, 209, 112, 157, 237, 24, 90, 4, 44, 247, 32, 159, 126, 171, 99, 216, 196, 228, 217, 157, 143, 32, 16, 111, 67, 106, 231, 10, 167, 13, 240, 182, 105, 52, 12, 84, 91, 243, 205, 180, 180, 35, 58, 238, 240, 0, 209, 48, 249, 243, 209, 93, 10, 22, 183, 5, 177, 110, 16, 188, 201, 240, 194, 11, 76, 219, 67, 254, 176, 139, 66, 81, 138, 109, 178, 71, 143, 74, 217, 52, 0, 127, 190, 12, 214, 231, 84, 239, 165, 155, 89, 95, 106, 62, 30, 182, 137, 85, 39, 221, 51, 188, 149, 104, 167, 71, 11, 220, 212, 246, 114, 10, 4, 216, 127, 233, 231, 178, 174, 181, 29, 49, 118, 177, 108, 156, 174, 118, 196, 216, 106, 203, 96, 65, 12, 140, 248, 152, 35, 152, 17, 89, 136, 138, 94, 5, 190, 92, 189, 16, 216, 61, 70, 165, 36, 238, 167, 16, 61, 206, 140, 226, 251, 37, 225, 211, 111, 42, 195, 36, 248, 233, 67, 146, 100, 244, 23, 154, 103, 48, 4, 15, 33, 169, 151, 13, 151, 115, 173, 37, 103, 172, 23, 182, 29, 22, 25, 54, 46, 188, 14, 24, 12, 182, 241, 163, 90, 121, 172, 29, 73, 191, 91, 232, 229, 197, 200, 32, 7, 67, 214, 141, 248, 10, 135, 168, 4, 144, 17, 94, 228, 76, 202, 130, 174, 251, 170, 100, 173, 232, 183, 132, 130, 35, 163, 1, 154, 134, 56, 202, 13, 190, 224, 56, 107, 107, 244, 16, 12, 149, 220, 120, 245, 179, 103, 85, 255, 195, 187, 191, 82, 225, 13, 206, 106, 60, 212, 12, 211, 247, 112, 185, 5, 56, 226, 236, 179, 181, 208, 204, 16, 159, 158, 36, 65, 101, 148, 23, 89, 125, 27, 61, 117, 255, 142, 32, 138, 105, 166, 203, 253, 113, 138, 30, 247, 250, 198, 21, 244, 113, 40, 161, 229, 179, 100, 76, 30, 177, 69, 87, 90, 9, 135, 254, 108, 99, 145, 195, 145, 138, 223, 237, 52, 126, 244, 109, 171, 44, 0, 187, 129, 127, 49, 220, 100, 253, 0, 116, 93, 87, 39, 245, 5, 54, 203, 241, 155, 255, 125, 80, 253, 75, 71, 242, 147, 153, 148, 214, 91, 33, 181, 78, 10, 82, 171, 89, 179, 221, 144, 224, 138, 112, 254, 152, 186, 190, 224, 44, 251, 60, 133, 65, 70, 72, 203, 126, 123, 212, 108, 68, 185, 42, 208, 51, 11, 177, 3, 24, 207, 14, 148, 113, 55, 1, 19, 179, 31, 133, 11, 227, 72, 145, 242, 157, 244, 239, 129, 124, 109, 56, 134, 56, 95, 110, 161, 73, 151, 136, 67, 176, 201, 193, 70, 53, 31, 238, 84, 81, 65, 50, 182, 20, 17, 247, 179, 217, 14, 34, 182, 97, 55, 117, 176, 108, 234, 147, 89, 168, 7, 251, 212, 22, 107, 63, 248, 179, 222, 167, 214, 136, 74, 53, 47, 120, 233, 131, 41, 167, 220, 56, 12, 51, 125, 207, 112, 179, 211, 47, 134, 223, 112, 223, 46, 249, 24, 64, 58, 36, 187, 77, 132, 116, 116, 111, 36, 127, 217, 177, 24, 58, 102, 166, 105, 119, 234, 187, 198, 77, 153, 23, 157, 103, 92, 33, 136, 182, 131, 154, 141, 149, 4, 117, 213, 226, 64, 116, 55, 6, 159, 126, 225};
for (int k = 0; k < this.pTableStr.length(); k++) {
this.pTableList.put((int) this.pTableStr.charAt(k), k);
}
int[] tXorVals = new int[] {
109, 87, 120, 70, 82, 74, 110, 71, 74, 53, 84, 57, 83, 105, 48, 79, 77, 86, 118, 69, 66, 66, 109, 56, 108, 97, 105, 104, 88, 107, 78, 56, 71, 109, 72, 54, 102, 117, 118, 55, 108, 100, 90, 104, 76, 121, 71, 82, 82, 75, 67, 99, 71, 122, 122, 105, 80, 89, 66, 97, 74, 111, 109
};
ArrayList<Integer> tModKey = new ArrayList<>();
int l = 0;
for (int value : tMyKey) {
int tVal = value ^ tXorVals[l];
tModKey.add(tVal);
l = (l + 1) % tXorVals.length;
}
for (int q = 0; q < 256; q++) {
tKey[q] = tModKey.get(q % tModKey.size());
pR3hu24v5[q] = q;
}
j = 0;
for (int q = 0; q < 256; q++) {
j = (j + pR3hu24v5[q] + tKey[q]) % 256;
int k = pR3hu24v5[q];
pR3hu24v5[q] = pR3hu24v5[j];
pR3hu24v5[j] = k;
}
this.q = 0;
this.j = 0;
this.i = 0;
String tPrMixString = "NV6VVFPoC7FLDlzDUri3qcOAg9cRoFOmsYR9ffDGy5P8HfF6eekX40SFSVfJ1mDb3lcpYRqdg28sp61eHkPukKbqTu1JsVEKiRavi04YtSzUsLXaYSa5BEGwg5G2OF";
for (l = 1; l <= 52; l++) {
this.AkwGx8bHG2kc1xGG4xbdHPCV0fqvK(tPrMixString);
}
}
public String AkwGx8bHG2kc1xGG4xbdHPCV0fqvK(String tdata) {
int[] tBytes = new int[tdata.length()];
for (int e = 0; e < tdata.length(); e++) {
int a = (int) tdata.charAt(e);
if (a > 255) {
tBytes[e] = (a - (a % 256)) / 256;
if (a % 256 != 0) {
tBytes[e] = a % 256;
}
} else {
tBytes[e] = a;
}
}
int[] tDataOut = new int[tBytes.length];
for (int a = 0; a < tBytes.length; a++) {
q = (q + 1) % 256;
j = (j + pR3hu24v5[q]) % 256;
int temp = pR3hu24v5[q];
pR3hu24v5[q] = pR3hu24v5[j];
pR3hu24v5[j] = temp;
if ((q & 63) == 63) {
int tI = 297 * (q + 67) % 256;
int tJ = (j + pR3hu24v5[tI]) % 256;
temp = pR3hu24v5[tI];
pR3hu24v5[tI] = pR3hu24v5[tJ];
pR3hu24v5[tJ] = temp;
}
int d = pR3hu24v5[((pR3hu24v5[q] + pR3hu24v5[j]) % 256)];
int tResult = tBytes[a] ^ d;
tDataOut[a] = tResult;
}
StringBuilder tCipher = new StringBuilder();
int a = 1;
while (a <= tDataOut.length) {
int tNum1 = tDataOut[(a - 1)];
int tNum2 = (a < tDataOut.length) ? tDataOut[(a)] : 0;
int tNum3 = (a + 1 < tDataOut.length) ? tDataOut[(a + 1)] : 0;
int tByte1 = (tNum1 & 252) / 4;
int tByte2a = (tNum1 & 3) * 16;
int tByte2b = (tNum2 & 240) / 16;
int tByte2 = tByte2a | tByte2b;
tCipher.append(pTableStr.charAt(tByte1)).append(pTableStr.charAt(tByte2));
if (tDataOut.length > a) {
int tByte3a = (tNum2 & 15) * 4;
int tByte3b = (tNum3 & 192) / 64;
int tByte3 = tByte3a | tByte3b;
tCipher.append(pTableStr.charAt(tByte3));
}
if (tDataOut.length > a + 1) {
int tByte4 = tNum3 & 63;
tCipher.append(pTableStr.charAt(tByte4));
}
a += 3;
}
int i = (int) (Math.random() * 256) - 1;
return tCipher.toString();
}
public String kg4R6Jo5xjlqtFGs1klMrK4ZTzb3R(String tdata) {
StringBuilder tCipher = new StringBuilder();
int a = 0;
while (a < tdata.length()) {
ArrayList<Integer> tDataIn = new ArrayList<Integer>();
int tNum1 = pTableList.get((int)tdata.charAt(a));
int tNum2 = pTableList.get((int)tdata.charAt(a + 1));
if (tNum2 < 0) {
tNum2 = 0;
}
int tByte1a = tNum1 * 4;
int tByte1b = (tNum2 & 48) / 16;
int tByte1 = tByte1a | tByte1b;
tDataIn.add(tByte1);
int tNum3 = 0;
if (tdata.length() > (a + 2)) {
tNum3 = pTableList.get((int)tdata.charAt(a + 2));
if (tNum3 < 0) {
tNum3 = 0;
}
int tByte2a = (tNum2 & 15) * 16;
int tByte2b = (tNum3 & 60) / 4;
int tByte2 = tByte2a | tByte2b;
tDataIn.add(tByte2);
}
if (tdata.length() > (a + 3)) {
int tNum4 = pTableList.get((int)tdata.charAt(a + 3));
if (tNum4 < 0) {
tNum4 = 0;
}
int tByte3a = (tNum3 & 3) * 64;
int tByte3b = tNum4 & 63;
int tByte3 = tByte3a | tByte3b;
tDataIn.add(tByte3);
}
a = a + 4;
for (int k = 0; k < tDataIn.size(); k++) {
q = (q + 1) % 256;
j = (j + pR3hu24v5[q]) % 256;
int temp = pR3hu24v5[q];
pR3hu24v5[q] = pR3hu24v5[j];
pR3hu24v5[j] = temp;
if ((q & 63) == 63) {
int tI = 297 * (q + 67) % 256;
int tJ = (j + pR3hu24v5[tI]) % 256;
temp = pR3hu24v5[tI];
pR3hu24v5[tI] = pR3hu24v5[tJ];
pR3hu24v5[tJ] = temp;
}
int d = pR3hu24v5[((pR3hu24v5[q] + pR3hu24v5[j]) % 256) ];
//System.out.println (tDataIn.get(k) + " / " + d);
tCipher.append((char) ((tDataIn.get(k) ^ d)));
}
}
return tCipher.toString();
}
}

View file

@ -2,84 +2,73 @@ package org.alexdev.havana.game.encryption;
import java.math.BigInteger;
import java.util.concurrent.ThreadLocalRandom;
import java.security.SecureRandom;
public class DiffieHellman {
private String clientPrivateKey;
private static final int BITLENGTH = 64;
private BigInteger clientP;
private BigInteger clientG;
private BigInteger publicKey;
private BigInteger privateKey;
private BigInteger sharedKey;
private BigInteger clientP;
private BigInteger clientG;
private String clientPublicKey;
public DiffieHellman() {
this.clientPrivateKey = DiffieHellman.generateRandomNumString(64);
this.privateKey = new BigInteger(this.clientPrivateKey);
this.clientP = new BigInteger(SecurityCode.assign(SecurityCode.getLoginParameter("p")));
this.clientG = new BigInteger(SecurityCode.assign(SecurityCode.getLoginParameter("g")));
this.privateKey = generatePrivateKey();
var adobeClientG = new HugeInt15();
var adobeClientP = new HugeInt15();
adobeClientG.assign(SecurityCode.getLoginParameter("g"), null, true);
adobeClientP.assign(SecurityCode.getLoginParameter("p"), null, true);
this.clientG = new BigInteger(adobeClientG.getString());
this.clientP = new BigInteger(adobeClientP.getString());
this.publicKey = this.computePublicKey(this.privateKey);
}
/**
* Generate shared key.
*
* @param publicKey the ckey
*/
public void generateSharedKey(String publicKey) {
this.clientPublicKey = publicKey;
this.publicKey = new BigInteger(publicKey);
this.sharedKey = this.publicKey.modPow(this.privateKey, this.clientP);
private static BigInteger generatePrivateKey() {
SecureRandom random = new SecureRandom();
BigInteger privateKey;
do {
privateKey = new BigInteger(BITLENGTH, random);
} while (privateKey.compareTo(BigInteger.ZERO) == 0);
return privateKey;
}
private BigInteger computePublicKey(BigInteger privateKey) {
return this.clientG.modPow(privateKey, this.clientP);
}
public static String generateRandomHexString(int len) {
StringBuilder result = new StringBuilder();
private BigInteger computeSharedSecret(BigInteger privateKey, BigInteger publicKey) {
return publicKey.modPow(privateKey, this.clientP);
}
for (int i = 0; i < len; i++) {
int rand = 1 + (int) (ThreadLocalRandom.current().nextDouble() * 254); // 1 - 255
result.append(Integer.toString(rand, 16));
}
return result.toString();
public void generateSharedKey(String publicServerKey) {
this.sharedKey = computeSharedSecret(this.privateKey, new BigInteger(publicServerKey));
}
public static String generateRandomNumString(int len) {
int rand = 0;
StringBuilder result = new StringBuilder();
char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
for (int i = 0; i < len; i++) {
result.append(Character.toString(numbers[ThreadLocalRandom.current().nextInt(numbers.length)]));
result.append(numbers[ThreadLocalRandom.current().nextInt(numbers.length)]);
}
return result.toString();
}
public BigInteger getClientP() {
return clientP;
}
public BigInteger getClientG() {
return clientG;
public BigInteger getPublicKey() {
return publicKey;
}
public BigInteger getPrivateKey() {
return this.privateKey;
}
public BigInteger getPublicKey() {
return this.publicKey;
return privateKey;
}
public BigInteger getSharedKey() {
return sharedKey;
}
public String getClientPublicKey() {
return clientPublicKey;
}
public String getClientPrivateKey() {
return clientPrivateKey;
}
}

View file

@ -0,0 +1,454 @@
package org.alexdev.havana.game.encryption;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class HugeInt15 {
public List<Integer> pData_NxIhNARqldyJyY2PfT03dK8t9OLUR;
private boolean pNegative;
private int pBase;
private int pDigits;
public HugeInt15() {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR = new ArrayList<Integer>();
pNegative = false;
pBase = 10000;
pDigits = Integer.toString(pBase).length() - 1;
}
public void neg() {
if (pNegative) {
pNegative = false;
} else {
pNegative = true;
}
}
public void assign(Object tdata, Object tLimit, boolean tUseKey) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR = new ArrayList<Integer>();
if (tdata instanceof String dataString) {
if (dataString.charAt(0) == '-') {
pNegative = true;
dataString = dataString.substring(1);
} else {
pNegative = false;
}
int i = dataString.length();
while (i > 0) {
String tCoef = dataString.substring(Math.max(0, i - pDigits), i);
i = i - tCoef.length();
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.add(Integer.valueOf(tCoef));
}
} else if (tdata instanceof int[] tIntArray) {
List<Integer> dataList = new ArrayList<>();
for (int j : tIntArray) {
dataList.add(j);
}
pNegative = false;
int tZeroes = 1;
int limit = (tLimit == null) ? dataList.size() : Math.min((int) tLimit, dataList.size());
for (int i = 0; i < limit; i++) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.add(null);
}
for (int i = 1; i <= limit; i++) {
if (dataList.get(i - 1) != 0 || tZeroes == 0) {
if (!tUseKey) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.set(limit - i, dataList.get(i - 1));
} else {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.set(limit - i, SecurityCode.decode(dataList.get(i - 1)));
}
tZeroes = 0;
}
}
}
//System.out.println("pData_NxIhNARqldyJyY2PfT03dK8t9OLUR - " + String.join(",", pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.stream().map(x -> x == null ? "" : x.toString()).toArray(String[]::new)));
}
public int getIntValue(Object tLimit) {
int limit = (tLimit == null) ? 100000000 : (int) tLimit;
int tLimitLo = limit / pBase * 10;
int tLength = pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size();
int tInt = pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(tLength - 1);
int tIndex = tLength - 2;
while (tInt < limit && tIndex >= 0) {
int tCoef = pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(tIndex);
if (tInt < tLimitLo) {
tInt = (tInt * pBase) + tCoef;
} else {
int tCoefMultiplier = 10;
while ((tInt * tCoefMultiplier) < limit) {
tCoefMultiplier = tCoefMultiplier * 10;
}
int tCoefDivider = pBase / tCoefMultiplier;
tInt = (tInt * tCoefMultiplier) + (tCoef / tCoefDivider);
}
tIndex--;
}
return tInt;
}
public String getString() {
if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() == 0) {
return "0";
}
String tStr = "";
for (int i = 0; i < pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size(); i++) {
String tValue = String.valueOf(pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i));
if (i < pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - 1) {
while (tValue.length() < pDigits) {
tValue = "0" + tValue;
}
}
tStr = tValue + tStr;
}
if (pNegative) {
tStr = "-" + tStr;
}
return tStr;
}
public void copyFrom(HugeInt15 tValue) {
pNegative = tValue.pNegative;
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR = new ArrayList<>(tValue.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR);
trim();
}
public void trim() {
for (int i = pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - 1; i >= 0; i--) {
if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i) == 0) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.remove(i);
} else {
break;
}
}
if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.isEmpty()) {
pNegative = false;
}
}
public int[] getIntArray(boolean tUseKey) {
ArrayList<Integer> tData = new ArrayList<>();
for (int i = 0; i < pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size(); i++) {
int tVal = pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - (i + 1));
if (tUseKey) {
tVal = encode(tVal);
}
tData.add(tVal);
}
int[] tArray = new int[tData.size()];
for (int i = 0; i < tData.size(); i++) {
tArray[i] = tData.get(i);
}
return tArray;
}
private int encode(int value) {
return (value < 0) ? (value + 256) : value;
}
public static int[] getByteArray(BigInteger tSharedKey) {
byte[] arr = tSharedKey.toByteArray();
// Remove the "sign bit" at the start that Java adds to the BigInteger so that
// it can match Shockwave's output
if (arr[0] == 0) {
byte[] bytesWithoutSignBit = new byte[arr.length - 1];
System.arraycopy(arr, 1, bytesWithoutSignBit, 0, bytesWithoutSignBit.length);
arr = bytesWithoutSignBit;
}
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
if (arr[i] < 0) {
result[i] = 256 - Math.abs(arr[i]);
} else {
result[i] = arr[i];
}
}
return result;
}
public boolean lessThan(HugeInt15 tValue, boolean tUseSign) {
if (equals(tValue)) {
return false;
}
return !greaterThan(tValue, tUseSign);
}
public boolean greaterThan(HugeInt15 tValue, Boolean tUseSign) {
if (equals(tValue)) {
return false;
}
if (tUseSign == null) {
tUseSign = true;
}
if (tUseSign) {
if (!pNegative && tValue.pNegative) {
return true;
}
if (pNegative && !tValue.pNegative) {
return false;
}
}
if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() > tValue.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size()) {
return tUseSign ? !pNegative : true;
} else if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() < tValue.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size()) {
return tUseSign ? pNegative : false;
}
for (int i = pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - 1; i >= 0; i--) {
if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i) > tValue.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i)) {
return tUseSign ? !pNegative : true;
} else if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i) < tValue.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i)) {
return tUseSign ? pNegative : false;
}
}
return false;
}
public boolean isZero() {
for (int i = 0; i < pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size(); i++) {
if (pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(i) != 0) {
return false;
}
}
return true;
}
/*
public HugeInt15 div(HugeInt15 tDivider, boolean tReturnModulo, boolean tKeepResult) {
if (tDivider.isZero()) {
return null;
}
HugeInt15 tResult = new HugeInt15();
if (lessThan(tDivider, false)) {
if (tReturnModulo) {
tResult.copyFrom(this);
}
return tResult;
}
HugeInt15 tTemp = new HugeInt15();
HugeInt15 tTemp2 = new HugeInt15();
HugeInt15 tRemainder = new HugeInt15();
HugeInt15 tRemainderTemp = new HugeInt15();
tRemainder.copyFrom(this);
int tDividerInt = tDivider.getIntValue(10000);
List<Integer> tResultData = new ArrayList<Integer>();
int tNegResult = 0;
if (tRemainder.pNegative) {
tRemainder.neg();
tNegResult = 1;
}
if (tDivider.pNegative) {
tDivider.neg();
tNegResult = tNegResult ^ 1;
}
int tDividerDigits = tDivider.getLength();
int tDividerIntLength = getIntLength(tDividerInt);
while (!tRemainder.lessThan(tDivider)) {
int tRemainderInt = tRemainder.getIntValue();
int tRemainderDigits = tRemainder.getLength();
int tRemainderIntLength = getIntLength(tRemainderInt);
int tRemainderIntFirstDigits = tRemainderInt;
for (int i = tRemainderIntLength - tDividerIntLength; i >= 1; i--) {
tRemainderIntFirstDigits = tRemainderIntFirstDigits / 10;
}
int tFastCoef;
if (tRemainderIntFirstDigits != tDividerInt) {
tFastCoef = tRemainderInt / tDividerInt;
} else {
String tRemainderStr = tRemainder.getString().substring(0, tDividerDigits);
tRemainderTemp.assign(tRemainderStr, null, false);
if (tDivider.greaterThan(tRemainderTemp)) {
tFastCoef = (tRemainderInt / tDividerInt) - 1;
} else {
tFastCoef = tRemainderInt / tDividerInt;
}
}
int tDigitDelta = tRemainderDigits - tDividerDigits;
int tDigitCount = tDigitDelta % pDigits;
int tFastCoefLength = getIntLength(tFastCoef);
if ((tFastCoefLength + tDividerIntLength) > tRemainderIntLength) {
tDigitCount = tDigitCount + 1;
}
if (tDigitCount == 0) {
tDigitCount = pDigits;
}
for (int i = tFastCoefLength - tDigitCount; i >= 1; i--) {
tFastCoef = tFastCoef / 10;
}
tTemp.copyFrom(tDivider);
tTemp.mul(tFastCoef);
int tAddCount = tRemainder.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size();
for (int i = 1; i <= tAddCount; i++) {
tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.add(0);
}
int tAddCountNew = tAddCount;
while (true) {
int tFastCoef = tRemainderDigit / tDividerDigit;
tTemp2.copyFrom(tDivider);
tTemp2.mul(tFastCoef);
int tDividerIntLength = getIntLength(tDividerDigit);
int tFastCoefLength = getIntLength(tFastCoef);
int tRemainderIntLength = getIntLength(tRemainderDigit);
int tDividerDigits = getDigits(tDividerDigit);
int tRemainderDigits = getDigits(tRemainderDigit);
int tDigitDelta = tRemainderDigits - tDividerDigits;
int tDigitCount = tDigitDelta % pDigits;
if ((tFastCoefLength + tDividerIntLength) > tRemainderIntLength) {
tDigitCount = tDigitCount + 1;
}
if (tDigitCount == 0) {
tDigitCount = pDigits;
}
if (tDigitCount > tDigitDelta) {
tDigitCount = tDigitCount - pDigits;
}
int tValidValue = 0;
tTemp.copyFrom(tDivider);
tTemp.mul(tFastCoef);
for (int i = 1; i <= tDigitCount; i++) {
tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(1, 0);
if (tTemp.greaterThan(tRemainder)) {
tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.removeAt(1);
tValidValue = 1;
next repeat;
}
}
if (!tValidValue) {
tTemp2.copyFrom(tDivider);
tTemp2.mul(tFastCoef - 1);
int tTemp2IntLength = getIntLength(tTemp2);
if ((tTemp2IntLength + tDividerIntLength) > tRemainderIntLength) {
tDigitCount = tDigitCount - pDigits;
}
tTemp2.copyFrom(tDivider);
tTemp2.mul(tFastCoef - 1);
for (int i = 1; i <= tDigitCount; i++) {
tTemp2.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(1, 0);
}
if (tTemp2.greaterThan(tRemainder)) {
tFastCoef = tFastCoef - 1;
tValidValue = 1;
}
}
if (!tValidValue) {
tTemp.copyFrom(tDivider);
tTemp.mul(tFastCoef + 1);
for (int i = 1; i <= tDigitCount; i++) {
if (tDividerDigits == pDigits) {
tTempInt = tRemainder.getIntValue(tRemainderDigits - tDividerDigits + 1);
} else {
tTempString = "";
for (int j = 0; j < tDividerDigits; j++) {
int tIndex = tRemainderDigits - tDividerDigits + j + 1;
if (tIndex <= tRemainderDigits) {
tTempString += Integer.toString(tRemainder.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.get(tIndex));
}
}
tTempInt = Integer.parseInt(tTempString);
}
tFastCoef = tTempInt / tDividerInt;
tTemp.copyFrom(tDivider);
tTemp.mul(tFastCoef);
tAddCountNew = tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - tRemainderDigits;
if (tAddCountNew > 0) {
int tTempCount = tAddCountNew - tAddCount;
for (int j = 1; j <= tTempCount; j++) {
tResultData.add(0);
}
tAddCount = tAddCountNew;
}
if (tAddCount > 0) {
for (int j = 1; j <= tAddCount; j++) {
tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(1, 0);
}
}
boolean tValidValue = false;
if (!tTemp.greaterThan(tRemainder)) {
if (tAddCountNew == tAddCount) {
tFastCoef--;
tValidValue = true;
} else {
tTemp2.copyFrom(tDivider);
tTemp2.mul(tFastCoef);
for (int j = 1; j <= tAddCount - 1; j++) {
tTemp2.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(1, 0);
}
if (tTemp2.greaterThan(tTemp)) {
tAddCount--;
} else {
tFastCoef--;
tValidValue = true;
}
}
} else {
tAddCount--;
}
if (!tValidValue) {
tTemp.copyFrom(tDivider);
tTemp.mul(tFastCoef);
for (int j = 1; j <= tAddCount; j++) {
tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(1, 0);
}
}
tResultData.add(tFastCoef);
tRemainder = tRemainder.dif(tTemp);
if (tRemainder.isZero()) {
for (int j = 1; j <= tAddCount; j++) {
tResultData.add(0);
}
break;
}
if (!tRemainder.lessThan(tDivider)) {
tFastCoef = tFastCoef + 1;
tTemp.copyFrom(tDivider);
tTemp.add(tDivider);
while (tTemp.lessThan(tRemainder)) {
tFastCoef = tFastCoef + 1;
tTemp.add(tDivider);
}
tTemp.sub(tDivider);
int tAddCountNew = tRemainder.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size() - tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.size();
if (tAddCountNew > tAddCount) {
tAddCount = tAddCountNew;
}
tValidValue = 0;
if (!tTemp.greaterThan(tRemainder)) {
if (tAddCountNew == tAddCount) {
tFastCoef = tFastCoef - 1;
tValidValue = 1;
} else {
tTemp2.copyFrom(tDivider);
tTemp2.mul(tFastCoef);
for (int i = 1; i <= tAddCount - 1; i++) {
tTemp2.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(0, 0);
}
if (tTemp2.greaterThan(tTemp)) {
tAddCount = tAddCount - 1;
} else {
tFastCoef = tFastCoef - 1;
tValidValue = 1;
}
}
} else {
tAddCount = tAddCount - 1;
}
if (tValidValue == 0) {
tTemp.copyFrom(tDivider);
tTemp.mul(tFastCoef);
for (int i = 1; i <= tAddCount; i++) {
tTemp.pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.addAt(0, 0);
}
}
}
*/
}

View file

@ -1,61 +1,29 @@
package org.alexdev.havana.game.encryption;
import java.util.ArrayList;
import java.util.List;
public class SecurityCode {
// 366592457230440492243310979215656075163725460776
public static String assign(Object obj) {
List<String> pData_NxIhNARqldyJyY2PfT03dK8t9OLUR = new ArrayList<>();
if (obj instanceof String) {
String hex = (String) obj;
String tData = hex;
if (hex.toCharArray()[0] == '-') {
tData = hex.substring(1);
}
int i = tData.length();
int pDigits = "10000".length() - 1;
while (i > 0) {
String tCoef = tData.substring(Math.max(0, i - (pDigits)), i);
i = i - tCoef.length();
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.add("" + Integer.parseInt(tCoef));
}
public static int encode(int tPlain) {
int tSeed = 5678;
int[] tSBox = new int[]{7530, 6652, 4115, 1750, 3354, 3647, 5188, 2844, 818, 2026, 7133, 2592, 3578};
int tIterations = 54;
int tCipher = tPlain;
for (int i = 1; i <= tIterations; i++) {
tSeed = ((69069 * tSeed) + (139 * i) + 92541) % 10000;
tSeed = tSeed + (int) Math.pow(i, 3);
tSeed = ((tSBox[(i % tSBox.length)] * tSeed) + 2541) % 10000;
tCipher = (tSeed ^ tCipher);
tCipher = (1379 + tSBox[(i % tSBox.length)]) ^ tCipher;
tCipher = (((14 * tSBox[(i % tSBox.length)]) + 13) % 10000) ^ tCipher;
tCipher = tCipher * 2;
int tHighBit = tCipher & 32768;
tCipher = tCipher & 32767;
tCipher = tCipher | (tHighBit != 0 ? 1 : 0);
}
if (obj instanceof int[]) {
int[] parameters = (int[]) obj;
int tLimit = parameters.length;
for (int tdata : parameters) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.add("");
}
/*int i = 0;
for (int tdata : parameters) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.add("" + decode(tdata));
i++;
}
Collections.reverse(pData_NxIhNARqldyJyY2PfT03dK8t9OLUR);*/
int i = 0;
for (int tdata : parameters) {
pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.set(tLimit - i - 1, "" + decode(tdata));
i++;
}
//Collections.reverse(pData_NxIhNARqldyJyY2PfT03dK8t9OLUR);
}
return String.join("", pData_NxIhNARqldyJyY2PfT03dK8t9OLUR);//Arrays.toString(pData_NxIhNARqldyJyY2PfT03dK8t9OLUR.toArray());
tCipher = 7639 ^ tCipher;
return tCipher;
}
private static int decode(int tInput) {
public static int decode(int tInput) {
int tSeed = 5678;
int[] tSBox = new int[]{7530, 6652, 4115, 1750, 3354, 3647, 5188, 2844, 818, 2026, 7133, 2592, 3578};

View file

@ -260,9 +260,11 @@ public abstract class Game {
var gameHistoryData = new GameHistoryData();
var gameHistory = new GameHistory(gameHistoryData);
this.teams.values().forEach(GameTeam::calculateScore);
if (this.teams.size() > 0) {
var sortedTeamList = new ArrayList<>(this.teams.values());
sortedTeamList.sort(Comparator.comparingInt(GameTeam::getScore).reversed());
List<GameTeam> sortedTeamList = new ArrayList<>(this.teams.values());
sortedTeamList.sort(Comparator.comparingInt(GameTeam::getPoints).reversed());
var winningTeam = sortedTeamList.get(0);
@ -270,13 +272,14 @@ public abstract class Game {
for (GameTeam team : sortedTeamList) {
for (GamePlayer gamePlayer : team.getPlayers()) {
gamePlayer.calculateScore();
gameHistoryData.addPlayer(gamePlayer.getUserId(), gamePlayer.getScore(), gamePlayer.getTeamId());
}
}
gameHistory.setName(this.getName());
gameHistory.setWinningTeam(winningTeam.getId());
gameHistory.setWinningTeamScore(winningTeam.getScore());
gameHistory.setWinningTeamScore(winningTeam.getPoints());
gameHistory.setGameType(this.gameType);
gameHistory.setMapId(this.getMapId());
@ -769,9 +772,9 @@ public abstract class Game {
* Method called when the game initially began
*/
public void gamePrepare() {
for (GameTeam gameTeam : this.getTeams().values()) {
gameTeam.setScore(0);
}
// for (GameTeam gameTeam : this.getTeams().values()) {
// gameTeam.setScore(0);
// }
for (GamePlayer gamePlayer : this.getActivePlayers()) {
gamePlayer.setXp(0);

View file

@ -10,6 +10,7 @@ import org.alexdev.havana.game.games.battleball.objects.PlayerUpdateObject;
import org.alexdev.havana.game.games.battleball.objects.PowerUpUpdateObject;
import org.alexdev.havana.game.games.enums.GameState;
import org.alexdev.havana.game.games.player.GamePlayer;
import org.alexdev.havana.game.games.player.GameTeam;
import org.alexdev.havana.game.pathfinder.Position;
import org.alexdev.havana.game.pathfinder.Rotation;
import org.alexdev.havana.game.player.Player;
@ -50,6 +51,7 @@ public class BattleBallTask implements Runnable {
this.game.getObjectsQueue().drainTo(objects);
this.game.getUpdateTilesQueue().drainTo(updateTiles);
this.game.getFillTilesQueue().drainTo(fillTiles);
this.game.getTeams().values().forEach(GameTeam::calculateScore);
for (GamePlayer gamePlayer : this.game.getActivePlayers()) {
Player player = gamePlayer.getPlayer();

View file

@ -11,6 +11,8 @@ import org.alexdev.havana.game.pathfinder.Position;
import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.game.games.snowstorm.util.SnowStormAttributes;
import java.util.concurrent.atomic.AtomicInteger;
public class GamePlayer {
private Player player;
private GameObject gameObject;
@ -27,7 +29,7 @@ public class GamePlayer {
private GamePlayer harlequinPlayer;
private boolean assignedSpawn;
private int score;
private AtomicInteger score;
private int xp;
private SnowStormAttributes snowStormAttributes;
@ -42,7 +44,7 @@ public class GamePlayer {
this.enteringGame = false;
this.clickedRestart = false;
this.position = new Position();
this.score = 0;
this.score = new AtomicInteger(0);
this.xp = 0;
this.snowStormAttributes = new SnowStormAttributes();
}
@ -53,7 +55,7 @@ public class GamePlayer {
* @param score the score
*/
public void setScore(int score) {
this.score = score;
this.score.set(score);
}
/**
@ -61,13 +63,15 @@ public class GamePlayer {
*
* @return the score
*/
public int getScore() {
public void calculateScore() {
if (!this.inGame) {
return 0;
this.score.set(0);
return;
}
if (this.getGame() instanceof BattleBallGame) {
this.score = 0;
this.score.set(0);
BattleBallGame battleBallGame = (BattleBallGame) this.getGame();
for (BattleBallTile battleBallTile : battleBallGame.getTiles()) {
@ -76,12 +80,14 @@ public class GamePlayer {
continue;
}
this.score += scoreReference.getScore();
this.score.addAndGet(scoreReference.getScore());
}
}
}
}
return this.score;
public int getScore() {
return score.get();
}
/**

View file

@ -7,19 +7,22 @@ import org.alexdev.havana.game.games.utils.ScoreReference;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class GameTeam {
private int id;
private Game game;
private List<GamePlayer> playerList;
private int score;
public AtomicInteger points;
public AtomicInteger snowstormPoints;
public GameTeam(int id, Game game) {
this.id = id;
this.game = game;
this.playerList = new CopyOnWriteArrayList<>();
this.score = 0;
this.points = new AtomicInteger(0);
}
public int getId() {
@ -30,10 +33,10 @@ public class GameTeam {
return playerList;
}
public int getScore() {
if (this.game instanceof BattleBallGame) {
this.score = 0;
public void calculateScore() {
this.points.set(0);
if (this.game instanceof BattleBallGame) {
BattleBallGame battleBallGame = (BattleBallGame) this.game;
for (BattleBallTile battleBallTile : battleBallGame.getTiles()) {
@ -42,18 +45,27 @@ public class GameTeam {
continue;
}
this.score += scoreReference.getScore();
this.points.addAndGet(scoreReference.getScore());
}
}
}
return this.score;
else {
this.points.set(0);
int totalScore = this.playerList.stream()
.mapToInt(player -> player.getScore())
.sum();
this.points.addAndGet(totalScore);
}
}
public void setScore(int score) {
this.score = score;
public int getPoints() {
return points.get();
}
public List<GamePlayer> getActivePlayers() {
return playerList.stream().filter(GamePlayer::isInGame).collect(Collectors.toList());
}

View file

@ -116,7 +116,8 @@ public class SnowStormGame extends Game {
}
for (GameTeam team : this.getTeams().values()) {
team.setScore(team.getPlayers().stream().mapToInt(GamePlayer::getScore).sum());
team.calculateScore();
// team.setScore(team.getPlayers().stream().mapToInt(GamePlayer::getScore).sum());
}
super.finishGame();

View file

@ -24,12 +24,12 @@ import java.util.UUID;
public class GameFinishTask implements Runnable {
private final List<GamePlayer> players;
private final ArrayList<GameTeam> sortedTeamList;
private final List<GameTeam> sortedTeamList;
private final GameType gameType;
private final Game game;
private final GameHistory gameHistory;
public GameFinishTask(Game game, GameHistory gameHistory, GameType gameType, ArrayList<GameTeam> sortedTeamList, List<GamePlayer> players) {
public GameFinishTask(Game game, GameHistory gameHistory, GameType gameType, List<GameTeam> sortedTeamList, List<GamePlayer> players) {
this.game = game;
this.gameHistory = gameHistory;
this.gameType = gameType;
@ -58,8 +58,8 @@ public class GameFinishTask implements Runnable {
if (this.game.canIncreasePoints()) {
if ((this.sortedTeamList.size() == 1 && this.sortedTeamList.get(0).getPlayers().size() > 1) || (this.sortedTeamList.size() > 1
&& this.sortedTeamList.get(0).getScore() > 0
&& this.sortedTeamList.get(0).getScore() != this.sortedTeamList.get(1).getScore()) &&
&& this.sortedTeamList.get(0).getPoints() > 0
&& this.sortedTeamList.get(0).getPoints() != this.sortedTeamList.get(1).getPoints()) &&
this.sortedTeamList.get(0).getPlayers().size() > 0 &&
this.sortedTeamList.get(1).getPlayers().size() > 0) {

View file

@ -81,7 +81,7 @@ public class FinishedGame {
private List<Pair<String, Integer>> playerScores;
private FinishedGameTeam(GameTeam gameTeam) {
this.score = gameTeam.getScore();
this.score = gameTeam.getPoints();
this.playerScores = new ArrayList<>();
for (var gamePlayer : gameTeam.getPlayers()) {

View file

@ -6,8 +6,8 @@ import org.alexdev.havana.game.achievements.user.UserAchievementManager;
import org.alexdev.havana.game.badges.BadgeManager;
import org.alexdev.havana.game.club.ClubSubscription;
import org.alexdev.havana.game.effects.Effect;
import org.alexdev.havana.game.encryption.Cryptography;
import org.alexdev.havana.game.encryption.DiffieHellman;
import org.alexdev.havana.game.encryption.RC4;
import org.alexdev.havana.game.entity.Entity;
import org.alexdev.havana.game.entity.EntityType;
import org.alexdev.havana.game.fuserights.Fuseright;
@ -33,12 +33,14 @@ import org.alexdev.havana.messages.outgoing.openinghours.INFO_HOTEL_CLOSING;
import org.alexdev.havana.messages.outgoing.user.settings.HELP_ITEMS;
import org.alexdev.havana.messages.types.MessageComposer;
import org.alexdev.havana.server.netty.NettyPlayerNetwork;
import org.alexdev.havana.server.netty.ServerHandlerType;
import org.alexdev.havana.util.DateUtil;
import org.alexdev.havana.util.StringUtil;
import org.alexdev.havana.util.config.GameConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
@ -60,18 +62,16 @@ public class Player extends Entity {
private CopyOnWriteArrayList<Effect> effects;
private Set<String> ignoredList;
private DiffieHellman diffieHellman;
private RC4 rc4;
private boolean loggedIn;
private boolean disconnected;
private boolean pingOK;
private boolean hasGenerateKey;
private long timeConnected;
private boolean processLoginSteps;
private List<Group> joinedGroups;
private String lastGift;
private boolean hasEncryption;
public Player(NettyPlayerNetwork nettyPlayerNetwork) {
this.network = nettyPlayerNetwork;
@ -494,6 +494,20 @@ public class Player extends Entity {
return diffieHellman;
}
/*
* Sets the rc4.
*
* @param sharedKey the new rc4
*/
public void setDecoder(BigInteger sharedKey) {
this.hasEncryption = true;
this.network.registerHandler(ServerHandlerType.RC4, sharedKey);
}
public boolean hasEncryption() {
return hasEncryption;
}
/**
* Get the list of user activated effects.
*
@ -503,24 +517,6 @@ public class Player extends Entity {
return effects;
}
/**
* Get if the user has used the generate key
*
* @return true, if successful
*/
public boolean hasGenerateKey() {
return hasGenerateKey;
}
/**
* Set whether the user has generated the key
*
* @param hasGenerateKey the flag
*/
public void setHasGenerateKey(boolean hasGenerateKey) {
this.hasGenerateKey = hasGenerateKey;
}
/**
* Get the user ignored list.
*

View file

@ -1,11 +1,13 @@
package org.alexdev.havana.messages.incoming.handshake;
import org.alexdev.havana.game.encryption.DiffieHellman;
import org.alexdev.havana.game.encryption.HugeInt15;
import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.messages.outgoing.handshake.SECRET_KEY;
import org.alexdev.havana.messages.types.MessageEvent;
import org.alexdev.havana.server.netty.streams.NettyRequest;
import java.util.Arrays;
public class GENERATEKEY implements MessageEvent {
@Override
@ -15,10 +17,15 @@ public class GENERATEKEY implements MessageEvent {
}
String publicKey = reader.readString();
player.getDiffieHellman().generateSharedKey(publicKey);
player.setHasGenerateKey(true);
player.send(new SECRET_KEY(DiffieHellman.generateRandomNumString(24)));//player.getDetails()));
player.send(new SECRET_KEY(player.getDiffieHellman().getPublicKey().toString()));
player.setDecoder(player.getDiffieHellman().getSharedKey());
//System.out.println("publicKey: " + publicKey);
//System.out.println("adobeClientSharedKey: " + adobeClientSharedKey.getString());
//System.out.println("sharedKey: " + player.getDiffieHellman().getSharedKey());
//System.out.println("sharedKey byte array: " + Arrays.toString(HugeInt15.getByteArray(player.getDiffieHellman().getSharedKey())));
}
}

View file

@ -1,9 +1,9 @@
package org.alexdev.havana.messages.incoming.handshake;
import org.alexdev.havana.game.GameScheduler;
import org.alexdev.havana.game.encryption.DiffieHellman;
import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.messages.outgoing.handshake.CRYPTO_PARAMETERS;
import org.alexdev.havana.messages.outgoing.handshake.SESSION_PARAMETERS;
import org.alexdev.havana.messages.types.MessageEvent;
import org.alexdev.havana.server.netty.streams.NettyRequest;
@ -17,33 +17,10 @@ public class INIT_CRYPTO implements MessageEvent {
return;
}
//String prime = Util.getRSA().sign(dh.getPrime().toString());
//String generator = Util.getRSA().sign(dh.getGenerator().toString());
String pToken = DiffieHellman.generateRandomNumString(24);
//player.sendObject("DAQBHIIIKHJIPAIQAdd-MM-yyyy\u0002SAHPB/client\u0002QBHIJWVVVSNKQCFUBJASMSLKUUOJCOLJQPNSBIRSVQBRXZQOTGPMNJIHLVJCRRULBLUO" + (char)1);
player.send(new CRYPTO_PARAMETERS());
// Try again
this.retrySend(player);
player.send(new CRYPTO_PARAMETERS(pToken));
player.getNetwork().setToken(pToken);
}
/**
* Retry sending the crypto parameters if after a second we received no response from the client.
*
* @param player the player to send the parameters to
*/
private void retrySend(Player player) {
GameScheduler.getInstance().getService().schedule(() -> {
if (player.isDisconnected()) {
return;
}
if (player.hasGenerateKey()) {
return;
}
player.send(new CRYPTO_PARAMETERS());
}, 1, TimeUnit.SECONDS);
}
}

View file

@ -34,7 +34,7 @@ public class GAMEEND extends MessageComposer {
response.writeInt(gamePlayer.getScore());
}
response.writeInt(team.getScore());
response.writeInt(team.getPoints());
}
}
}

View file

@ -83,7 +83,7 @@ public class GAMESTATUS extends MessageComposer {
response.writeInt(this.gameTeams.size());
for (GameTeam team : this.gameTeams) {
response.writeInt(team.getScore());
response.writeInt(team.getPoints());
}
response.writeInt(1);

View file

@ -5,11 +5,16 @@ import org.alexdev.havana.messages.types.MessageComposer;
import org.alexdev.havana.server.netty.streams.NettyResponse;
public class CRYPTO_PARAMETERS extends MessageComposer {
private String token;
public CRYPTO_PARAMETERS(String token) {
this.token = token;
}
@Override
public void compose(NettyResponse response) {
response.writeString(DiffieHellman.generateRandomNumString(32));
response.writeInt(0);
response.writeString(this.token);
response.writeBool(true);
}
@Override

View file

@ -29,8 +29,8 @@ public class NettyChannelInitializer extends ChannelInitializer<SocketChannel> {
pipeline.addLast("trafficShapingHandler", new ChannelTrafficShapingHandler(bandwidthLimit, bandwidthLimit));
}
pipeline.addLast("gameEncoder", new NetworkEncoder());
pipeline.addLast("gameDecoder", new NetworkDecoder());
pipeline.addLast("networkEncoder", new NetworkEncoder());
pipeline.addLast("networkDecoder", new NetworkDecoder());
pipeline.addLast("handler", new ConnectionHandler(this.nettyServer));
pipeline.addLast("idleStateHandler", new IdleStateHandler(60, 0, 0));
pipeline.addLast("idleHandler", new IdleConnectionHandler());

View file

@ -1,25 +1,109 @@
package org.alexdev.havana.server.netty;
import io.netty.channel.Channel;
import org.alexdev.havana.Havana;
import org.alexdev.havana.dao.mysql.PlayerDao;
import org.alexdev.havana.game.player.PlayerManager;
import org.alexdev.havana.util.StringUtil;
import org.alexdev.havana.util.config.ServerConfiguration;
import org.alexdev.havana.server.netty.codec.EncryptionDecoder;
import org.alexdev.havana.server.netty.codec.EncryptionEncoder;
import org.apache.commons.validator.routines.InetAddressValidator;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
public class NettyPlayerNetwork {
private Channel channel;
private int connectionId;
private boolean saveMachineId;
private String clientMachineId;
private String pToken;
private int pTx;
private int pRx;
public NettyPlayerNetwork(Channel channel, int connectionId) {
this.channel = channel;
this.connectionId = connectionId;
}
public static String removePadding(String tBody, int i) {
if (i >= tBody.length())
return tBody;
return tBody.substring(i);
}
public static String addPad(String tMsg, int amount) {
var secureRandom = new SecureRandom();
for (int i = 0; i < amount; i++) {
tMsg = Character.toString(secureRandom.nextInt(255) + 1) + tMsg;
}
return tMsg;
}
public void setToken(String tToken) {
this.pToken = tToken;
String tSeedHex = pToken.substring(pToken.length() - 4);
Map<String, Integer> tVals = new HashMap<>();
tVals.put("0", 0);
tVals.put("1", 1);
tVals.put("2", 2);
tVals.put("3", 3);
tVals.put("4", 4);
tVals.put("5", 5);
tVals.put("6", 6);
tVals.put("7", 7);
tVals.put("8", 8);
tVals.put("9", 9);
tVals.put("a", 10);
tVals.put("b", 11);
tVals.put("c", 12);
tVals.put("d", 13);
tVals.put("e", 14);
tVals.put("f", 15);
tVals.put("A", 10);
tVals.put("B", 11);
tVals.put("C", 12);
tVals.put("D", 13);
tVals.put("E", 14);
tVals.put("F", 15);
this.pTx = 0;
for (int i = 0; i <= 3; i++) {
this.pTx += (int)(Math.pow(16, i) * tVals.get(Character.toString(tSeedHex.charAt(3 - i))));
}
this.pRx = 0;
tSeedHex = pToken.substring(0, 4);
for (int i = 0; i <= 3; i++) {
this.pRx += (int)(Math.pow(16, i) * tVals.get(Character.toString(tSeedHex.charAt(3 - i))));
}
}
public static int iterateRandom(int tSeed) {
return ((19979 * tSeed) + 5) % 65536;
}
public int getTx() {
return pTx;
}
public int getRx() {
return pRx;
}
public void setTx(int pTx) {
this.pTx = pTx;
}
public void setRx(int pRx) {
this.pRx = pRx;
}
public Channel getChannel() {
return this.channel;
}
@ -73,4 +157,11 @@ public class NettyPlayerNetwork {
this.saveMachineId = saveMachineId;
}
public void registerHandler(ServerHandlerType type, Object object) {
if (type == ServerHandlerType.RC4) {
this.channel.pipeline().addBefore("networkDecoder", "encryptionDecoder", new EncryptionDecoder((BigInteger) object));
this.channel.pipeline().addBefore("networkEncoder", "encryptionEncoder", new EncryptionEncoder((BigInteger) object));
// this.channel.pipeline().remove("gameDecoder");
}
}
}

View file

@ -4,26 +4,72 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.alexdev.havana.game.encryption.RC4;
import org.alexdev.havana.game.encryption.Cryptography;
import org.alexdev.havana.game.encryption.HugeInt15;
import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.server.netty.NettyPlayerNetwork;
import org.alexdev.havana.server.netty.streams.NettyRequest;
import org.alexdev.havana.util.StringUtil;
import org.alexdev.havana.util.encoding.Base64Encoding;
import java.math.BigInteger;
import java.util.List;
public class EncryptionDecoder extends ByteToMessageDecoder {
private Cryptography pHeaderDecoder;
private Cryptography pDecoder;
private RC4 rc4;
public EncryptionDecoder(RC4 rc4) {
this.rc4 = rc4;
public EncryptionDecoder(BigInteger sharedKey) {
this.pHeaderDecoder = new Cryptography(HugeInt15.getByteArray(sharedKey));
this.pDecoder = new Cryptography(HugeInt15.getByteArray(sharedKey));
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
ByteBuf result = Unpooled.buffer();
Player player = ctx.channel().attr(Player.PLAYER_KEY).get();
while (buffer.readableBytes() > 0) {
result.writeByte((byte) (buffer.readByte() ^ this.rc4.next()));
String tHeader;
String tBody;
int pMsgSize;
buffer.markReaderIndex();
while (buffer.readableBytes() > 6) {
byte[] tHeaderMsg = new byte[6];
buffer.readBytes(tHeaderMsg);
tHeader = new String(tHeaderMsg, StringUtil.getCharset());
tHeader = this.pHeaderDecoder.kg4R6Jo5xjlqtFGs1klMrK4ZTzb3R(tHeader);
int tByte1 = ((int) tHeader.charAt(3)) & 63;
int tByte2 = ((int) tHeader.charAt(2)) & 63;
int tByte3 = ((int) tHeader.charAt(1)) & 63;
pMsgSize = (tByte2 * 64) | tByte1;
pMsgSize = (tByte3 * 64 * 64) | pMsgSize;
if (buffer.readableBytes() < pMsgSize) {
buffer.resetReaderIndex();
return;
}
player.getNetwork().setTx(
NettyPlayerNetwork.iterateRandom(player.getNetwork().getTx())
);
byte[] tBodyMsg = new byte[pMsgSize];
buffer.readBytes(tBodyMsg);
tBody = new String(tBodyMsg, StringUtil.getCharset());
tBody = this.pDecoder.kg4R6Jo5xjlqtFGs1klMrK4ZTzb3R(tBody);
tBody = NettyPlayerNetwork.removePadding(tBody, player.getNetwork().getTx() % 5);
ByteBuf result = Unpooled.buffer();
result.writeBytes(Base64Encoding.encode(tBody.length(), 3));
result.writeBytes(tBody.getBytes(StringUtil.getCharset()));
out.add(result);
}
out.add(result);
}
}

View file

@ -0,0 +1,61 @@
package org.alexdev.havana.server.netty.codec;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import org.alexdev.havana.game.encryption.Cryptography;
import org.alexdev.havana.game.encryption.HugeInt15;
import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.server.netty.NettyPlayerNetwork;
import org.alexdev.havana.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class EncryptionEncoder extends MessageToMessageEncoder<ByteBuf> {
private static final Logger log = LoggerFactory.getLogger(EncryptionEncoder.class);
private Cryptography pHeaderEncoder;
private Cryptography pEncoder;
public EncryptionEncoder(BigInteger sharedKey) {
this.pHeaderEncoder = new Cryptography(HugeInt15.getByteArray(sharedKey));
this.pEncoder = new Cryptography(HugeInt15.getByteArray(sharedKey));
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
Player player = ctx.channel().attr(Player.PLAYER_KEY).get();
player.getNetwork().setRx(NettyPlayerNetwork.iterateRandom(
player.getNetwork().getRx()
));
String tOriginalMsg = buffer.toString(StringUtil.getCharset());
String tHeader;
String tMsg;
tMsg = NettyPlayerNetwork.addPad(tOriginalMsg, player.getNetwork().getRx() % 5);
tMsg = this.pEncoder.AkwGx8bHG2kc1xGG4xbdHPCV0fqvK(tMsg);
var tLength = tMsg.length();
var tL1 = Character.toString((tLength & 63) | 64);
var tL2 = Character.toString(((tLength / 64) & 63) | 64);
var tL3 = Character.toString(((tLength / 4096) & 63) | 64);
tHeader = (char) (ThreadLocalRandom.current().nextInt(127) + 1) + (tL3 + tL2 + tL1);
tHeader = this.pHeaderEncoder.AkwGx8bHG2kc1xGG4xbdHPCV0fqvK(tHeader);
var tEncryptedMsg = Unpooled.buffer();
tEncryptedMsg.writeBytes(tHeader.getBytes(StringUtil.getCharset()));
tEncryptedMsg.writeBytes(tMsg.getBytes(StringUtil.getCharset()));
out.add(tEncryptedMsg);
}
}

View file

@ -7,18 +7,20 @@ import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.server.netty.streams.NettyRequest;
import org.alexdev.havana.util.encoding.Base64Encoding;
import java.nio.charset.Charset;
import java.util.List;
public class NetworkDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
if (buffer.readableBytes() < 5) {
if (buffer.readableBytes() < 4) {
// If the incoming data is less than 5 bytes, it's junk.
return;
}
buffer.markReaderIndex();
int length = Base64Encoding.decode(new byte[]{buffer.readByte(), buffer.readByte(), buffer.readByte()});
if (buffer.readableBytes() < length) {

View file

@ -1,7 +1,9 @@
package org.alexdev.havana.server.netty.codec;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageEncoder;
import org.alexdev.havana.game.player.Player;
import org.alexdev.havana.log.Log;
@ -15,51 +17,38 @@ import org.alexdev.havana.util.config.ServerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.Buffer;
import java.util.List;
public class NetworkEncoder extends MessageToMessageEncoder<Object> {
public class NetworkEncoder extends MessageToMessageEncoder<MessageComposer> {
final private static Logger log = LoggerFactory.getLogger(NetworkEncoder.class);
@Override
protected void encode(ChannelHandlerContext ctx, Object obj, List<Object> out) throws Exception {
protected void encode(ChannelHandlerContext ctx, MessageComposer msg, List<Object> out) throws Exception {
Player player = ctx.channel().attr(Player.PLAYER_KEY).get();
ByteBuf buffer = ctx.alloc().buffer();
ByteBuf buffer = Unpooled.buffer();
if (obj instanceof MessageComposer) {
MessageComposer msg = (MessageComposer) obj;
if (obj instanceof PlayerMessageComposer) {
PlayerMessageComposer playerMessageComposer = (PlayerMessageComposer) obj;
playerMessageComposer.setPlayer(player);
}
NettyResponse response = new NettyResponse(msg.getHeader(), buffer);
try {
msg.compose(response);
} catch (Exception ex) {
String name = "";
if (player != null && player.isLoggedIn()) {
name = player.getDetails().getName();
}
Log.getErrorLogger().error("Error occurred when composing (" + response.getHeader() + ") for user (" + name + "):", ex);
return;
}
if (!response.isFinalised()) {
buffer.writeByte(1);
response.setFinalised(true);
}
if (ServerConfiguration.getBoolean("log.sent.packets")) {
log.info("SENT: {} / {}", msg.getHeader(), response.getBodyString());
}
if (msg instanceof PlayerMessageComposer) {
PlayerMessageComposer playerMessageComposer = (PlayerMessageComposer) msg;
playerMessageComposer.setPlayer(player);
}
if (obj instanceof String) {
buffer.writeBytes(((String) obj).getBytes());
NettyResponse response = new NettyResponse(msg.getHeader(), buffer);
try {
msg.compose(response);
} catch (Exception ex) {
Log.getErrorLogger().error("Error occurred when composing (" + response.getHeader() + "):", ex);
return;
}
if (!response.isFinalised()) {
buffer.writeByte(1);
response.setFinalised(true);
}
if (ServerConfiguration.getBoolean("log.sent.packets")) {
log.info("SENT 1: {} / {}", msg.getHeader(), response.getBodyString());
}
out.add(buffer);

View file

@ -21,6 +21,7 @@ The reason why Shockwave emulators exist is for multiple reasons, the first is t
- Handshake
- Login via SSO ticket
- Login via username/password
- Diffie-Hellman two-way client/server encryption (v28+)
- Games
- Battleball
- Snowstorm
@ -194,7 +195,7 @@ Install any JDK version that is equal or above >= 17 to run the jar files.
Run both Havana-Server.jar and Havana-Web.jar at least once to generate the necessary configuration files, configure the MySQL attributes to connect to the MariaDB server.
Download the [havana_www.zip](https://www.mediafire.com/file/x94neh4qbu3l2s2/havana_www.zip/file) file, and then extract it to /tools/www/ this directory is located where you ran Havana-Web.jar.
Download the [havana_www_10092023.7z](https://www.mediafire.com/file/jy8a96vleuzebe0/havana_www_10092023.7z/file) file, and then extract it to /tools/www/ this directory is located where you ran Havana-Web.jar.
*(This is the default directory for static content within the Havana-Web project, but the directory where it looks for static images can be configured in the Housekeeping settings).*