Moved many files into the PSWGCommon library

This commit is contained in:
Josh Larson
2017-04-15 15:32:07 -05:00
parent af7c39c374
commit 13265130cb
61 changed files with 41609 additions and 14 deletions

View File

@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<accessrules>
<accessrule kind="accessible" pattern="javafx/**"/>
</accessrules>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>

Binary file not shown.

View File

@@ -0,0 +1,803 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
// Copyright (c) 2006 Damien Miller <djm@mindrot.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package com.projectswg.common.data;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
/**
* BCrypt implements OpenBSD-style Blowfish password hashing using
* the scheme described in "A Future-Adaptable Password Scheme" by
* Niels Provos and David Mazieres.
* <p>
* This password hashing system tries to thwart off-line password
* cracking using a computationally-intensive hashing algorithm,
* based on Bruce Schneier's Blowfish cipher. The work factor of
* the algorithm is parameterised, so it can be increased as
* computers get faster.
* <p>
* Usage is really simple. To hash a password for the first time,
* call the hashpw method with a random salt, like this:
* <p>
* <code>
* String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); <br />
* </code>
* <p>
* To check whether a plaintext password matches one that has been
* hashed previously, use the checkpw method:
* <p>
* <code>
* if (BCrypt.checkpw(candidate_password, stored_hash))<br />
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It matches");<br />
* else<br />
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It does not match");<br />
* </code>
* <p>
* The gensalt() method takes an optional parameter (log_rounds)
* that determines the computational complexity of the hashing:
* <p>
* <code>
* String strong_salt = BCrypt.gensalt(10)<br />
* String stronger_salt = BCrypt.gensalt(12)<br />
* </code>
* <p>
* The amount of work increases exponentially (2**log_rounds), so
* each increment is twice as much work. The default log_rounds is
* 10, and the valid range is 4 to 30.
*
* @author Damien Miller
* @version 0.2
*/
public class BCrypt {
// BCrypt parameters
private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
private static final int BCRYPT_SALT_LEN = 16;
// Blowfish parameters
private static final int BLOWFISH_NUM_ROUNDS = 16;
// Initial contents of key schedule
private static final int P_orig[] = {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b
};
private static final int S_orig[] = {
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
};
// bcrypt IV: "OrpheanBeholderScryDoubt". The C implementation calls
// this "ciphertext", but it is really plaintext or an IV. We keep
// the name to make code comparison easier.
static private final int bf_crypt_ciphertext[] = {
0x4f727068, 0x65616e42, 0x65686f6c,
0x64657253, 0x63727944, 0x6f756274
};
// Table for Base64 encoding
static private final char base64_code[] = {
'.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9'
};
// Table for Base64 decoding
static private final byte index_64[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 0, 1, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
-1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-1, -1, -1, -1, -1, -1, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, -1, -1, -1, -1, -1
};
// Expanded Blowfish key
private int P[];
private int S[];
/**
* Encode a byte array using bcrypt's slightly-modified base64
* encoding scheme. Note that this is *not* compatible with
* the standard MIME-base64 encoding.
*
* @param d the byte array to encode
* @param len the number of bytes to encode
* @return base64-encoded string
* @exception IllegalArgumentException if the length is invalid
*/
private static String encode_base64(byte d[], int len)
throws IllegalArgumentException {
int off = 0;
StringBuffer rs = new StringBuffer();
int c1, c2;
if (len <= 0 || len > d.length)
throw new IllegalArgumentException ("Invalid len");
while (off < len) {
c1 = d[off++] & 0xff;
rs.append(base64_code[(c1 >> 2) & 0x3f]);
c1 = (c1 & 0x03) << 4;
if (off >= len) {
rs.append(base64_code[c1 & 0x3f]);
break;
}
c2 = d[off++] & 0xff;
c1 |= (c2 >> 4) & 0x0f;
rs.append(base64_code[c1 & 0x3f]);
c1 = (c2 & 0x0f) << 2;
if (off >= len) {
rs.append(base64_code[c1 & 0x3f]);
break;
}
c2 = d[off++] & 0xff;
c1 |= (c2 >> 6) & 0x03;
rs.append(base64_code[c1 & 0x3f]);
rs.append(base64_code[c2 & 0x3f]);
}
return rs.toString();
}
/**
* Look up the 3 bits base64-encoded by the specified character,
* range-checking againt conversion table
* @param x the base64-encoded value
* @return the decoded value of x
*/
private static byte char64(char x) {
if ((int)x > index_64.length)
return -1;
return index_64[(int)x];
}
/**
* Decode a string encoded using bcrypt's base64 scheme to a
* byte array. Note that this is *not* compatible with
* the standard MIME-base64 encoding.
* @param s the string to decode
* @param maxolen the maximum number of bytes to decode
* @return an array containing the decoded bytes
* @throws IllegalArgumentException if maxolen is invalid
*/
private static byte[] decode_base64(String s, int maxolen)
throws IllegalArgumentException {
StringBuffer rs = new StringBuffer();
int off = 0, slen = s.length(), olen = 0;
byte ret[];
byte c1, c2, c3, c4, o;
if (maxolen <= 0)
throw new IllegalArgumentException ("Invalid maxolen");
while (off < slen - 1 && olen < maxolen) {
c1 = char64(s.charAt(off++));
c2 = char64(s.charAt(off++));
if (c1 == -1 || c2 == -1)
break;
o = (byte)(c1 << 2);
o |= (c2 & 0x30) >> 4;
rs.append((char)o);
if (++olen >= maxolen || off >= slen)
break;
c3 = char64(s.charAt(off++));
if (c3 == -1)
break;
o = (byte)((c2 & 0x0f) << 4);
o |= (c3 & 0x3c) >> 2;
rs.append((char)o);
if (++olen >= maxolen || off >= slen)
break;
c4 = char64(s.charAt(off++));
o = (byte)((c3 & 0x03) << 6);
o |= c4;
rs.append((char)o);
++olen;
}
ret = new byte[olen];
for (off = 0; off < olen; off++)
ret[off] = (byte)rs.charAt(off);
return ret;
}
/**
* Blowfish encipher a single 64-bit block encoded as
* two 32-bit halves
* @param lr an array containing the two 32-bit half blocks
* @param off the position in the array of the blocks
*/
private final void encipher(int lr[], int off) {
int i, n, l = lr[off], r = lr[off + 1];
l ^= P[0];
for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) {
// Feistel substitution on left word
n = S[(l >> 24) & 0xff];
n += S[0x100 | ((l >> 16) & 0xff)];
n ^= S[0x200 | ((l >> 8) & 0xff)];
n += S[0x300 | (l & 0xff)];
r ^= n ^ P[++i];
// Feistel substitution on right word
n = S[(r >> 24) & 0xff];
n += S[0x100 | ((r >> 16) & 0xff)];
n ^= S[0x200 | ((r >> 8) & 0xff)];
n += S[0x300 | (r & 0xff)];
l ^= n ^ P[++i];
}
lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
lr[off + 1] = l;
}
/**
* Cycically extract a word of key material
* @param data the string to extract the data from
* @param offp a "pointer" (as a one-entry array) to the
* current offset into data
* @return the next word of material from data
*/
private static int streamtoword(byte data[], int offp[]) {
int i;
int word = 0;
int off = offp[0];
for (i = 0; i < 4; i++) {
word = (word << 8) | (data[off] & 0xff);
off = (off + 1) % data.length;
}
offp[0] = off;
return word;
}
/**
* Initialise the Blowfish key schedule
*/
private void init_key() {
P = (int[])P_orig.clone();
S = (int[])S_orig.clone();
}
/**
* Key the Blowfish cipher
* @param key an array containing the key
*/
private void key(byte key[]) {
int i;
int koffp[] = { 0 };
int lr[] = { 0, 0 };
int plen = P.length, slen = S.length;
for (i = 0; i < plen; i++)
P[i] = P[i] ^ streamtoword(key, koffp);
for (i = 0; i < plen; i += 2) {
encipher(lr, 0);
P[i] = lr[0];
P[i + 1] = lr[1];
}
for (i = 0; i < slen; i += 2) {
encipher(lr, 0);
S[i] = lr[0];
S[i + 1] = lr[1];
}
}
/**
* Perform the "enhanced key schedule" step described by
* Provos and Mazieres in "A Future-Adaptable Password Scheme"
* http://www.openbsd.org/papers/bcrypt-paper.ps
* @param data salt information
* @param key password information
*/
private void ekskey(byte data[], byte key[]) {
int i;
int koffp[] = { 0 }, doffp[] = { 0 };
int lr[] = { 0, 0 };
int plen = P.length, slen = S.length;
for (i = 0; i < plen; i++)
P[i] = P[i] ^ streamtoword(key, koffp);
for (i = 0; i < plen; i += 2) {
lr[0] ^= streamtoword(data, doffp);
lr[1] ^= streamtoword(data, doffp);
encipher(lr, 0);
P[i] = lr[0];
P[i + 1] = lr[1];
}
for (i = 0; i < slen; i += 2) {
lr[0] ^= streamtoword(data, doffp);
lr[1] ^= streamtoword(data, doffp);
encipher(lr, 0);
S[i] = lr[0];
S[i + 1] = lr[1];
}
}
/**
* Perform the central password hashing step in the
* bcrypt scheme
* @param password the password to hash
* @param salt the binary salt to hash with the password
* @param log_rounds the binary logarithm of the number
* of rounds of hashing to apply
* @param cdata the plaintext to encrypt
* @return an array containing the binary hashed password
*/
public byte[] crypt_raw(byte password[], byte salt[], int log_rounds,
int cdata[]) {
int rounds, i, j;
int clen = cdata.length;
byte ret[];
if (log_rounds < 4 || log_rounds > 30)
throw new IllegalArgumentException ("Bad number of rounds");
rounds = 1 << log_rounds;
if (salt.length != BCRYPT_SALT_LEN)
throw new IllegalArgumentException ("Bad salt length");
init_key();
ekskey(salt, password);
for (i = 0; i != rounds; i++) {
key(password);
key(salt);
}
for (i = 0; i < 64; i++) {
for (j = 0; j < (clen >> 1); j++)
encipher(cdata, j << 1);
}
ret = new byte[clen * 4];
for (i = 0, j = 0; i < clen; i++) {
ret[j++] = (byte)((cdata[i] >> 24) & 0xff);
ret[j++] = (byte)((cdata[i] >> 16) & 0xff);
ret[j++] = (byte)((cdata[i] >> 8) & 0xff);
ret[j++] = (byte)(cdata[i] & 0xff);
}
return ret;
}
/**
* Hash a password using the OpenBSD bcrypt scheme
* @param password the password to hash
* @param salt the salt to hash with (perhaps generated
* using BCrypt.gensalt)
* @return the hashed password
*/
public static String hashpw(String password, String salt) {
BCrypt B;
String real_salt;
byte passwordb[], saltb[], hashed[];
char minor = (char)0;
int rounds, off = 0;
StringBuffer rs = new StringBuffer();
if (salt.charAt(0) != '$' || salt.charAt(1) != '2')
throw new IllegalArgumentException ("Invalid salt version");
if (salt.charAt(2) == '$')
off = 3;
else {
minor = salt.charAt(2);
if (minor != 'a' || salt.charAt(3) != '$')
throw new IllegalArgumentException ("Invalid salt revision");
off = 4;
}
// Extract number of rounds
if (salt.charAt(off + 2) > '$')
throw new IllegalArgumentException ("Missing salt rounds");
rounds = Integer.parseInt(salt.substring(off, off + 2));
real_salt = salt.substring(off + 3, off + 25);
try {
passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
throw new AssertionError("UTF-8 is not supported");
}
saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
B = new BCrypt();
hashed = B.crypt_raw(passwordb, saltb, rounds,
(int[])bf_crypt_ciphertext.clone());
rs.append("$2");
if (minor >= 'a')
rs.append(minor);
rs.append("$");
if (rounds < 10)
rs.append("0");
if (rounds > 30) {
throw new IllegalArgumentException(
"rounds exceeds maximum (30)");
}
rs.append(Integer.toString(rounds));
rs.append("$");
rs.append(encode_base64(saltb, saltb.length));
rs.append(encode_base64(hashed,
bf_crypt_ciphertext.length * 4 - 1));
return rs.toString();
}
/**
* Generate a salt for use with the BCrypt.hashpw() method
* @param log_rounds the log2 of the number of rounds of
* hashing to apply - the work factor therefore increases as
* 2**log_rounds.
* @param random an instance of SecureRandom to use
* @return an encoded salt value
*/
public static String gensalt(int log_rounds, SecureRandom random) {
StringBuffer rs = new StringBuffer();
byte rnd[] = new byte[BCRYPT_SALT_LEN];
random.nextBytes(rnd);
rs.append("$2a$");
if (log_rounds < 10)
rs.append("0");
if (log_rounds > 30) {
throw new IllegalArgumentException(
"log_rounds exceeds maximum (30)");
}
rs.append(Integer.toString(log_rounds));
rs.append("$");
rs.append(encode_base64(rnd, rnd.length));
return rs.toString();
}
/**
* Generate a salt for use with the BCrypt.hashpw() method
* @param log_rounds the log2 of the number of rounds of
* hashing to apply - the work factor therefore increases as
* 2**log_rounds.
* @return an encoded salt value
*/
public static String gensalt(int log_rounds) {
return gensalt(log_rounds, new SecureRandom());
}
/**
* Generate a salt for use with the BCrypt.hashpw() method,
* selecting a reasonable default for the number of hashing
* rounds to apply
* @return an encoded salt value
*/
public static String gensalt() {
return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS);
}
/**
* Check that a plaintext password matches a previously hashed
* one
* @param plaintext the plaintext password to verify
* @param hashed the previously-hashed password
* @return true if the passwords match, false otherwise
*/
public static boolean checkpw(String plaintext, String hashed) {
byte hashed_bytes[];
byte try_bytes[];
try {
String try_pw = hashpw(plaintext, hashed);
hashed_bytes = hashed.getBytes("UTF-8");
try_bytes = try_pw.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
return false;
}
if (hashed_bytes.length != try_bytes.length)
return false;
byte ret = 0;
for (int i = 0; i < try_bytes.length; i++)
ret |= hashed_bytes[i] ^ try_bytes[i];
return ret == 0;
}
}

View File

@@ -0,0 +1,168 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.persistable.Persistable;
public class CRC implements Encodable, Persistable {
private static final int CRC_TABLE[] = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
};
private String str;
private int crc;
public CRC() {
this.str = null;
this.crc = 0;
}
public CRC(int crc) {
this.crc = crc;
this.str = getString(crc);
}
public CRC(String str) {
this.str = str;
if (str != null)
this.crc = getCrc(str);
else
this.crc = 0;
}
public String getString() {
return str;
}
public int getCrc() {
return crc;
}
@Override
public byte [] encode() {
NetBuffer buffer = NetBuffer.allocate(4);
buffer.addInt(crc);
return buffer.array();
}
@Override
public void decode(ByteBuffer data) {
this.crc = data.order(ByteOrder.LITTLE_ENDIAN).getInt();
this.str = getString(crc);
}
@Override
public void save(NetBufferStream stream) {
stream.addInt(crc);
}
@Override
public void read(NetBufferStream stream) {
crc = stream.getInt();
}
@Override
public String toString() {
return str;
}
@Override
public int hashCode() {
return this.crc;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof CRC)) {
return false;
}
return crc == ((CRC) obj).crc;
}
public static int getCrc(String input) {
return getCrc(input.getBytes(StandardCharsets.UTF_8));
}
public static int getCrc(byte [] data) {
int crc = 0xFFFFFFFF;
for (int i = 0; i < data.length; i++)
crc = CRC_TABLE[((crc>>>24) ^ data[i]) & 0xFF] ^ (crc << 8);
return ~crc;
}
public static String getString(int crc) {
return CrcDatabase.getInstance().getString(crc);
}
}

View File

@@ -0,0 +1,135 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.projectswg.common.debug.Log;
public class CrcDatabase {
private static final CrcDatabase INSTANCE = new CrcDatabase();
static {
INSTANCE.loadStrings();
}
private final Map<Integer, String> crcTable;
private CrcDatabase() {
crcTable = new HashMap<>();
}
public void saveStrings(OutputStream os) throws IOException {
for (Entry<Integer, String> e : crcTable.entrySet()) {
os.write((Integer.toString(e.getKey(), 16) + ',' + e.getValue() + '\n').getBytes(StandardCharsets.US_ASCII));
}
os.flush();
}
public void addCrc(String string) {
crcTable.put(CRC.getCrc(string), string);
}
public String getString(int crc) {
return crcTable.get(crc);
}
private void loadStrings() {
StringBuilder str = new StringBuilder(256);
try (InputStream is = getClass().getResourceAsStream("crc_database.csv")) {
BufferedByteReader reader = new BufferedByteReader(is);
while (reader.canRead()) {
str.setLength(0);
processLine(str, reader);
}
} catch (IOException e) {
Log.e(e);
}
}
private void processLine(StringBuilder str, BufferedByteReader reader) throws IOException {
int crc = 0;
int b;
while ((b = reader.getNextByte()) != -1) {
if (b == ',' && crc == 0) {
crc = Integer.parseInt(str.toString(), 16);
str.setLength(0);
} else if (b == '\n') {
if (crc == 0)
break;
crcTable.put(crc, str.toString().intern());
break;
} else {
str.append((char) b);
}
}
}
public static CrcDatabase getInstance() {
return INSTANCE;
}
private static class BufferedByteReader {
private final InputStream is;
private final byte [] buffer;
private int remaining;
private int position;
public BufferedByteReader(InputStream is) {
this.is = is;
this.buffer = new byte[4096];
this.remaining = 0;
this.position = 0;
}
public int getNextByte() throws IOException {
if (remaining <= 0) {
remaining = is.read(buffer);
position = 0;
if (remaining <= 0)
return -1;
}
remaining--;
return buffer[position++];
}
public boolean canRead() {
return remaining >= 0;
}
}
}

View File

@@ -0,0 +1,96 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data;
import java.awt.Color;
import java.nio.ByteBuffer;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.network.NetBuffer;
public class RGB implements Encodable {
private byte r;
private byte g;
private byte b;
public RGB() {
this(0, 0, 0);
}
public RGB(int r, int g, int b) {
setR(r);
setG(g);
setB(b);
}
public RGB(Color c) {
this(c.getRed(), c.getGreen(), c.getBlue());
}
@Override
public byte[] encode() {
NetBuffer buffer = NetBuffer.allocate(3);
buffer.addByte(r);
buffer.addByte(g);
buffer.addByte(b);
return buffer.array();
}
@Override
public void decode(ByteBuffer data) {
r = data.get();
g = data.get();
b = data.get();
}
public byte getR() {
return r;
}
public void setR(int r) {
this.r = (byte) r;
}
public byte getG() {
return g;
}
public void setG(int g) {
this.g = (byte) g;
}
public byte getB() {
return b;
}
public void setB(int b) {
this.b = (byte) b;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.info;
package com.projectswg.common.data.info;
import java.io.File;
import java.util.Map;

View File

@@ -25,7 +25,7 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.info;
package com.projectswg.common.data.info;
import java.io.BufferedReader;
import java.io.BufferedWriter;

View File

@@ -25,7 +25,7 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.info;
package com.projectswg.common.data.info;
public class PostgresqlDatabase extends RelationalDatabase {

View File

@@ -25,7 +25,7 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.info;
package com.projectswg.common.data.info;
import java.io.Closeable;
import java.sql.Connection;

View File

@@ -25,7 +25,7 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.info;
package com.projectswg.common.data.info;
import java.io.BufferedReader;
import java.io.Closeable;
@@ -252,7 +252,7 @@ public class RelationalServerData extends RelationalDatabase {
private boolean importFromSdb(String table, File sdb) {
try (TableReader reader = new TableReader(table, sdb)) {
Log.i("RelationalServerData", "Importing sdb... '" + sdb + "'");
Log.i("Importing sdb... '" + sdb + "'");
if (sdb.getName().endsWith(".msdb"))
reader.readMaster();
else
@@ -263,7 +263,7 @@ public class RelationalServerData extends RelationalDatabase {
} catch (SQLException e) {
Log.e(e);
} catch (IllegalArgumentException e) {
Log.e("RelationalServerData", "Invalid file format. Aborting read of %s! Message: %s", sdb, e.getMessage());
Log.e("Invalid file format. Aborting read of %s! Message: %s", sdb, e.getMessage());
}
return false;
}
@@ -324,15 +324,15 @@ public class RelationalServerData extends RelationalDatabase {
while ((line = reader.readLine()) != null) {
String [] parts = line.split("\t");
if (parts.length != 2) {
Log.e("RelationalServerData", "Invalid line [%d]: %s", lineNum, line);
Log.e("Invalid line [%d]: %s", lineNum, line);
continue;
}
boolean load = Boolean.parseBoolean(parts[1]);
if (load) {
File sdb = new File(file.getParent(), parts[0]);
Log.i("RelationalServerData", " Importing sdb... '" + sdb + "'");
Log.i(" Importing sdb... '" + sdb + "'");
if (!sdb.isFile()) {
Log.e("RelationalServerData", " Failed to import sdb! File is not file or does not exist");
Log.e(" Failed to import sdb! File is not file or does not exist");
continue;
}
@SuppressWarnings("resource") // This closes the database.. we don't want to do that yet
@@ -421,7 +421,7 @@ public class RelationalServerData extends RelationalDatabase {
private void generateInsert(String [] data, int line) throws SQLException {
if (columnTypes.length != data.length) {
Log.e("RelationalServerData", "Could not load record: Types length and data length mismatch. Line: " + line);
Log.e("Could not load record: Types length and data length mismatch. Line: " + line);
return;
}
int column = 0;
@@ -438,7 +438,7 @@ public class RelationalServerData extends RelationalDatabase {
}
insert.addBatch();
} catch (NumberFormatException e) {
Log.e("RelationalServerData", "Could not load record: Record has invalid data. Line: " + line + " Column: " + column);
Log.e("Could not load record: Record has invalid data. Line: " + line + " Column: " + column);
}
}

View File

@@ -25,7 +25,7 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.info;
package com.projectswg.common.data.info;
import java.io.ByteArrayOutputStream;
import java.io.File;

View File

@@ -0,0 +1,302 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.location;
import java.nio.ByteBuffer;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.persistable.Persistable;
public class Location implements Encodable, Persistable {
private final Point3D point;
private final Quaternion orientation;
private Terrain terrain;
public Location() {
this(Double.NaN, Double.NaN, Double.NaN, null);
}
public Location(Location l) {
this(l.getX(), l.getY(), l.getZ(), l.terrain);
orientation.set(l.orientation);
}
public Location(double x, double y, double z, Terrain terrain) {
this.orientation = new Quaternion(0, 0, 0, 1);
this.point = new Point3D(x, y, z);
this.terrain = terrain;
}
public void setTerrain(Terrain terrain) { this.terrain = terrain; }
public void setX(double x) { point.setX(x); }
public void setY(double y) { point.setY(y); }
public void setZ(double z) { point.setZ(z); }
public void setOrientationX(double oX) { orientation.setX(oX); }
public void setOrientationY(double oY) { orientation.setY(oY); }
public void setOrientationZ(double oZ) { orientation.setZ(oZ); }
public void setOrientationW(double oW) { orientation.setW(oW); }
public void setPosition(double x, double y, double z) {
setX(x);
setY(y);
setZ(z);
}
public void setOrientation(double oX, double oY, double oZ, double oW) {
setOrientationX(oX);
setOrientationY(oY);
setOrientationZ(oZ);
setOrientationW(oW);
}
public Terrain getTerrain() { return terrain; }
public double getX() { return point.getX(); }
public double getY() { return point.getY(); }
public double getZ() { return point.getZ(); }
public Point3D getPosition() { return new Point3D(point); }
public double getOrientationX() { return orientation.getX(); }
public double getOrientationY() { return orientation.getY(); }
public double getOrientationZ() { return orientation.getZ(); }
public double getOrientationW() { return orientation.getW(); }
public Quaternion getOrientation() { return new Quaternion(orientation); }
public boolean isWithinDistance(Location l, double x, double y, double z) {
if (getTerrain() != l.getTerrain())
return false;
double xD = Math.abs(getX() - l.getX());
double yD = Math.abs(getY() - l.getY());
double zD = Math.abs(getZ() - l.getZ());
return xD <= x && yD <= y && zD <= z;
}
public boolean isWithinDistance(Location l, double radius) {
return isWithinDistance(l.getTerrain(), l.getX(), l.getY(), l.getZ(), radius);
}
public boolean isWithinDistance(Terrain t, double x, double y, double z, double radius) {
if (getTerrain() != t)
return false;
return square(getX()-x) + square(getY()-y) + square(getZ()-z) <= square(radius);
}
public boolean isWithinFlatDistance(Location l, double radius) {
return isWithinFlatDistance(l.point, radius);
}
public boolean isWithinFlatDistance(Point3D target, double radius){
return square(getX() - target.getX()) + square(getZ() - target.getZ()) <= square(radius);
}
public void translatePosition(double x, double y, double z) {
setX(getX() + x);
setY(getY() + y);
setZ(getZ() + z);
}
public void translateLocation(Location l) {
point.rotateAround(l.getX(), l.getY(), l.getZ(), l.orientation);
orientation.rotateByQuaternion(l.orientation);
}
public Location translate(Location l) {
Location ret = new Location(this);
ret.translateLocation(l);
return ret;
}
/**
* Sets the orientation to be facing the specified heading
* @param heading the heading to face, in degrees
*/
public void setHeading(double heading) {
orientation.setHeading(heading);
}
/**
* Rotates the orientation by the specified angle along the Y-axis
* @param angle the angle to rotate by in degrees
*/
public void rotateHeading(double angle) {
orientation.rotateHeading(angle);
}
/**
* Rotates the orientation by the specified angle along the specified axises
* @param angle the angle to rotate by in degrees
* @param axisX the amount of rotation about the x-axis
* @param axisY the amount of rotation about the x-axis
* @param axisZ the amount of rotation about the x-axis
*/
public void rotate(double angle, double axisX, double axisY, double axisZ) {
orientation.rotateDegrees(angle, axisX, axisY, axisZ);
}
public void mergeWith(Location l) {
if (terrain == null || terrain != l.getTerrain())
terrain = l.getTerrain();
mergeLocation(l.getX(), l.getY(), l.getZ());
mergeOrientation(l);
}
public void mergeLocation(double lX, double lY, double lZ) {
if (!isEqual(getX(), lX))
point.setX(lX);
if (!isEqual(getY(), lY))
point.setY(lY);
if (!isEqual(getZ(), lZ))
point.setZ(lZ);
}
private void mergeOrientation(Location l) {
if (!isEqual(getOrientationX(), l.getOrientationX()))
orientation.setX(l.getOrientationX());
if (!isEqual(getOrientationY(), l.getOrientationY()))
orientation.setY(l.getOrientationY());
if (!isEqual(getOrientationZ(), l.getOrientationZ()))
orientation.setZ(l.getOrientationZ());
if (!isEqual(getOrientationW(), l.getOrientationW()))
orientation.setW(l.getOrientationW());
}
public double getSpeed(Location l, double deltaTime) {
double dist = Math.sqrt(square(getX()-l.getX()) + square(getY()-l.getY()) + square(getZ()-l.getZ()));
return dist / deltaTime;
}
public double getYaw() {
return orientation.getYaw();
}
private double square(double x) {
return x*x;
}
public boolean equals(Object o) {
if (!(o instanceof Location))
return false;
return equals((Location) o);
}
public boolean equals(Location l) {
if (terrain != l.terrain)
return false;
if (!isEqual(l.getX(), getX()))
return false;
if (!isEqual(l.getY(), getY()))
return false;
if (!isEqual(l.getZ(), getZ()))
return false;
if (!isEqual(l.getOrientationX(), getOrientationX()))
return false;
if (!isEqual(l.getOrientationY(), getOrientationY()))
return false;
if (!isEqual(l.getOrientationZ(), getOrientationZ()))
return false;
if (!isEqual(l.getOrientationW(), getOrientationW()))
return false;
return true;
}
public int hashCode() {
return hash(getX())*13 + hash(getY())*17 + hash(getZ())*19 + hash(getOrientationX())*23 + hash(getOrientationY())*29 + hash(getOrientationZ())*31 + hash(getOrientationW())*37;
}
private int hash(double x) {
long v = Double.doubleToLongBits(x);
return (int)(v^(v>>>32));
}
private boolean isEqual(double x, double y) {
if (Double.isNaN(x))
return Double.isNaN(y);
if (Double.isNaN(y))
return false;
return Math.abs(x - y) <= 1E-7;
}
@Override
public byte[] encode() {
NetBuffer buf = NetBuffer.allocate(28);
buf.addFloat(safeEncodeDouble(orientation.getX()));
buf.addFloat(safeEncodeDouble(orientation.getY()));
buf.addFloat(safeEncodeDouble(orientation.getZ()));
buf.addFloat(safeEncodeDouble(orientation.getW()));
buf.addFloat(safeEncodeDouble(point.getX()));
buf.addFloat(safeEncodeDouble(point.getY()));
buf.addFloat(safeEncodeDouble(point.getZ()));
return buf.array();
}
@Override
public void decode(ByteBuffer data) {
orientation.decode(data);
point.decode(data);
}
@Override
public void save(NetBufferStream stream) {
stream.addByte(0);
orientation.save(stream);
point.save(stream);
stream.addBoolean(terrain != null);
if (terrain != null)
stream.addAscii(terrain.name());
}
@Override
public void read(NetBufferStream stream) {
stream.getByte();
orientation.read(stream);
point.read(stream);
if (stream.getBoolean())
terrain = Terrain.valueOf(stream.getAscii());
}
@Override
public String toString() {
return String.format("Location[TRN=%s, %s %s]", terrain, point, orientation);
}
/**
* @param destination to get the distance for
* @return the distance between {@code this} and destination, which is ALWAYS positive.
*/
public double distanceTo(Location destination) {
return distanceTo(destination.getX(), destination.getY(), destination.getZ());
}
public double distanceTo(double dstX, double dstY, double dstZ) {
return Math.sqrt(square(dstX - getX()) + square(dstY - getY()) + square(dstZ - getZ()));
}
private float safeEncodeDouble(double d) {
return (float) (Double.isNaN(d) ? 0 : d);
}
}

View File

@@ -0,0 +1,150 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.location;
import java.nio.ByteBuffer;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.persistable.Persistable;
public class Point3D implements Encodable, Persistable {
private double x;
private double y;
private double z;
public Point3D() {
this(0, 0, 0);
}
public Point3D(Point3D p) {
this(p.getX(), p.getY(), p.getZ());
}
public Point3D(double x, double y, double z) {
set(x, y, z);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setZ(double z) {
this.z = z;
}
public void set(double x, double y, double z) {
setX(x);
setY(y);
setZ(z);
}
public void translate(Point3D p) {
translate(p.getX(), p.getY(), p.getZ());
}
public void translate(double x, double y, double z) {
this.x += x;
this.y += y;
this.z += z;
}
public void rotateAround(double x, double y, double z, Quaternion rot) {
rot.rotatePoint(this);
translate(x, y, z);
}
@Override
public byte[] encode() {
NetBuffer buf = NetBuffer.allocate(12);
buf.addFloat((float) x);
buf.addFloat((float) y);
buf.addFloat((float) z);
return buf.array();
}
@Override
public void decode(ByteBuffer data) {
NetBuffer buf = NetBuffer.wrap(data);
x = buf.getFloat();
y = buf.getFloat();
z = buf.getFloat();
}
@Override
public void save(NetBufferStream stream) {
stream.addFloat((float) x);
stream.addFloat((float) y);
stream.addFloat((float) z);
}
@Override
public void read(NetBufferStream stream) {
x = stream.getFloat();
y = stream.getFloat();
z = stream.getFloat();
}
public boolean equals(Object o) {
if (!(o instanceof Point3D))
return false;
if (Math.abs(((Point3D) o).getX()-getX()) > 1E-7)
return false;
if (Math.abs(((Point3D) o).getY()-getY()) > 1E-7)
return false;
if (Math.abs(((Point3D) o).getZ()-getZ()) > 1E-7)
return false;
return true;
}
public int hashCode() {
return Double.hashCode(getX()) ^ Double.hashCode(getY()) ^ Double.hashCode(getZ());
}
public String toString() {
return String.format("Point3D[%.2f, %.2f, %.2f]", x, y, z);
}
}

View File

@@ -0,0 +1,222 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.location;
import java.nio.ByteBuffer;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.persistable.Persistable;
public class Quaternion implements Encodable, Persistable {
private final double [][] rotationMatrix;
private double x;
private double y;
private double z;
private double w;
public Quaternion(Quaternion q) {
this(q.x, q.y, q.z, q.w);
}
public Quaternion(double x, double y, double z, double w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
this.rotationMatrix = new double[3][3];
updateRotationMatrix();
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public double getW() {
return w;
}
public double getYaw() {
return Math.toDegrees(Math.atan2(y*y, w*w));
}
public void setX(double x) {
this.x = x;
updateRotationMatrix();
}
public void setY(double y) {
this.y = y;
updateRotationMatrix();
}
public void setZ(double z) {
this.z = z;
updateRotationMatrix();
}
public void setW(double w) {
this.w = w;
updateRotationMatrix();
}
public void set(double x, double y, double z, double w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
updateRotationMatrix();
}
public void set(Quaternion q) {
set(q.x, q.y, q.z, q.w);
}
public void setHeading(double degrees) {
set(0, 0, 0, 1);
rotateHeading(degrees);
}
public void rotateHeading(double degrees) {
rotateDegrees(degrees, 0, 1, 0);
}
public void rotateDegrees(double degrees, double axisX, double axisY, double axisZ) {
double rad = Math.toRadians(degrees) / 2;
double sin = Math.sin(rad);
w = Math.cos(rad);
x = sin * axisX;
y = sin * axisY;
z = sin * axisZ;
normalize();
}
public void rotateByQuaternion(Quaternion q) {
double nW = w * q.w - x * q.x - y * q.y - z * q.z;
double nX = w * q.x + x * q.w + y * q.z - z * q.y;
double nY = w * q.y + y * q.w + z * q.x - x * q.z;
double nZ = w * q.z + z * q.w + x * q.y - y * q.x;
set(nX, nY, nZ, nW);
normalize();
}
public void rotatePoint(Point3D p) {
double nX = rotationMatrix[0][0]*p.getX() + rotationMatrix[0][1]*p.getY() + rotationMatrix[0][2]*p.getZ();
double nY = rotationMatrix[1][0]*p.getX() + rotationMatrix[1][1]*p.getY() + rotationMatrix[1][2]*p.getZ();
double nZ = rotationMatrix[2][0]*p.getX() + rotationMatrix[2][1]*p.getY() + rotationMatrix[2][2]*p.getZ();
p.set(nX, nY, nZ);
}
public void normalize() {
double mag = Math.sqrt(x * x + y * y + z * z + w * w);
x /= mag;
y /= mag;
z /= mag;
w /= mag;
updateRotationMatrix();
}
@Override
public byte[] encode() {
NetBuffer buf = NetBuffer.allocate(16);
buf.addFloat((float) x);
buf.addFloat((float) y);
buf.addFloat((float) z);
buf.addFloat((float) w);
return buf.array();
}
@Override
public void decode(ByteBuffer data) {
NetBuffer buf = NetBuffer.wrap(data);
x = buf.getFloat();
y = buf.getFloat();
z = buf.getFloat();
w = buf.getFloat();
updateRotationMatrix();
}
@Override
public void save(NetBufferStream stream) {
stream.addFloat((float) x);
stream.addFloat((float) y);
stream.addFloat((float) z);
stream.addFloat((float) w);
}
@Override
public void read(NetBufferStream stream) {
x = stream.getFloat();
y = stream.getFloat();
z = stream.getFloat();
w = stream.getFloat();
updateRotationMatrix();
}
public String toString() {
return String.format("Quaternion[%.3f, %.3f, %.3f, %.3f]", x, y, z, w);
}
private void updateRotationMatrix() {
double x2 = x * x;
double y2 = y * y;
double z2 = z * z;
double w2 = w * w;
updateRotationMatrixX(x2, y2, z2, w2);
updateRotationMatrixY(x2, y2, z2, w2);
updateRotationMatrixZ(x2, y2, z2, w2);
}
private void updateRotationMatrixX(double x2, double y2, double z2, double w2) {
rotationMatrix[0][0] = x2 + w2 - y2 - z2;
rotationMatrix[0][1] = 2*y*x - 2*z*w;
rotationMatrix[0][2] = 2*y*w + 2*z*x;
}
private void updateRotationMatrixY(double x2, double y2, double z2, double w2) {
rotationMatrix[1][0] = 2*x*y + 2*w*z;
rotationMatrix[1][1] = y2 - z2 + w2 - x2;
rotationMatrix[1][2] = 2*z*y - 2*x*w;
}
private void updateRotationMatrixZ(double x2, double y2, double z2, double w2) {
rotationMatrix[2][0] = 2*x*z - 2*w*y;
rotationMatrix[2][1] = 2*y*z + 2*w*x;
rotationMatrix[2][2] = z2 + w2 - x2 - y2;
}
}

View File

@@ -0,0 +1,193 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.location;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import com.projectswg.common.data.CRC;
public enum Terrain {
ADVENTURE1 ("terrain/adventure1.trn"),
ADVENTURE2 ("terrain/adventure2.trn"),
CHARACTER_FARM ("terrain/character_farm.trn"),
CINCO_CITY_TEST_M5 ("terrain/cinco_city_test_m5.trn"),
CORELLIA ("terrain/corellia.trn"),
CREATURE_TEST ("terrain/creature_test.trn"),
DANTOOINE ("terrain/dantooine.trn"),
DATHOMIR ("terrain/dathomir.trn"),
DEV_AREA ("terrain/tatooine.trn"),
DUNGEON1 ("terrain/dungeon1.trn"),
ENDOR_ASOMMERS ("terrain/endor_asommers.trn"),
ENDOR ("terrain/endor.trn"),
FLORATEST ("terrain/floratest.trn"),
GODCLIENT_TEST ("terrain/godclient_test.trn"),
GONE ("terrain/gone.trn"),
KASHYYYK_DEAD_FOREST ("terrain/kashyyyk_dead_forest.trn"),
KASHYYYK_HUNTING ("terrain/kashyyyk_hunting.trn"),
KASHYYYK_MAIN ("terrain/kashyyyk_main.trn"),
KASHYYYK_NORTH_DUNGEONS ("terrain/kashyyyk_north_dungeons.trn"),
KASHYYYK_POB_DUNGEONS ("terrain/kashyyyk_pob_dungeons.trn"),
KASHYYYK_RRYATT_TRAIL ("terrain/kashyyyk_rryatt_trail.trn"),
KASHYYYK_SOUTH_DUNGEONS ("terrain/kashyyyk_south_dungeons.trn"),
KASHYYYK ("terrain/kashyyyk.trn"),
LOK ("terrain/lok.trn"),
MUSTAFAR ("terrain/mustafar.trn"),
NABOO ("terrain/naboo.trn"),
OTOH_GUNGA ("terrain/otoh_gunga.trn"),
RIVERTEST ("terrain/rivertest.trn"),
RORI ("terrain/rori.trn"),
RUNTIMERULES ("terrain/runtimerules.trn"),
SIMPLE ("terrain/simple.trn"),
SPACE_CORELLIA_2 ("terrain/space_corellia_2.trn"),
SPACE_CORELLIA ("terrain/space_corellia.trn"),
SPACE_DANTOOINE ("terrain/space_dantooine.trn"),
SPACE_DATHOMIR ("terrain/space_dathomir.trn"),
SPACE_ENDOR ("terrain/space_endor.trn"),
SPACE_ENV ("terrain/space_env.trn"),
SPACE_HALOS ("terrain/space_halos.trn"),
SPACE_HEAVY1 ("terrain/space_heavy1.trn"),
SPACE_KASHYYYK ("terrain/space_kashyyyk.trn"),
SPACE_LIGHT1 ("terrain/space_light1.trn"),
SPACE_LOK ("terrain/space_lok.trn"),
SPACE_NABOO_2 ("terrain/space_naboo_2.trn"),
SPACE_NABOO ("terrain/space_naboo.trn"),
SPACE_NOVA_ORION ("terrain/space_nova_orion.trn"),
SPACE_NPE_FALCON_2 ("terrain/space_npe_falcon_2.trn"),
SPACE_NPE_FALCON_3 ("terrain/space_npe_falcon_3.trn"),
SPACE_NPE_FALCON ("terrain/space_npe_falcon.trn"),
SPACE_ORD_MANTELL_2 ("terrain/space_ord_mantell_2.trn"),
SPACE_ORD_MANTELL_3 ("terrain/space_ord_mantell_3.trn"),
SPACE_ORD_MANTELL_4 ("terrain/space_ord_mantell_4.trn"),
SPACE_ORD_MANTELL_5 ("terrain/space_ord_mantell_5.trn"),
SPACE_ORD_MANTELL_6 ("terrain/space_ord_mantell_6.trn"),
SPACE_ORD_MANTELL ("terrain/space_ord_mantell.trn"),
SPACE_TATOOINE_2 ("terrain/space_tatooine_2.trn"),
SPACE_TATOOINE ("terrain/space_tatooine.trn"),
SPACE_YAVIN4 ("terrain/space_yavin4.trn"),
TAANAB ("terrain/taanab.trn"),
TALUS ("terrain/talus.trn"),
TATOOINE ("terrain/tatooine.trn"),
TERRAIN_TEST ("terrain/terrain_test.trn"),
TEST_WEARABLES ("terrain/test_wearables.trn"),
TUSKAN_RAID_ENCOUNTER ("terrain/tuskan_raid_encounter.trn"),
TUTORIAL ("terrain/tutorial.trn"),
UMBRA ("terrain/umbra.trn"),
WATERTABLETEST ("terrain/watertabletest.trn"),
YAVIN4 ("terrain/yavin4.trn");
private static final Map <Integer, String> CRC_TO_NAME = new ConcurrentHashMap<>();
private static final Map <String, Integer> NAME_TO_CRC = new ConcurrentHashMap<>();
private static final Map <String, Terrain> NAME_TO_TERRAIN = new ConcurrentHashMap<>();
private static final Map <Integer, Terrain> CRC_TO_TERRAIN = new ConcurrentHashMap<>();
private String file;
private String name;
private int crc;
static {
for (Terrain p : values()) {
CRC_TO_TERRAIN.put(p.getCrc(), p);
CRC_TO_NAME.put(p.getCrc(), p.name());
NAME_TO_CRC.put(p.name().toLowerCase(Locale.US), p.getCrc());
NAME_TO_CRC.put(p.name().toLowerCase(Locale.US), p.getCrc());
NAME_TO_TERRAIN.put(p.name().toLowerCase(Locale.US), p);
}
}
Terrain(String file) {
this.file = file;
this.name = file.substring(8, file.length() - 4);
this.crc = CRC.getCrc(name);
}
public String getFile() { return file; }
public String getName() { return name; }
public String getNameCapitalized() { return Character.toUpperCase(name.charAt(0)) + name.substring(1); }
public int getCrc() { return crc; }
public Location getStartLocation() {
Location l = new Location();
Random r = new Random();
if (this == TATOOINE) {
l.setOrientationX(0);
l.setOrientationY(0);
l.setOrientationZ(0);
l.setOrientationW(1);
l.setX(3828 + r.nextInt(100) / 10 - 5);
l.setY(4);
l.setZ(-4804 + r.nextInt(100) / 10 - 5);
}
return l;
}
public static int getTerrainCount() {
return CRC_TO_TERRAIN.size();
}
public static String getNameFromCrc(int crc) {
String name = CRC_TO_NAME.get(crc);
if (name == null)
return "";
return name;
}
public static int getCrcFromName(String name) {
Integer crc = NAME_TO_CRC.get(name.toLowerCase(Locale.ENGLISH));
if (crc == null)
return 0;
return crc;
}
/**
* Note: Defaults to TATOOINE
*/
public static Terrain getTerrainFromCrc(int crc) {
Terrain p = CRC_TO_TERRAIN.get(crc);
if (p == null)
return TATOOINE;
return p;
}
/**
* Note: Defaults to TATOOINE
*/
public static Terrain getTerrainFromName(String name) {
Terrain p = NAME_TO_TERRAIN.get(name.toLowerCase(Locale.ENGLISH));
if (p == null)
return TATOOINE;
return p;
}
public static boolean doesTerrainExistForName(String name) {
return NAME_TO_TERRAIN.containsKey(name.toLowerCase(Locale.ENGLISH));
}
}

View File

@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile;
/**
* @author Waverunner
*/
public interface ChunkReader {
void handleReadChunk(IffNode chunk);
}

View File

@@ -0,0 +1,35 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile;
/**
* Created by Waverunner on 6/9/2015
*/
public abstract class ClientData {
public void readIff(SWGFile iff) {}
public void writeIff(SWGFile iff) {}
}

View File

@@ -0,0 +1,239 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import com.projectswg.common.debug.Log;
import com.projectswg.common.data.swgfile.visitors.CrcStringTableData;
import com.projectswg.common.data.swgfile.visitors.DatatableData;
import com.projectswg.common.data.swgfile.visitors.ObjectData;
import com.projectswg.common.data.swgfile.visitors.PortalLayoutData;
import com.projectswg.common.data.swgfile.visitors.ProfTemplateData;
import com.projectswg.common.data.swgfile.visitors.SlotArrangementData;
import com.projectswg.common.data.swgfile.visitors.SlotDefinitionData;
import com.projectswg.common.data.swgfile.visitors.SlotDescriptorData;
import com.projectswg.common.data.swgfile.visitors.WorldSnapshotData;
import com.projectswg.common.data.swgfile.visitors.appearance.AppearanceTemplateData;
import com.projectswg.common.data.swgfile.visitors.appearance.AppearanceTemplateList;
import com.projectswg.common.data.swgfile.visitors.appearance.BasicSkeletonTemplate;
import com.projectswg.common.data.swgfile.visitors.appearance.DetailedAppearanceTemplateData;
import com.projectswg.common.data.swgfile.visitors.appearance.LodMeshGeneratorTemplateData;
import com.projectswg.common.data.swgfile.visitors.appearance.LodSkeletonTemplateData;
import com.projectswg.common.data.swgfile.visitors.appearance.MeshAppearanceTemplate;
import com.projectswg.common.data.swgfile.visitors.appearance.SkeletalAppearanceData;
import com.projectswg.common.data.swgfile.visitors.appearance.SkeletalMeshGeneratorTemplateData;
import com.projectswg.common.data.swgfile.visitors.shader.CustomizableShaderData;
import com.projectswg.common.data.swgfile.visitors.shader.StaticShaderData;
public class ClientFactory extends DataFactory {
private static final ClientFactory INSTANCE = new ClientFactory();
private Map <String, SoftReference<ClientData>> dataMap = new HashMap<>();
private Map <String, String> typeMap = new HashMap<>();
/**
* Creates a new instance of ClientFactory.
* <br>
* <br>
* In order to add parsing for an IFF type which is not yet parsed:
* <OL>
* <LI>Create a new class which extends {@link ClientData}.
* <LI>Perform the parsing of each node within the parse method using switch-case statements for different node names.
* <LI>Add a new entry to the typeMap through populateTypeMap() method by adding in the name of the folder/node you're parsing
* as the Key and the name of the class that was just created as the Value.
* <LI>Add in a case statement in the createDataObject method returning a new instance of the class, the case being the Value
* that was entered in Step 3.
* </OL>
*/
public ClientFactory() {
populateTypeMap();
}
/**
* Retrieves information from a client file used by SWG. Parsing of the file is done internally using {@link ClientData} which also
* stores the variables and is the returned type. Retrieving info from this file puts a reference of the returned
* {@link ClientData} into a {@link HashMap}. Future calls for this file will try and obtain this reference if it's not null to prevent
* the file from being parsed multiple times if the save variable is true.
* @param file The SWG file you wish to get information from which resides in the ./clientdata/ folder.
* Example: creation/profession_defaults_combat_brawler.iff
* @return Specific visitor type of {@link ClientData} relating to the chosen file. For example, loading the file
* creation/profession_defaults_combat_brawler.iff would return an instance of {@link ProfTemplateData} extended from {@link ClientData}.
* A null instance of {@link ClientData} means that parsing for the type of file is not done, or a file was entered that doesn't exist on the
* file system.
* @param save Future calls for this file will try and obtain this reference if it's not null to prevent the file from being parsed multiple times
*/
public synchronized static ClientData getInfoFromFile(String file, boolean save) {
file = file.intern();
ClientFactory factory = ClientFactory.getInstance();
SoftReference<ClientData> reference = factory.dataMap.get(file);
ClientData data = null;
if (reference != null)
data = reference.get();
if (data == null) {
data = factory.readFile(file);
if (data == null) {
return null;
}
reference = new SoftReference<ClientData>(data);
// Soft used over Weak because Weak cleared as soon as the reference was not longer needed, Soft will be cleared when memory is needed by the JVM.
if (save) {
factory.dataMap.put(file, reference);
}
}
return data;
}
/**
* Retrieves information from a client file used by SWG. Parsing of the file is done internally using {@link ClientData} which also
* stores the variables and is the returned type.
* @param file The SWG file you wish to get information from which resides in the ./clientdata/ folder.
* Example: creation/profession_defaults_combat_brawler.iff
* @return Specific visitor type of {@link ClientData} relating to the chosen file. For example, loading the file
* creation/profession_defaults_combat_brawler.iff would return an instance of {@link ProfTemplateData} extended from {@link ClientData}.
* A null instance of {@link ClientData} means that parsing for the type of file is not done, or a file was entered that doesn't exist on the
* file system.
*/
public synchronized static ClientData getInfoFromFile(String file) {
return getInfoFromFile(file, false);
}
public synchronized static String formatToSharedFile(String original) {
if (original.contains("shared_"))
return original.intern();
int index = original.lastIndexOf('/');
return (original.substring(0, index) + "/shared_" + original.substring(index+1)).intern();
}
// Any time a new DataObject is coded for parsing a file, it will need to be added in populateTypeMap() along with a new return
// of that instance so the file can be parsed. The type is the name of the folder/node which is then used to get the value associated
// with it in the typeMap (value being the name of the Class preferably). If populateTypeMap() does not contain that node, then null is returned
// and getFileType method will print out what the type is along with a "not implemented!" message.
@Override
protected ClientData createDataObject(String type) {
String c = typeMap.get(type);
if (c == null) {
Log.e("Don't know what class to use for " + type);
return null;
}
switch (c) {
case "": return null; // Disabled clientdata
case "AppearanceTemplateData": return new AppearanceTemplateData();
case "AppearanceTemplateList": return new AppearanceTemplateList();
case "BasicSkeletonTemplate": return new BasicSkeletonTemplate();
case "CrcStringTableData": return new CrcStringTableData();
case "CustomizableShaderData": return new CustomizableShaderData();
case "DatatableData": return new DatatableData();
case "DetailedAppearanceTemplateData": return new DetailedAppearanceTemplateData();
case "LodMeshGeneratorTemplateData": return new LodMeshGeneratorTemplateData();
case "LodSkeletonTemplateData": return new LodSkeletonTemplateData();
case "MeshAppearanceTemplate": return new MeshAppearanceTemplate();
case "ObjectData": return new ObjectData();
case "PortalLayoutData": return new PortalLayoutData();
case "ProfTemplateData": return new ProfTemplateData();
case "SlotDescriptorData": return new SlotDescriptorData();
case "SlotDefinitionData": return new SlotDefinitionData();
case "SlotArrangementData": return new SlotArrangementData();
case "SkeletalAppearanceData": return new SkeletalAppearanceData();
case "SkeletalMeshGeneratorTemplateData": return new SkeletalMeshGeneratorTemplateData();
case "StaticShaderData": return new StaticShaderData();
case "WorldSnapshotData": return new WorldSnapshotData();
default: Log.e("Unimplemented typeMap value: " + c); return null;
}
}
// The typeMap is used for determining what DataObject class
private void populateTypeMap() {
typeMap.put("CSTB", "CrcStringTableData");
typeMap.put("DTII", "DatatableData");
typeMap.put("PRTO", "PortalLayoutData");
typeMap.put("PRFI", "ProfTemplateData");
typeMap.put("ARGD", "SlotArrangementData");
typeMap.put("0006", "SlotDefinitionData");
typeMap.put("SLTD", "SlotDescriptorData");
typeMap.put("WSNP", "WorldSnapshotData");
// Appearance Related Data
boolean loadAppearanceData = false;
typeMap.put("APPR", !loadAppearanceData?"":"AppearanceTemplateData");
typeMap.put("APT ", !loadAppearanceData?"":"AppearanceTemplateList");
typeMap.put("CSHD", !loadAppearanceData?"":"CustomizableShaderData");
typeMap.put("DTLA", !loadAppearanceData?"":"DetailedAppearanceTemplateData");
typeMap.put("SKTM", !loadAppearanceData?"":"BasicSkeletonTemplate");
typeMap.put("MESH", !loadAppearanceData?"":"MeshAppearanceTemplate");
typeMap.put("MLOD", !loadAppearanceData?"":"LodMeshGeneratorTemplateData");
typeMap.put("SLOD", !loadAppearanceData?"":"LodSkeletonTemplateData");
typeMap.put("SMAT", !loadAppearanceData?"":"SkeletalAppearanceData");
typeMap.put("SKMG", !loadAppearanceData?"":"SkeletalMeshGeneratorTemplateData");
typeMap.put("SSHT", !loadAppearanceData?"":"StaticShaderData");
// Objects
typeMap.put("SBMK", "ObjectData"); // object/battlefield_marker
typeMap.put("SBOT", "ObjectData"); // object/building
typeMap.put("CCLT", "ObjectData"); // object/cell
typeMap.put("SCNC", "ObjectData"); // object/construction_contract
typeMap.put("SCOU", "ObjectData"); // object/counting
typeMap.put("SCOT", "ObjectData"); // object/creature && object/mobile
typeMap.put("SDSC", "ObjectData"); // object/draft_schematic
typeMap.put("SFOT", "ObjectData"); // object/factory
typeMap.put("SGRP", "ObjectData"); // object/group
typeMap.put("SGLD", "ObjectData"); // object/guild
typeMap.put("SIOT", "ObjectData"); // object/installation
typeMap.put("SITN", "ObjectData"); // object/intangible
typeMap.put("SJED", "ObjectData"); // object/jedi_manager
typeMap.put("SMSC", "ObjectData"); // object/manufacture_schematic
typeMap.put("SMSO", "ObjectData"); // object/mission
typeMap.put("SHOT", "ObjectData"); // object/object
typeMap.put("STOT", "ObjectData"); // object/path_waypoint && object/tangible
typeMap.put("SPLY", "ObjectData"); // object/player
typeMap.put("SPQO", "ObjectData"); // object/player_quest
typeMap.put("RCCT", "ObjectData"); // object/resource_container
typeMap.put("SSHP", "ObjectData"); // object/ship
typeMap.put("STAT", "ObjectData"); // object/soundobject && object/static
typeMap.put("STOK", "ObjectData"); // object/token
typeMap.put("SUNI", "ObjectData"); // object/universe
typeMap.put("SWAY", "ObjectData"); // object/waypoint
typeMap.put("SWOT", "ObjectData"); // object/weapon
//
}
@Override
protected String getFolder() {
return "./clientdata/";
}
private static ClientFactory getInstance() {
return INSTANCE;
}
}

View File

@@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile;
import java.io.File;
import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import com.projectswg.common.debug.Log;
/**
* Created by Waverunner on 6/9/2015
*/
public abstract class DataFactory {
protected ClientData readFile(String filename) {
if (filename == null || filename.isEmpty()) {
Log.e("File cannot be null or empty!");
return null;
}
File file = new File(getFolder() + filename);
if (!file.isFile()) {
Log.e("Not a file: " + file);
return null;
}
SWGFile swgFile = new SWGFile();
try {
swgFile.read(file);
} catch (IOException e) {
if (e instanceof ClosedChannelException)
return null;
Log.e(e);
}
ClientData clientData = createDataObject(swgFile.getType());
if (clientData == null)
return null;
clientData.readIff(swgFile);
return clientData;
}
protected File writeFile(SWGFile swgFile, ClientData data) {
if (swgFile == null || data == null) {
Log.e("File or data objects cannot be null or empty!");
return null;
}
File save = new File(swgFile.getFileName());
data.writeIff(swgFile);
try {
swgFile.save(save);
} catch (IOException e) {
Log.e(e);
}
return save;
}
protected abstract ClientData createDataObject(String type);
protected ClientData createDataObject(SWGFile swgFile) {
return createDataObject(swgFile.getType());
}
protected abstract String getFolder();
}

View File

@@ -0,0 +1,323 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
* <p>
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on July 7th, 2011 after SOE announced the
* official shutdown of Star Wars Galaxies. Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing it on the final publish of the game prior
* to end-game events.
* <p>
* This file is part of Holocore.
* <p>
* --------------------------------------------------------------------------------
* <p>
* Holocore is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
* version.
* <p>
* Holocore is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
* <p>
* You should have received a copy of the GNU Affero General Public License along with Holocore. If not, see
* <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.projectswg.common.data.location.Point3D;
import com.projectswg.common.utilities.ByteUtilities;
/**
* Created by Waverunner on 6/7/2015
*/
public class IffNode {
private String tag;
private boolean isForm;
private boolean read;
private IffNode parent;
private List<IffNode> children;
private byte[] chunkData;
private ByteBuffer bb;
private Iterator<IffNode> childrenItr;
public IffNode() {
children = new LinkedList<>();
}
public IffNode(String tag, boolean isForm) {
this();
this.tag = tag;
this.isForm = isForm;
}
public void printTree() {
printTree(this, 0);
}
private void printTree(IffNode node, int depth) {
for (int i = 0; i < depth; i++)
System.out.print("\t");
System.out.println(node.getTag()+":form="+node.isForm());
for (IffNode child : node.getChildren()) {
printTree(child, depth+1);
}
}
public void addChild(IffNode child) {
children.add(child);
}
public int remaining() {
initBuffer();
return bb.remaining();
}
public byte readByte() {
initBuffer();
return bb.get();
}
public void writeByte(byte val) {
bb.order(ByteOrder.LITTLE_ENDIAN).put(val);
}
public short readShort() {
initBuffer();
return bb.order(ByteOrder.LITTLE_ENDIAN).getShort();
}
public void writeShort(short val) {
bb.order(ByteOrder.LITTLE_ENDIAN).putShort(val);
}
public int readInt() {
initBuffer();
return bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
}
public void writeInt(int val) {
bb.order(ByteOrder.LITTLE_ENDIAN).putInt(val);
}
public float readFloat() {
initBuffer();
return bb.order(ByteOrder.LITTLE_ENDIAN).getFloat();
}
public void writeFloat(float val) {
bb.putFloat(val);
}
public long readLong() {
initBuffer();
return bb.order(ByteOrder.LITTLE_ENDIAN).getLong();
}
public void writeLong(long val) {
bb.order(ByteOrder.LITTLE_ENDIAN).putLong(val);
}
public int readUInt() {
initBuffer();
return bb.order(ByteOrder.BIG_ENDIAN).getInt();
}
public short readUShort() {
initBuffer();
return bb.order(ByteOrder.BIG_ENDIAN).getShort();
}
public long readULong() {
initBuffer();
return bb.order(ByteOrder.BIG_ENDIAN).getLong();
}
public boolean readBoolean() {
return readByte() == 1;
}
public void skip(int offset) {
initBuffer();
bb.position(bb.position() + offset);
}
public String readString() {
initBuffer();
String string = ByteUtilities.nextString(bb);
if (bb.hasRemaining())
bb.get();
return string.intern();
}
public void writeString(String s) {
bb.put(s.getBytes(Charset.forName("US-ASCII")));
writeByte((byte) 0);
}
public Point3D readVector() {
initBuffer();
return new Point3D(readFloat(), readFloat(), readFloat());
}
public void writeVector(Point3D vector) {
writeFloat((float) vector.getX());
writeFloat((float) vector.getY());
writeFloat((float) vector.getZ());
}
public void readChunk(ChunkReader reader) {
initBuffer();
while(bb.hasRemaining()) {
reader.handleReadChunk(this);
}
}
public byte[] getBytes() {
return isForm ? createForm() : createChunk();
}
public String getTag() {
return tag;
}
public int getVersionFromTag() {
return Integer.parseInt(tag);
}
public List<IffNode> getChildren() {
return children;
}
public boolean isForm() {
return isForm;
}
public boolean hasBeenRead() {
return read;
}
public IffNode getNextUnreadChunk() {
while(childrenItr.hasNext()) {
IffNode child = childrenItr.next();
if (!child.isForm && !child.hasBeenRead())
return child;
}
return null;
}
public IffNode getNextUnreadForm() {
while(childrenItr.hasNext()) {
IffNode child = childrenItr.next();
if (child.isForm && !child.hasBeenRead())
return child;
}
return null;
}
public void setHasBeenRead(boolean read) {
this.read = read;
}
public byte[] getChunkData() {
if (chunkData == null)
System.err.println("Null chunk data for " + tag + " Form=" + isForm);
return chunkData;
}
public void setChunkData(ByteBuffer chunkData) {
this.chunkData = chunkData.array();
}
public IffNode getParent() {
return parent;
}
public int populateFromBuffer(ByteBuffer bb) {
String nodeTag = getTag(bb);
if (!nodeTag.equals("FORM")) {
tag = nodeTag;
return 4 + readChunk(bb);
} else return 4 + readForm(bb);
}
private void initBuffer() {
if (bb == null) bb = ByteBuffer.wrap(getChunkData());
}
public void initWriteBuffer(int size) {
bb = ByteBuffer.allocate(size);
}
public void updateChunk() {
chunkData = bb.array();
}
private byte[] createForm() {
List<byte[]> childrenData = new ArrayList<>();
int size = 0;
for (IffNode child : children) {
byte[] subData = child.getBytes();
size += subData.length;
childrenData.add(subData);
}
ByteBuffer bb = ByteBuffer.allocate(size + 12).order(ByteOrder.LITTLE_ENDIAN);
bb.put("FORM".getBytes(Charset.forName("US-ASCII")));
bb.order(ByteOrder.BIG_ENDIAN).putInt(size + 4);
bb.put(tag.getBytes(Charset.forName("US-ASCII")));
for (byte[] bytes : childrenData) {
bb.put(bytes);
}
return bb.array();
}
private int readForm(ByteBuffer bb) {
isForm = true;
int size = bb.getInt(); // Size includes the "FORM" length (4)
tag = getTag(bb);
for (int read = 4; read < size; ) {
IffNode child = new IffNode();
child.parent = this;
read += child.populateFromBuffer(bb);
addChild(child);
}
childrenItr = children.listIterator();
return 4 + size;
}
private byte[] createChunk() {
ByteBuffer byteBuffer = ByteBuffer.allocate(8 + chunkData.length).order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.put(tag.getBytes(Charset.forName("US-ASCII")));
byteBuffer.order(ByteOrder.BIG_ENDIAN).putInt(chunkData.length);
byteBuffer.put(chunkData);
return byteBuffer.array();
}
private int readChunk(ByteBuffer bb) {
isForm = false;
chunkData = new byte[bb.getInt()];
bb.get(chunkData);
return 4 + chunkData.length;
}
private String getTag(ByteBuffer bb) {
byte[] tagBytes = new byte[4];
bb.get(tagBytes);
return new String(tagBytes, StandardCharsets.UTF_8);
}
@Override
public String toString() {
return "IffNode[tag='" + tag + '\'' + ", read=" + read + ", parent=" + parent + ", isForm=" + isForm + "]";
}
}

View File

@@ -0,0 +1,252 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import com.projectswg.common.debug.Log;
/**
* Created by Waverunner on 6/4/2015
*/
public class SWGFile {
private String type;
private IffNode master;
private IffNode currentForm;
private String fileName;
public SWGFile() {}
public SWGFile(String fileName, String type) {
this(type);
this.fileName = fileName;
}
public SWGFile(String type) {
this.type = type;
this.master = new IffNode(type, true);
this.currentForm = master;
}
public void printTree() {
printTree(master, 0);
}
private void printTree(IffNode node, int depth) {
for (int i = 0; i < depth; i++)
System.out.print("\t");
System.out.println(node.getTag()+":form="+node.isForm());
for (IffNode child : node.getChildren())
printTree(child, depth+1);
}
public void save(File file) throws IOException {
try (FileOutputStream outputStream = new FileOutputStream(file, false)) {
outputStream.write(getData());
}
}
public void read(File file) throws IOException {
FileChannel channel = FileChannel.open(file.toPath());
MappedByteBuffer bb = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
int size = (int) channel.size();
channel.close();
master = new IffNode("", true);
currentForm = master;
if (!isValidIff(bb, size)) {
Log.e("Tried to open a file not in a valid Interchangeable File Format: " + file.getAbsolutePath());
return;
}
if (size != master.populateFromBuffer(bb)) {
Log.e("Size mismatch between population result and channel size: " + file.getAbsolutePath());
return;
}
type = master.getTag();
fileName = file.getAbsolutePath();
}
private boolean isValidIff(ByteBuffer buffer, int size) {
buffer.mark();
byte[] tag = new byte[4];
buffer.get(tag);
String root = new String(tag, StandardCharsets.UTF_8);
if (!root.equals("FORM"))
return false;
int formSize = buffer.getInt();
if (size != (formSize) + 8)
return false;
buffer.reset();
return true;
}
public IffNode addForm(String tag) {
return addForm(tag, true);
}
public IffNode addForm(String tag, boolean enterForm) {
IffNode form = new IffNode(tag, true);
currentForm.addChild(form);
if (enterForm)
currentForm = form;
return form;
}
public IffNode addChunk(String tag) {
IffNode chunk = new IffNode(tag, false);
currentForm.addChild(chunk);
return chunk;
}
public boolean hasNextForm() {
return currentForm.getNextUnreadForm() != null;
}
/**
* Enters the next unread form based off of the current form
* @return Entered form
*/
public IffNode enterNextForm() {
IffNode next = currentForm.getNextUnreadForm();
if (next == null)
return null;
next.setHasBeenRead(true);
currentForm = next;
return next;
}
/**
* Enters the next unread form based off of the current forms children with the given tag
* @param tag Form tag to enter
* @return Entered form
*/
public IffNode enterForm(String tag) {
for (IffNode child : currentForm.getChildren()) {
if (!child.isForm() || child.hasBeenRead())
continue;
if (child.getTag().equals(tag) && child != currentForm) {
currentForm = child;
child.setHasBeenRead(true);
return child;
}
}
return null;
}
/**
* Enters the next unread chunk with the given tag
* @param tag Tag of the chunk to enter
* @return Entered chunk
*/
public IffNode enterChunk(String tag) {
for (IffNode child : currentForm.getChildren()) {
if (child.isForm() || child.hasBeenRead())
continue;
if (child.getTag().equals(tag)) {
child.setHasBeenRead(true);
return child;
}
}
return null;
}
/**
* Enters the next chunk based off of the current forms children
* @return Entered chunk
*/
public IffNode enterNextChunk() {
for (IffNode child : currentForm.getChildren()) {
if (child.isForm() || child.hasBeenRead())
continue;
child.setHasBeenRead(true);
return child;
}
return null;
}
public IffNode exitForm() {
IffNode parent = currentForm.getParent();
if (parent != null) {
// System.out.println("Exit form " + currentForm.getTag() + " to enter form " + parent.getTag());
currentForm = parent;
}
return currentForm;
}
public boolean containsUnreadChunk(String tag) {
for (IffNode child : currentForm.getChildren()) {
if (child.isForm() || child.hasBeenRead())
continue;
if (child.getTag().equals(tag))
return true;
}
return false;
}
public byte[] getData() {
return master.getBytes();
}
public String getType() {
return type;
}
public IffNode getMaster() {
return master;
}
public IffNode getCurrentForm() {
return currentForm;
}
public String getFileName() {
return fileName;
}
}

View File

@@ -0,0 +1,100 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class CrcStringTableData extends ClientData {
private final Map<Integer, String> crcMap = new HashMap<>();
private final Map<String, Integer> reverseCrcMap = new HashMap<>();
@Override
public void readIff(SWGFile iff) {
iff.enterNextForm(); // Version
int [] crcList = null;
int count = 0;
IffNode chunk;
while ((chunk = iff.enterNextChunk()) != null) {
switch (chunk.getTag()) {
case "DATA":
count = chunk.readInt();
crcList = new int[count];
break;
case "CRCT":
for (int i = 0; i < count; ++i) {
crcList[i] = chunk.readInt();
}
break;
case "STRT":
chunk.skip(count * 4); // Start List -- not needed
break;
case "STNG":
for (int i = 0; i < count; ++i) {
String str = chunk.readString();
crcMap.put(crcList[i], str);
reverseCrcMap.put(str, crcList[i]);
}
break;
default:
break;
}
}
}
public boolean isValidCrc(int crc) {
return reverseCrcMap.containsValue(crc);
}
public String getTemplateString(int crc) {
return crcMap.get(crc);
}
public int getCrcForString(String str) {
Integer crc = reverseCrcMap.get(str);
return crc == null ? 0 : crc.intValue();
}
public Map<Integer, String> getCrcMap() {
return Collections.unmodifiableMap(crcMap);
}
public List<String> getStrings() {
return new ArrayList<>(reverseCrcMap.keySet());
}
}

View File

@@ -0,0 +1,352 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import com.projectswg.common.debug.Log;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class DatatableData extends ClientData {
private final Map<String, Integer> nameToIndex;
private String [] columnNames;
private ColumnType [] columnTypes;
private Object [][] table;
public DatatableData() {
this.nameToIndex = new HashMap<>();
this.columnNames = null;
this.columnTypes = null;
this.table = null;
}
@Override
public void readIff(SWGFile iff) {
iff.enterNextForm(); // version form
IffNode chunk;
while ((chunk = iff.enterNextChunk()) != null) {
switch (chunk.getTag()) {
case "COLS": {
String[] columnNames = new String[chunk.readInt()];
for (int i = 0; i < columnNames.length; i++) {
columnNames[i] = chunk.readString();
}
setColumnNames(columnNames);
break;
}
case "TYPE":
parseTypes(chunk);
break;
case "ROWS":
parseRows(chunk);
break;
default:
break;
}
}
}
@Override
public void writeIff(SWGFile iff) {
iff.addForm("0001");
writeColumns(iff.addChunk("COLS"));
writeTypes(iff.addChunk("TYPE"));
writeRows(iff.addChunk("ROWS"));
}
private void writeColumns(IffNode chunk) {
int size = getTableStringSize(columnNames);
chunk.initWriteBuffer(size + 4);
chunk.writeInt(columnNames.length);
for (String columnName : columnNames) {
chunk.writeString(columnName);
}
chunk.updateChunk();
}
private void writeTypes(IffNode chunk) {
int size = getColumnCount() * 2; // single char + \0
chunk.initWriteBuffer(size);
for (ColumnType columnType : columnTypes) {
chunk.writeString(columnType.getString());
}
chunk.updateChunk();
}
private void writeRows(IffNode chunk) {
int rows = getRowCount();
int cols = getColumnCount();
chunk.initWriteBuffer(getTableContentSize());
chunk.writeInt(rows);
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
switch (getColumnType(c)) {
case BOOLEAN:
case CRC:
case INTEGER:
case DATATABLE_ENUM:
case ENUM:
chunk.writeInt((Integer) getCell(r, c));
break;
case FLOAT:
chunk.writeFloat((Float) getCell(r, c));
break;
case STRING:
chunk.writeString((String) getCell(r, c));
break;
case NONE:
break;
}
}
}
chunk.updateChunk();
}
private void parseTypes(IffNode chunk) {
int cols = getColumnCount();
ColumnType [] columnTypes = new ColumnType[cols];
for (int c = 0; c < cols; c++) {
columnTypes[c] = ColumnType.getForChar(chunk.readString());
}
setColumnTypes(columnTypes);
}
private void parseRows(IffNode chunk) {
int rows = chunk.readInt();
int cols = getColumnCount();
Object [][] table = new Object[rows][getColumnCount()];
for (int r = 0; r < rows; ++r) {
for (int t = 0; t < cols; ++t) {
table[r][t] = parseObject(chunk, getColumnType(t));
}
}
setTable(table);
}
private Object parseObject(IffNode chunk, ColumnType type) {
switch (type) {
case BOOLEAN: // Boolean
return chunk.readInt() == 1;
case FLOAT: // Float
return chunk.readFloat();
case ENUM: // Enumerator
case CRC: // CRC
case INTEGER: // Integer
case DATATABLE_ENUM: // TODO: Datatable Enums
return chunk.readInt();
case STRING: // String
return chunk.readString();
case NONE:
return null;
}
return null;
}
public int getRowCount() {
return table == null ? 0 : table.length;
}
public int getColumnCount() {
return columnNames == null ? 0 : columnNames.length;
}
public Object[] getRow(int row) {
return table[row];
}
public Object getCell(int row, int column) {
return table[row][column];
}
public Object getCell(int row, String columnName) {
return getCell(row, nameToIndex.get(columnName).intValue());
}
public String getString(int row, String columnName) {
return (String) getCell(row, nameToIndex.get(columnName).intValue());
}
public float getFloat(int row, String columnName) {
return (float) getCell(row, nameToIndex.get(columnName).intValue());
}
public int getInt(int row, String columnName) {
return (int) getCell(row, nameToIndex.get(columnName).intValue());
}
public String getColumnName(int column) {
if (column < 0 || column >= getColumnCount())
return null;
return columnNames[column];
}
public ColumnType getColumnType(int column) {
if (column < 0 || column >= getColumnCount())
return ColumnType.NONE;
return columnTypes[column];
}
public int getColumnFromName(String columnName) {
Integer column = nameToIndex.get(columnName);
return column == null ? -1 : column;
}
public void handleRows(DatatableRowHandler handler) {
for (int r = 0; r < getRowCount(); r++) {
handler.handleRow(r);
}
}
public void setColumnNames(String[] columnNames) {
this.columnNames = columnNames;
nameToIndex.clear();
for (int i = 0; i < columnNames.length; i++) {
nameToIndex.put(columnNames[i], i);
}
}
public void setColumnTypes(String [] columnTypes) {
ColumnType [] newTypes = new ColumnType[columnTypes.length];
for (int i = 0; i < columnTypes.length; i++) {
newTypes[i] = ColumnType.getForChar(columnTypes[i]);
}
setColumnTypes(newTypes);
}
public void setColumnTypes(ColumnType [] columnTypes) {
this.columnTypes = columnTypes;
}
public void setTable(Object[][] table) {
this.table = table;
}
private int getTableStringSize(String[] table) {
int size = 0;
for (String s : table) {
size += s.length() + 1;
}
return size;
}
private int getTableContentSize() {
int size = 0;
int rows = getRowCount();
for (int i = 0; i < getColumnCount(); i++) {
switch (getColumnType(i)) {
case BOOLEAN:
case FLOAT:
case CRC:
case INTEGER:
case DATATABLE_ENUM:
case ENUM:
size += 4 * rows;
break;
case STRING:
for (int r = 0; r < rows; r++) {
size += ((String) table[r][i]).length() + 1;
}
break;
case NONE:
Log.e("Cannot write row type %s", getColumnType(i));
break;
}
}
return size + 4;
}
public interface DatatableRowHandler {
void handleRow(int row);
}
public enum ColumnType {
BOOLEAN ('b'),
FLOAT ('f'),
CRC ('h'),
INTEGER ('i'),
STRING ('s'),
ENUM ('e'),
DATATABLE_ENUM ('v'),
NONE (' ');
private static final ColumnType [] VALUES = values();
private final char c;
ColumnType(char c) {
this.c = c;
}
public char getChar() {
return c;
}
public String getString() {
return Character.toString(c);
}
public static ColumnType getForChar(String str) {
str = str.toLowerCase(Locale.ENGLISH);
if (str.indexOf('[') != -1)
str = str.substring(0, str.indexOf('['));
if (str.indexOf('(') != -1) // relevant only to enums
str = str.substring(0, str.indexOf('('));
if (str.length() != 1)
return NONE;
return getForChar(str.charAt(0));
}
public static ColumnType getForChar(char c) {
for (ColumnType type : VALUES) {
if (type.getChar() == c)
return type;
}
return NONE;
}
}
}

View File

@@ -0,0 +1,321 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import com.projectswg.common.debug.Log;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class ObjectData extends ClientData {
private final Map<ObjectDataAttribute, Object> attributes = new HashMap<>();
private final List<String> parsedFiles = new ArrayList<>();
public enum ObjectDataAttribute {
ACCELERATION ("acceleration"),
ANIMATION_MAP_FILENAME ("animationMapFilename"),
APPEARANCE_FILENAME ("appearanceFilename"),
ARRANGEMENT_DESCRIPTOR_FILENAME ("arrangementDescriptorFilename"),
ATTACK_TYPE ("attackType"),
CAMERA_HEIGHT ("cameraHeight"),
CERTIFICATIONS_REQUIRED ("certificationsRequired"),
CLEAR_FLORA_RADIUS ("clearFloraRadius"),
CLIENT_DATA_FILE ("clientDataFile"),
CLIENT_VISIBILITY_FLAG ("clientVisabilityFlag"),
COCKPIT_FILENAME ("cockpitFilename"),
COLLISION_ACTION_BLOCK_FLAGS ("collisionActionBlockFlags"),
COLLISION_ACTION_FLAGS ("collisionActionFlags"),
COLLISION_ACTION_PASS_FLAGS ("collisionActionPassFlags"),
COLLISION_HEIGHT ("collisionHeight"),
COLLISION_LENGTH ("collisionLength"),
COLLISION_MATERIAL_BLOCK_FLAGS ("collisionMaterialBlockFlags"),
COLLISION_MATERIAL_FLAGS ("collisionMaterialFlags"),
COLLISION_MATERIAL_PASS_FLAGS ("collisionMaterialPassFlags"),
COLLISION_OFFSET_X ("collisionOffsetX"),
COLLISION_OFFSET_Z ("collisionOffsetZ"),
COLLISION_RADIUS ("collisionRadius"),
CONST_STRING_CUSTOMIZATION_VARIABLES ("constStringCustomizationVariables"),
CONTAINER_TYPE ("containerType"),
CONTAINER_VOLUME_LIMIT ("containerVolumeLimit"),
CUSTOMIZATION_VARIABLE_MAPPING ("customizationVariableMapping"),
DETAILED_DESCRIPTION ("detailedDescription"),
FORCE_NO_COLLISION ("forceNoCollision"),
GAME_OBJECT_TYPE ("gameObjectType"),
GENDER ("gender"),
HAS_WINGS ("hasWings"),
INTERIOR_LAYOUT_FILENAME ("interiorLayoutFileName"),
LOCATION_RESERVATION_RADIUS ("locationReservationRadius"),
LOOK_AT_TEXT ("lookAtText"),
MOVEMENT_DATATABLE ("movementDatatable"),
NICHE ("niche"),
NO_BUILD_RADIUS ("noBuildRadius"),
OBJECT_NAME ("objectName"),
ONLY_VISIBLE_IN_TOOLS ("onlyVisibleInTools"),
PALETTE_COLOR_CUSTOMIZATION_VARIABLES ("paletteColorCustomizationVariables"),
PLAYER_CONTROLLED ("playerControlled"),
PORTAL_LAYOUT_FILENAME ("portalLayoutFilename"),
POSTURE_ALIGN_TO_TERRAIN ("postureAlignToTerrain"),
RACE ("race"),
RANGED_INT_CUSTOMIZATION_VARIABLES ("rangedIntCustomizationVariables"),
SCALE ("scale"),
SCALE_THRESHOLD_BEFORE_EXTENT_TEST ("scaleThresholdBeforeExtentTest"),
SEND_TO_CLIENT ("sendToClient"),
SLOPE_MOD_ANGLE ("slopeModAngle"),
SLOPE_MOD_PERCENT ("slopeModPercent"),
SLOT_DESCRIPTOR_FILENAME ("slotDescriptorFilename"),
SNAP_TO_TERRAIN ("snapToTerrain"),
SOCKET_DESTINATIONS ("socketDestinations"),
SPECIES ("species"),
SPEED ("speed"),
STEP_HEIGHT ("stepHeight"),
STRUCTURE_FOOTPRINT_FILENAME ("structureFootprintFileName"),
SURFACE_TYPE ("surfaceType"),
SWIM_HEIGHT ("swimHeight"),
TARGETABLE ("targetable"),
TERRAIN_MODIFICATION_FILENAME ("terrainModificationFileName"),
TINT_PALETTE ("tintPalette"),
TURN_RADIUS ("turnRate"),
USE_STRUCTURE_FOOTPRINT_OUTLINE ("useStructureFootprintOutline"),
WARP_TOLERANCE ("warpTolerance"),
WATER_MOD_PERCENT ("waterModPercent"),
WEAPON_EFFECT ("weaponEffect"),
WEAPON_EFFECT_INDEX ("weaponEffectIndex");
private static final Map<String, ObjectDataAttribute> ATTRIBUTES = new Hashtable<>(values().length);
static {
for (ObjectDataAttribute attr : values())
ATTRIBUTES.put(attr.getName(), attr);
}
private final String name;
ObjectDataAttribute(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static ObjectDataAttribute getForName(String name) {
return ATTRIBUTES.get(name);
}
}
public ObjectData() {}
@Override
public void readIff(SWGFile iff) {
readNextForm(iff);
}
private void readNextForm(SWGFile iff) {
IffNode next;
while ((next = iff.enterNextForm()) != null) {
String tag = next.getTag();
if (tag.equals("DERV"))
readExtendedAttributes(iff);
else if (tag.contains("0"))
readVersionForm(iff);
else if (!tag.isEmpty())
readNextForm(iff);
iff.exitForm();
}
}
private void readVersionForm(SWGFile iff) {
IffNode attributeChunk;
while ((attributeChunk = iff.enterChunk("XXXX")) != null) {
parseAttributeChunk(attributeChunk);
}
}
private void readExtendedAttributes(SWGFile iff) {
IffNode chunk = iff.enterNextChunk();
String file = chunk.readString();
if (parsedFiles.contains(file)) // some repeated and we do not want to replace any attributes unless they're overriden by a more specific obj
return;
ClientData attrData = ClientFactory.getInfoFromFile(file, true);
if (attrData == null || !(attrData instanceof ObjectData)) {
Log.w("Could not load attribute data from file " + file + "!");
return; // break out of whole method as we should only continue if we have all the extended attributes
}
// Put all the extended attributes in this map so it's accessible. Note that some of these are overridden.
attributes.putAll(((ObjectData)attrData).getAttributes());
parsedFiles.add(file);
}
// Try and parse the attribute to map w/ appropriate Object type.
private void parseAttributeChunk(IffNode chunk) {
String str = chunk.readString();
if (str.isEmpty())
return;
ObjectDataAttribute attr = ObjectDataAttribute.getForName(str);
if (attr == null) {
System.err.println("Unknown attribute: " + str);
return;
}
parseObjectAttribute(chunk, attr);
parseBuildingAttribute(chunk, attr);
parseVehicleAttribute(chunk, attr);
parseWeaponAttribute(chunk, attr);
parseShipAttribute(chunk, attr);
}
private void parseObjectAttribute(IffNode chunk, ObjectDataAttribute attr) {
switch (attr) {
case APPEARANCE_FILENAME: putString(chunk, attr); break;
case ARRANGEMENT_DESCRIPTOR_FILENAME: putString(chunk,attr); break;
case CLEAR_FLORA_RADIUS: putFloat(chunk, attr); break;
case CLIENT_DATA_FILE: putString(chunk, attr); break;
case CLIENT_VISIBILITY_FLAG: putBoolean(chunk, attr); break;
case CONTAINER_TYPE: putInt(chunk, attr); break;
case CONTAINER_VOLUME_LIMIT: putInt(chunk, attr);break;
case DETAILED_DESCRIPTION: putStfString(chunk, attr); break;
case FORCE_NO_COLLISION: putBoolean(chunk, attr); break;
case GAME_OBJECT_TYPE: putInt(chunk, attr); break;
case GENDER: putInt(chunk, attr); break;
case LOCATION_RESERVATION_RADIUS: putFloat(chunk, attr); break;
case LOOK_AT_TEXT: putString(chunk, attr); break;
case NO_BUILD_RADIUS: putFloat(chunk, attr); break;
case OBJECT_NAME: putStfString(chunk, attr); break;
case ONLY_VISIBLE_IN_TOOLS: putBoolean(chunk, attr); break;
case PORTAL_LAYOUT_FILENAME: putString(chunk, attr); break;
case SCALE: putFloat(chunk, attr); break;
case SCALE_THRESHOLD_BEFORE_EXTENT_TEST: putFloat(chunk, attr); break;
case SEND_TO_CLIENT: putBoolean(chunk, attr); break;
case SLOT_DESCRIPTOR_FILENAME: putString(chunk, attr); break;
case SNAP_TO_TERRAIN: putBoolean(chunk, attr); break;
case STRUCTURE_FOOTPRINT_FILENAME: putString(chunk, attr); break;
case SURFACE_TYPE: putInt(chunk, attr); break;
case TARGETABLE: putBoolean(chunk, attr); break;
case TINT_PALETTE: putString(chunk, attr); break;
case USE_STRUCTURE_FOOTPRINT_OUTLINE: putBoolean(chunk, attr); break;
default: break;
}
}
private void parseBuildingAttribute(IffNode chunk, ObjectDataAttribute attr) {
switch (attr) {
case INTERIOR_LAYOUT_FILENAME: putString(chunk, attr); break;
case TERRAIN_MODIFICATION_FILENAME: putString(chunk, attr); break;
default: break;
}
}
private void parseWeaponAttribute(IffNode chunk, ObjectDataAttribute attr) {
switch (attr) {
case WEAPON_EFFECT: putString(chunk, attr); break;
case WEAPON_EFFECT_INDEX: putInt(chunk, attr); break;
case ATTACK_TYPE: putInt(chunk, attr); break;
default: break;
}
}
private void parseVehicleAttribute(IffNode chunk, ObjectDataAttribute attr) {
switch (attr) {
case SPEED: putFloat(chunk, attr); break;
case TURN_RADIUS: putFloat(chunk, attr); break;
case ACCELERATION: putFloat(chunk, attr); break;
default: break;
}
}
private void parseShipAttribute(IffNode chunk, ObjectDataAttribute attr) {
switch (attr) {
case COCKPIT_FILENAME: putString(chunk, attr); break;
case HAS_WINGS: putBoolean(chunk, attr); break;
case PLAYER_CONTROLLED: putBoolean(chunk, attr); break;
default: break;
}
}
private void putStfString(IffNode chunk, ObjectDataAttribute attr) {
if (chunk.readByte() == 0)
return;
String stfFile = getString(chunk);
if (stfFile.isEmpty())
return;
attributes.put(attr, stfFile + ":" + getString(chunk));
}
private String getString(IffNode chunk) {
chunk.readByte();
return chunk.readString();
}
private void putString(IffNode chunk, ObjectDataAttribute attr) {
if (chunk.readByte() == 0)
return;
String s = chunk.readString();
if (s.isEmpty())
return;
attributes.put(attr, s);
}
private void putInt(IffNode chunk, ObjectDataAttribute attr) {
if (chunk.readByte() == 0)
return; // This should always be 1 if there is an int (note that 0x20 follows after this even if it's 0)
chunk.readByte(); // 0x20 byte for all it seems, unsure what it means
attributes.put(attr, chunk.readInt());
}
private void putFloat(IffNode chunk, ObjectDataAttribute attr) {
if (chunk.readByte() == 0)
return; // This should always be 1 if there is an int (note that 0x20 follows after this even if it's 0)
chunk.readByte(); // 0x20 byte for all it seems, unsure what it means
attributes.put(attr, chunk.readFloat());
}
private void putBoolean(IffNode chunk, ObjectDataAttribute attr) {
attributes.put(attr, (chunk.readByte() == 1));
}
public Object getAttribute(ObjectDataAttribute attribute) {
return attributes.get(attribute);
}
public Map<ObjectDataAttribute, Object> getAttributes() {
return attributes;
}
}

View File

@@ -0,0 +1,291 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import com.projectswg.common.data.location.Point3D;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderData;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderSegment;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderableData;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderableDataChild;
/**
* @author Waverunner
*/
public class PortalLayoutData extends ClientData implements RenderableData {
private List<Cell> cells = new LinkedList<>();
private List<Point3D> radarPoints = new ArrayList<>();
@Override
public void readIff(SWGFile iff) {
IffNode versionForm = iff.enterNextForm();
if (versionForm == null) {
System.err.println("Expected version for a POB IFF");
return;
}
int version = versionForm.getVersionFromTag();
switch(version) {
case 3:
readVersion3(iff);
break;
case 4:
readVersion4(iff);
break;
default: System.err.println("Do not know how to handle POB version type " + version + " in file " + iff.getFileName());
}
}
@Override
public List<RenderData> getAllRenderData() {
List<RenderData> render = new ArrayList<>();
render.add(getHighestRenderData());
for (Cell cell : cells) {
if (cell.isSingleRenderData())
render.add(cell.getRenderData());
else
render.addAll(cell.getRenderDataList());
}
return render;
}
@Override
public RenderData getHighestRenderData() {
RenderData ret = new RenderData();
for (Cell cell : cells) {
if (cell.isSingleRenderData())
mergeAll(cell.getRenderData(), ret);
else
mergeAll(cell.getHighestRenderData(), ret);
}
return ret;
}
@Override
public RenderData getProportionalRenderData(double percent) {
RenderData ret = new RenderData();
for (Cell cell : cells) {
if (cell.isSingleRenderData())
mergeAll(cell.getRenderData(), ret);
else
mergeAll(cell.getProportionalRenderData(percent), ret);
}
return ret;
}
private void mergeAll(RenderData src, RenderData dst) {
if (src == null)
return;
for (RenderSegment segment : src.getSegments()) {
dst.addSegment(segment);
}
}
private void readVersion3(SWGFile iff) {
IffNode data = iff.enterChunk("DATA");
int portalCount = data.readInt();
loadPortals3(iff, portalCount);
loadCells(iff);
}
private void readVersion4(SWGFile iff) {
IffNode data = iff.enterChunk("DATA");
int portalCount = data.readInt();
loadPortals4(iff, portalCount);
loadCells(iff);
}
public List<Cell> getCells() {
return cells;
}
public List<Point3D> getRadarPoints() {
return radarPoints;
}
private void loadCells(SWGFile iff) {
iff.enterForm("CELS");
while (iff.enterForm("CELL") != null) {
cells.add(new Cell(iff));
iff.exitForm();
}
iff.exitForm(); // Exit CELS form
}
private void loadPortals3(SWGFile iff, int portalCount) {
IffNode node = iff.enterForm("PRTS");
if (node == null)
System.err.println("Failed to enter PRTS!");
for (int i = 0; i < portalCount; i++) {
IffNode chunk = iff.enterChunk("PRTL");
if (chunk == null)
continue;
int vertices = chunk.readInt();
List<Point3D> points = new ArrayList<>(vertices);
for (int j = 0; j < vertices; j++) {
points.add(chunk.readVector());
}
buildRadar(points);
}
iff.exitForm();
}
private void loadPortals4(SWGFile iff, int portalCount) {
IffNode node = iff.enterForm("PRTS");
if (node == null)
System.err.println("Failed to enter PRTS!");
for (int i = 0; i < portalCount; i++) {
iff.enterForm("IDTL");
iff.enterForm("0000");
IffNode chunk = iff.enterChunk("VERT");
List<Point3D> points = new ArrayList<>(chunk.remaining() / 12);
while (chunk.remaining() >= 12) {
points.add(chunk.readVector());
}
chunk = iff.enterChunk("INDX");
while (chunk.remaining() >= 4) {
radarPoints.add(new Point3D(points.get(chunk.readInt())));
}
iff.exitForm();
iff.exitForm();
}
iff.exitForm();
}
private void buildRadar(List<Point3D> points) {
// Point3D first = points.get(0);
// for (int i = 0; i < points.size()-2; i++) {
// radarPoints.add(first);
// radarPoints.add(points.get(i+1));
// radarPoints.add(points.get(i+2));
// }
radarPoints.addAll(points);
}
public static class Cell extends ClientData {
private String name;
private String appearance;
private List<RenderData> renderDataList;
private RenderData renderData;
private boolean isSingleRenderData;
public Cell(SWGFile iff) {
renderDataList = new ArrayList<>();
renderData = new RenderData();
isSingleRenderData = true;
readIff(iff);
}
@Override
public void readIff(SWGFile iff) {
IffNode versionForm = iff.enterNextForm();
if (versionForm == null) {
System.err.println("Expected version for CELL in IFF " + iff.getFileName());
return;
}
int version = versionForm.getVersionFromTag();
switch(version) {
case 3: readVersion3(iff); break;
case 5: readVersion5(iff); break;
default: System.err.println("Don't know how to handle version " + version + " CELL " + iff.getFileName());
}
iff.exitForm();
}
public RenderData getRenderData() {
return renderData;
}
public boolean isSingleRenderData() {
return isSingleRenderData;
}
public List<RenderData> getRenderDataList() {
return renderDataList;
}
public RenderData getHighestRenderData() {
return renderDataList.isEmpty() ? null : renderDataList.get(renderDataList.size()-1);
}
public RenderData getProportionalRenderData(double percent) {
return renderDataList.isEmpty() ? null : renderDataList.get((int) Math.min(renderDataList.size()-1, percent*renderDataList.size()+0.5));
}
private void readVersion3(SWGFile iff) {
IffNode dataChunk = iff.enterChunk("DATA");
dataChunk.readInt(); // cellPortals
dataChunk.readBoolean(); // canSeeParentCell
appearance = dataChunk.readString();
ClientData data = ClientFactory.getInfoFromFile(appearance);
if (data instanceof RenderableDataChild) {
renderData = ((RenderableDataChild) data).getRenderData();
isSingleRenderData = true;
} else if (data instanceof RenderableData) {
renderDataList.clear();
renderDataList.addAll(((RenderableData) data).getAllRenderData());
isSingleRenderData = false;
}
}
private void readVersion5(SWGFile iff) {
IffNode dataChunk = iff.enterChunk("DATA");
dataChunk.readInt(); // cellPortals
dataChunk.readBoolean(); // canSeeParentCell
name = dataChunk.readString();
appearance = dataChunk.readString();
ClientData data = ClientFactory.getInfoFromFile(appearance);
if (data instanceof RenderableDataChild) {
renderData = ((RenderableDataChild) data).getRenderData();
isSingleRenderData = true;
} else if (data instanceof RenderableData) {
renderDataList.clear();
renderDataList.addAll(((RenderableData) data).getAllRenderData());
isSingleRenderData = false;
}
}
public String getName() {
return name;
}
public String getAppearance() {
return appearance;
}
}
}

View File

@@ -0,0 +1,105 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class ProfTemplateData extends ClientData {
private List<Template> templates = new ArrayList<>();
private static class Template {
private List<String> items;
private String template;
public Template(String template) {
this.template = template;
this.items = new ArrayList<>();
}
public List<String> getItems() {
return items;
}
public String getTemplate() {
return template;
}
}
@Override
public void readIff(SWGFile iff) {
iff.enterNextForm(); // Version
IffNode form;
while((form = iff.enterNextForm()) != null) {
if (!form.getTag().equals("PTMP")) {
iff.exitForm();
continue;
}
IffNode chunk;
while((chunk = iff.enterNextChunk()) != null) {
String tag = chunk.getTag();
switch(tag) {
case "NAME":
templates.add(new Template(chunk.readString()));
break;
case "ITEM":
int index = templates.size() - 1;
chunk.readInt(); // empty int it seems for all items
templates.get(index).getItems().add(chunk.readString());
break;
default: break;
}
}
iff.exitForm();
}
}
/**
* Gets the items for the race
* @param race Race IFF template
* @return {@link List} of the newbie clothing items for the racial template
*/
public List<String> getItems(String race) {
for (Template t : templates) {
if (t.getTemplate().equals(race))
return t.getItems();
}
return null;
}
}

View File

@@ -0,0 +1,60 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class SlotArrangementData extends ClientData {
private List <List <String>> occupiedSlots = new ArrayList<>();
@Override
public void readIff(SWGFile iff) {
iff.enterNextForm(); // Version
List<String> slots = new ArrayList<>();
IffNode chunk = iff.enterNextChunk(); // Enter ARG chunk
String slotName;
while((slotName = chunk.readString()) != null && !slotName.isEmpty()) { // Read strings until there are none left.
slots.add(slotName);
}
occupiedSlots.add(slots);
}
public List <List<String>> getArrangement() {
return occupiedSlots;
}
}

View File

@@ -0,0 +1,89 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.HashMap;
import java.util.Map;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class SlotDefinitionData extends ClientData {
private Map<String, SlotDefinition> definitions = new HashMap<>();
public static class SlotDefinition {
private String name;
private boolean isGlobal;
private boolean isModdable;
private boolean isExclusive;
private boolean hasHardpoint;
private String hardpointName;
public String getName() { return name; }
public boolean isGlobal() { return isGlobal; }
public boolean isModdable() { return isModdable; }
public boolean isExclusive() { return isExclusive; }
public boolean hasHardpoint() { return hasHardpoint; }
public String getHardpointName() { return hardpointName; }
public void setName(String name) { this.name = name; }
public void setGlobal(boolean isGlobal) { this.isGlobal = isGlobal; }
public void setModdable(boolean isModdable) { this.isModdable = isModdable; }
public void setExclusive(boolean isExclusive) { this.isExclusive = isExclusive; }
public void setHasHardpoint(boolean hasHardpoint) { this.hasHardpoint = hasHardpoint; }
public void setHardpointName(String hardpointName) { this.hardpointName = hardpointName; }
}
@Override
public void readIff(SWGFile iff) {
IffNode data = iff.enterChunk("DATA");
data.readChunk((chunk) -> {
SlotDefinition def = new SlotDefinition();
def.setName(chunk.readString());
def.setGlobal(chunk.readBoolean());
def.setModdable(chunk.readBoolean());
def.setExclusive(chunk.readBoolean());
def.setHasHardpoint(chunk.readBoolean());
def.setHardpointName(chunk.readString());
chunk.readBoolean(); // "combat bone"
chunk.readBoolean(); // "observe with parent"
chunk.readBoolean(); // "expose with parent"
definitions.put(def.name, def);
});
}
public SlotDefinition getDefinition(String name) {
return definitions.get(name);
}
}

View File

@@ -0,0 +1,58 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class SlotDescriptorData extends ClientData {
private List<String> slots = new ArrayList<>();
@Override
public void readIff(SWGFile iff) {
iff.enterNextForm(); // version
IffNode chunk = iff.enterChunk("DATA");
String slot;
while (!(slot = chunk.readString()).isEmpty()) {
slots.add(slot);
}
}
public List<String> getSlots() {
return slots;
}
}

View File

@@ -0,0 +1,213 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.data.swgfile.visitors;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class WorldSnapshotData extends ClientData {
private Map<Integer, String> objectTemplateNames = new HashMap<>();
private List<Node> nodes = new LinkedList<>();
@Override
public void readIff(SWGFile iff) {
IffNode versionForm = iff.enterNextForm();
if (versionForm == null) {
System.err.println("Expected a version form for " + iff.getFileName());
return;
}
int version = versionForm.getVersionFromTag();
switch (version) {
case 1: readVersion1(iff); break;
default: System.err.println("Don't know how to handle version " + version + " in IFF " + iff.getFileName());
}
}
private void readVersion1(SWGFile iff) {
iff.enterForm("NODS");
while(iff.enterNextForm() != null) {
nodes.add(new Node(iff));
iff.exitForm();
}
iff.exitForm(); // Exit NODS form
IffNode chunk = iff.enterChunk("OTNL");
int size = chunk.readInt();
for (int i = 0; i < size; i++) {
objectTemplateNames.put(i, chunk.readString());
}
}
public Map<Integer, String> getObjectTemplateNames() {
return objectTemplateNames;
}
public List<Node> getNodes() {
return nodes;
}
public class Node extends ClientData {
private int id;
private int containerId;
private int objectTemplateNameIndex;
private int cellIndex;
private Location location;
private float radius;
private int portalLayoutCrc;
private List<Node> children = new LinkedList<>();
public Node(SWGFile iff) {
readIff(iff);
}
@Override
public void readIff(SWGFile iff) {
IffNode versionForm = iff.enterNextForm();
if (versionForm == null) {
System.err.println("Expected version form for WorldSnapshot IFF " + iff.getFileName());
return;
}
int version = versionForm.getVersionFromTag();
switch(version) {
case 0: readVersion0(iff); break;
default: System.err.println("Unknown version " + version + " in Node for " + iff.getFileName());
}
iff.exitForm();
}
private void readVersion0(SWGFile iff) {
IffNode chunk = iff.enterChunk("DATA");
id = chunk.readInt();
containerId = chunk.readInt();
objectTemplateNameIndex = chunk.readInt();
cellIndex = chunk.readInt();
location = new Location();
location.setOrientationW(chunk.readFloat());
location.setOrientationX(chunk.readFloat());
location.setOrientationY(chunk.readFloat());
location.setOrientationZ(chunk.readFloat());
location.setX(chunk.readFloat());
location.setY(chunk.readFloat());
location.setZ(chunk.readFloat());
radius = chunk.readFloat();
portalLayoutCrc = chunk.readUInt();
while(iff.enterNextForm() != null) {
Node node = new Node(iff);
children.add(node);
iff.exitForm();
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getContainerId() {
return containerId;
}
public void setContainerId(int containerId) {
this.containerId = containerId;
}
public int getObjectTemplateNameIndex() {
return objectTemplateNameIndex;
}
public void setObjectTemplateNameIndex(int objectTemplateNameIndex) {
this.objectTemplateNameIndex = objectTemplateNameIndex;
}
public int getCellIndex() {
return cellIndex;
}
public void setCellIndex(int cellIndex) {
this.cellIndex = cellIndex;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
}
public int getPortalLayoutCrc() {
return portalLayoutCrc;
}
public void setPortalLayoutCrc(int portalLayoutCrc) {
this.portalLayoutCrc = portalLayoutCrc;
}
public List<Node> getChildren() {
return children;
}
@Override
public boolean equals(Object o) {
return o instanceof Node && id == ((Node) o).getId();
}
@Override
public int hashCode() {
return id;
}
}
}

View File

@@ -0,0 +1,105 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.location.Point3D;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class AppearanceTemplateData extends ClientData {
private final List<Hardpoint> hardpoints;
private String floor;
public AppearanceTemplateData() {
hardpoints = new ArrayList<>();
floor = "";
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0003":
readForm3(iff);
break;
default:
System.err.println("Unknown AppearanceTemplateData version: " + node.getTag());
break;
}
iff.exitForm();
}
public List<Hardpoint> getHardpoints() {
return hardpoints;
}
public String getFloor() {
return floor;
}
private void readForm3(SWGFile iff) {
readHardpoints(iff);
readFloor(iff);
}
private void readHardpoints(SWGFile iff) {
IffNode node = iff.enterForm("HPTS");
IffNode hptChunk = null;
double [] translation = new double[3];
while ((hptChunk = node.getNextUnreadChunk()) != null) {
for (int y = 0; y < 3; y++) {
hptChunk.readFloat();
hptChunk.readFloat();
hptChunk.readFloat();
translation[y] = hptChunk.readFloat();
}
byte [] str = new byte[hptChunk.remaining()];
for (int i = 0; i < str.length; i++)
str[i] = hptChunk.readByte();
hardpoints.add(new Hardpoint(new String(str, StandardCharsets.UTF_8), new Point3D(translation[0], translation[1], translation[2])));
}
iff.exitForm();
}
private void readFloor(SWGFile iff) {
iff.enterForm("FLOR");
IffNode node = iff.enterChunk("DATA");
if (node.readBoolean())
floor = node.readString();
else
floor = "";
iff.exitForm();
}
}

View File

@@ -0,0 +1,91 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.List;
import com.projectswg.common.debug.Log;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderData;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderableData;
public class AppearanceTemplateList extends ClientData implements RenderableData {
private RenderableData subAppearance;
public AppearanceTemplateList() {
subAppearance = null;
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0000":
readForm0(iff);
break;
default:
System.err.println("Unknown AppearanceTemplateData version: " + node.getTag());
break;
}
}
@Override
public List<RenderData> getAllRenderData() {
if (subAppearance == null)
return null;
return subAppearance.getAllRenderData();
}
@Override
public RenderData getHighestRenderData() {
if (subAppearance == null)
return null;
return subAppearance.getHighestRenderData();
}
@Override
public RenderData getProportionalRenderData(double percent) {
if (subAppearance == null)
return null;
return subAppearance.getProportionalRenderData(percent);
}
private void readForm0(SWGFile iff) {
IffNode node = iff.enterChunk("NAME");
ClientData child = ClientFactory.getInfoFromFile(node.readString());
if (child instanceof RenderableData)
subAppearance = (RenderableData) child;
else
Log.e("Sub-appearance does not implement RenderableData!");
}
}

View File

@@ -0,0 +1,138 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.location.Quaternion;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class BasicSkeletonTemplate extends ClientData {
private final List<Joint> joints;
private int jointCount;
public BasicSkeletonTemplate() {
joints = new ArrayList<>();
jointCount = 0;
}
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0002":
readForm2(iff);
break;
default:
System.err.println("Unknown BasicSkeletonTemplate version: " + node.getTag());
break;
}
iff.exitForm();
}
public List<Joint> getJoints() {
return joints;
}
private void readForm2(SWGFile iff) {
readInfo(iff.enterChunk("INFO"));
readNames(iff.enterChunk("NAME"));
readParents(iff.enterChunk("PRNT"));
readPreMultiply(iff.enterChunk("RPRE"));
readPostMultiply(iff.enterChunk("RPST"));
}
private void readInfo(IffNode node) {
jointCount = node.readInt();
}
private void readNames(IffNode node) {
joints.clear();
for (int i = 0; i < jointCount; i++) {
joints.add(new Joint(node.readString()));
}
}
private void readParents(IffNode node) {
for (int i = 0; i < jointCount; i++) {
int parent = node.readInt();
if (parent == -1)
continue;
joints.get(i).setParent(joints.get(parent));
}
}
private void readPreMultiply(IffNode node) {
for (Joint j : joints) {
j.setPreMultiply(readQuaternion(node));
}
}
private void readPostMultiply(IffNode node) {
for (Joint j : joints) {
j.setPostMultiply(readQuaternion(node));
}
}
private Quaternion readQuaternion(IffNode node) {
float w = node.readFloat();
float x = node.readFloat();
float y = node.readFloat();
float z = node.readFloat();
return new Quaternion(x, y, z, w);
}
public static class Joint {
private final String name;
private Joint parent;
private Quaternion preMultiply;
private Quaternion postMultiply;
public Joint(String name) {
this.name = name;
this.parent = null;
}
public String getName() { return name; }
public Joint getParent() { return parent; }
public Quaternion getPreMultiply() { return preMultiply; }
public Quaternion getPostMultiply() { return postMultiply; }
public void setParent(Joint parent) { this.parent = parent; }
public void setPreMultiply(Quaternion preMultiply) { this.preMultiply = preMultiply; }
public void setPostMultiply(Quaternion postMultiply) { this.postMultiply = postMultiply; }
public String toString() { return String.format("Joint[name=%s]", name); }
}
}

View File

@@ -0,0 +1,151 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.debug.Log;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderData;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderableData;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderableDataChild;
public class DetailedAppearanceTemplateData extends ClientData implements RenderableData {
private final List<RenderableDataChild> children;
private IndexedTriangleList radar;
private IndexedTriangleList test;
private IndexedTriangleList write;
public DetailedAppearanceTemplateData() {
children = new ArrayList<>();
radar = null;
test = null;
write = null;
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0007":
readForm7(iff);
break;
case "0008":
readForm7(iff);
break;
default:
System.err.println("Unknown DetailedAppearanceTemplateData version: " + node.getTag());
break;
}
iff.exitForm();
}
@Override
public List<RenderData> getAllRenderData() {
List<RenderData> all = new ArrayList<>();
for (RenderableDataChild child : children)
all.add(child.getRenderData());
return all;
}
@Override
public RenderData getHighestRenderData() {
return children.isEmpty() ? null : children.get(children.size()-1).getRenderData();
}
@Override
public RenderData getProportionalRenderData(double percent) {
return children.isEmpty() ? null : children.get((int) Math.min(children.size()-1, percent*children.size()+0.5)).getRenderData();
}
public IndexedTriangleList getRadar() {
return radar;
}
public IndexedTriangleList getTest() {
return test;
}
public IndexedTriangleList getWrite() {
return write;
}
private void readForm7(SWGFile iff) {
IffNode node = iff.enterForm("APPR");
if (node != null) {
readAppearance(iff);
iff.exitForm();
}
node = iff.enterForm("RADR");
radar = readVertices(iff);
iff.exitForm();
node = iff.enterForm("TEST");
test = readVertices(iff);
iff.exitForm();
node = iff.enterForm("WRIT");
write = readVertices(iff);
iff.exitForm();
node = iff.enterForm("DATA");
readChildren(iff);
iff.exitForm();
}
private void readAppearance(SWGFile iff) {
AppearanceTemplateData appearance = new AppearanceTemplateData();
appearance.readIff(iff);
}
private IndexedTriangleList readVertices(SWGFile iff) {
IffNode node = iff.enterChunk("INFO");
boolean hasVertices = node.readInt() != 0;
if (!hasVertices)
return new IndexedTriangleList();
IndexedTriangleList list = new IndexedTriangleList();
list.readIff(iff);
return list;
}
private void readChildren(SWGFile iff) {
IffNode node = null; // Only going to read the last one
while ((node = iff.enterChunk("CHLD")) != null) {
node.readInt(); // id
String name = node.readString();
ClientData child = ClientFactory.getInfoFromFile("appearance/"+name);
if (child instanceof RenderableDataChild)
children.add((RenderableDataChild) child);
else
Log.e("Child does not implement RenderableDataChild!");
}
}
}

View File

@@ -0,0 +1,58 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import com.projectswg.common.data.location.Point3D;
public class Hardpoint {
private String name;
private Point3D translation;
public Hardpoint(String name, Point3D translation) {
this.name = name;
this.translation = translation;
}
public String getName() {
return name;
}
public Point3D getTranslation() {
return translation;
}
public void setName(String name) {
this.name = name;
}
public void setTranslation(Point3D translation) {
this.translation = translation;
}
}

View File

@@ -0,0 +1,84 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.location.Point3D;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class IndexedTriangleList extends ClientData {
private final List<Point3D> points;
private final List<Integer> indices;
public IndexedTriangleList() {
points = new ArrayList<>();
indices = new ArrayList<>();
}
@Override
public void readIff(SWGFile iff) {
iff.enterForm("IDTL");
IffNode node = iff.enterNextForm();
if (!node.getTag().equals("0000")) {
iff.exitForm();
return;
}
readForm0(iff);
iff.exitForm();
iff.exitForm();
}
public List<Point3D> getPoints() {
return points;
}
public List<Integer> getIndices() {
return indices;
}
private void readForm0(SWGFile iff) {
IffNode node = iff.enterChunk("VERT");
int count = node.remaining() / 12;
points.clear();
for (int i = 0; i < count; i++) {
points.add(new Point3D(node.readFloat(), node.readFloat(), node.readFloat()));
}
node = iff.enterChunk("INDX");
count = node.remaining() / 4;
indices.clear();
for (int i = 0; i < count; i++) {
indices.add(node.readInt());
}
}
}

View File

@@ -0,0 +1,103 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class LodDistanceTable extends ClientData {
private final List<Level> levels;
public LodDistanceTable() {
levels = new ArrayList<>();
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0000":
readForm0(iff);
break;
}
}
public List<Level> getLevels() {
return levels;
}
private void readForm0(SWGFile iff) {
IffNode node = iff.enterChunk("INFO");
int levelCount = node.readShort();
levels.clear();
for (int i = 0; i < levelCount; i++) {
Level level = new Level();
level.setMinDistance(node.readFloat());
level.setMaxDistance(node.readFloat());
levels.add(level);
}
}
public static class Level {
private float minDistance;
private float maxDistance;
public Level() {
}
public float getMinDistance() {
return minDistance;
}
public float getMaxDistance() {
return maxDistance;
}
public void setMinDistance(float minDistance) {
this.minDistance = minDistance;
}
public void setMaxDistance(float maxDistance) {
this.maxDistance = maxDistance;
}
public String toString() {
return String.format("Level[min=%.3f max=%.3f]", minDistance, maxDistance);
}
}
}

View File

@@ -0,0 +1,85 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.HashMap;
import java.util.Map;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class LodMeshGeneratorTemplateData extends ClientData {
private final Map<String, SkeletalMeshGeneratorTemplateData> generators;
private int lodCount;
public LodMeshGeneratorTemplateData() {
generators = new HashMap<>();
lodCount = 0;
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0000":
readForm0(iff);
break;
default:
System.err.println("Unknown LodMeshGeneratorTemplateData version: " + node.getTag());
break;
}
iff.exitForm();
}
public Map<String, SkeletalMeshGeneratorTemplateData> getGenerators() {
return generators;
}
private void readForm0(SWGFile iff) {
readInfo(iff.enterChunk("INFO"));
readNames(iff);
}
private void readInfo(IffNode node) {
lodCount = node.readShort();
}
private void readNames(SWGFile iff) {
for (int i = 0; i < lodCount; i++) {
IffNode node = iff.enterChunk("NAME");
String name = node.readString();
generators.put(name, (SkeletalMeshGeneratorTemplateData) ClientFactory.getInfoFromFile(name, false));
}
}
}

View File

@@ -0,0 +1,71 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class LodSkeletonTemplateData extends ClientData {
private int lodCount;
public LodSkeletonTemplateData() {
lodCount = 0;
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0000":
readForm0(iff);
break;
default:
System.err.println("Unknown LodMeshGeneratorTemplateData version: " + node.getTag());
break;
}
iff.exitForm();
}
private void readForm0(SWGFile iff) {
readInfo(iff.enterChunk("INFO"));
for (int i = 0; i < lodCount; i++) {
iff.enterNextForm();
BasicSkeletonTemplate list = new BasicSkeletonTemplate();
list.readIff(iff);
iff.exitForm();
}
}
private void readInfo(IffNode node) {
lodCount = node.readShort();
}
}

View File

@@ -0,0 +1,221 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import com.projectswg.common.data.location.Point3D;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderData;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderSegment;
import com.projectswg.common.data.swgfile.visitors.appearance.render.RenderableDataChild;
import com.projectswg.common.data.swgfile.visitors.appearance.render.Vertex;
import com.projectswg.common.data.swgfile.visitors.shader.ShaderData;
public class MeshAppearanceTemplate extends ClientData implements RenderableDataChild {
private static final int F_position = 0b00000000000000000000000000000001;
private static final int F_transformed = 0b00000000000000000000000000000010;
private static final int F_normal = 0b00000000000000000000000000000100;
private static final int F_color0 = 0b00000000000000000000000000001000;
private static final int F_color1 = 0b00000000000000000000000000010000;
private static final int F_pointSize = 0b00000000000000000000000000100000;
private static final int textureCoordinateSetCountShift = 8;
private static final int textureCoordinateSetCountMask = 0b1111;
private static final int textureCoordinateSetDimensionBaseShift = 12;
private static final int textureCoordinateSetDimensionPerSetShift = 2;
private static final int textureCoordinateSetDimensionAdjustment = 1;
private static final int textureCoordinateSetDimensionMask = 0b0011;
private final RenderData renderData;
private AppearanceTemplateData template;
public MeshAppearanceTemplate() {
renderData = new RenderData();
template = null;
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0004":
readForm4(iff);
break;
case "0005":
readForm5(iff);
break;
default:
System.err.println("Unknown MeshAppearanceTemplate version: " + node.getTag());
break;
}
iff.exitForm();
}
public RenderData getRenderData() {
return renderData;
}
public AppearanceTemplateData getTemplate() {
return template;
}
private void readForm4(SWGFile iff) {
readForm5(iff);
}
private void readForm5(SWGFile iff) {
template = new AppearanceTemplateData();
iff.enterForm("APPR");
template.readIff(iff);
iff.exitForm();
iff.enterForm("SPS ");
loadSps(iff);
iff.exitForm();
}
private void loadSps(SWGFile iff) {
iff.enterForm("0001");
IffNode node = iff.enterChunk("CNT ");
int count = node.readInt();
for (int i = 0; i < count; i++) {
RenderSegment segment = new RenderSegment();
iff.enterForm(String.format("%04d", i + 1));
node = iff.enterChunk("NAME");
ShaderData shader = (ShaderData) ClientFactory.getInfoFromFile(node.readString());
if (shader != null)
segment.setTextureFile(shader.getTextureFile());
iff.enterChunk("INFO");
iff.enterNextForm();
readMeshData(iff, segment);
iff.exitForm();
iff.exitForm();
renderData.addSegment(segment);
}
}
private void readMeshData(SWGFile iff, RenderSegment segment) {
IffNode node = iff.enterChunk("INFO");
node.readInt(); // draw type
boolean hasIndices = node.readBoolean();
iff.enterForm("VTXA");
iff.enterForm("0003");
node = iff.enterChunk("INFO");
int format = node.readInt();
int vertexCount = node.readInt();
segment.setVertices(readVertices(iff.enterChunk("DATA"), format, vertexCount));
iff.exitForm();
iff.exitForm();
if (hasIndices) {
segment.setIndices(loadStaticIndices(iff.enterChunk("INDX")));
}
}
private Vertex [] readVertices(IffNode node, int format, int vertexCount) {
Vertex [] vertices = new Vertex[vertexCount];
for (int i = 0; i < vertexCount; i++) {
Vertex v = new Vertex();
Point3D p = new Point3D(0, 0, 0);
v.setPoint(p);
if (hasPosition(format))
p.set(node.readFloat(), node.readFloat(), node.readFloat());
if (isTransformed(format))
node.readFloat(); // ooz
if (hasNormal(format)) {
node.readFloat();
node.readFloat();
node.readFloat(); // normal
}
if (hasPointSize(format))
node.readFloat(); // point size
if (hasColor0(format))
node.readInt();
if (hasColor1(format))
node.readInt();
for (int j = 0; j < getNumberOfTextureCoordinateSets(format); ++j) {
int dimension = getTextureCoordinateSetDimension(format, j);
for (int k = 0; k < dimension; ++k) {
float f = node.readFloat();
if (dimension == 2) {
if (k == 0)
v.setTexCoordinateX(f);
else
v.setTexCoordinateY(f);
}
}
}
vertices[i] = v;
}
return vertices;
}
private int [] loadStaticIndices(IffNode node) {
int count = node.readInt();
int [] indices = new int[count];
for (int i = 0; i < count; i++) {
indices[i] = node.readShort();
}
return indices;
}
private boolean hasPosition(int format) {
return (format & F_position) != 0;
}
private boolean isTransformed(int format) {
return (format & F_transformed) != 0;
}
private boolean hasNormal(int format) {
return (format & F_normal) != 0;
}
private boolean hasPointSize(int format) {
return (format & F_pointSize) != 0;
}
private boolean hasColor0(int format) {
return (format & F_color0) != 0;
}
private boolean hasColor1(int format) {
return (format & F_color1) != 0;
}
private int getNumberOfTextureCoordinateSets(int format) {
return (format >> textureCoordinateSetCountShift) & (textureCoordinateSetCountMask);
}
private int getTextureCoordinateSetDimension(int format, int textureCoordinateSet) {
int shift = textureCoordinateSetDimensionBaseShift + (textureCoordinateSet * textureCoordinateSetDimensionPerSetShift);
return ((format >> shift) & textureCoordinateSetDimensionMask) + textureCoordinateSetDimensionAdjustment;
}
}

View File

@@ -0,0 +1,133 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.HashMap;
import java.util.Map;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class SkeletalAppearanceData extends ClientData {
private final Map<String, LodMeshGeneratorTemplateData> meshGenerators;
private final Map<String, String> skeletonInfo;
private final Map<String, String> latxPairs;
private LodDistanceTable lodDistanceTable;
private int meshGeneratorCount;
private int skeletonTemplateCount;
private boolean createAnimationController;
public SkeletalAppearanceData() {
meshGenerators = new HashMap<>();
skeletonInfo = new HashMap<>();
latxPairs = new HashMap<>();
lodDistanceTable = null;
meshGeneratorCount = 0;
skeletonTemplateCount = 0;
createAnimationController = false;
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0003":
readForm3(iff);
break;
}
}
public Map<String, LodMeshGeneratorTemplateData> getMeshGenerators() {
return meshGenerators;
}
public Map<String, String> getSkeletonInfo() {
return skeletonInfo;
}
public Map<String, String> getLatxPairs() {
return latxPairs;
}
public LodDistanceTable getLodDistanceTable() {
return lodDistanceTable;
}
public boolean isCreateAnimationController() {
return createAnimationController;
}
private void readForm3(SWGFile iff) {
readInfo(iff.enterChunk("INFO"));
readMeshGenerator(iff.enterChunk("MSGN"));
readSkeletonInfo(iff.enterChunk("SKTI"));
IffNode node = iff.enterChunk("LATX");
if (node != null)
readLATX(node);
node = iff.enterForm("LDTB");
if (node != null)
readLDTB(iff);
}
private void readInfo(IffNode node) {
meshGeneratorCount = node.readInt();
skeletonTemplateCount = node.readInt();
createAnimationController = node.readBoolean();
}
private void readMeshGenerator(IffNode node) {
for (int i = 0; i < meshGeneratorCount; i++) {
String name = node.readString();
meshGenerators.put(name, (LodMeshGeneratorTemplateData) ClientFactory.getInfoFromFile(name, false));
}
}
private void readSkeletonInfo(IffNode node) {
for (int i = 0; i < skeletonTemplateCount; i++) {
skeletonInfo.put(node.readString(), node.readString());
}
}
private void readLATX(IffNode node) {
int count = node.readShort();
for (int i = 0; i < count; i++) {
latxPairs.put(node.readString(), node.readString());
}
}
private void readLDTB(SWGFile iff) {
lodDistanceTable = new LodDistanceTable();
lodDistanceTable.readIff(iff);
}
}

View File

@@ -0,0 +1,246 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.geometry.Point3D;
import com.projectswg.common.data.swgfile.ClientData;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class SkeletalMeshGeneratorTemplateData extends ClientData {
private final Map<String, ClientData> skeletonTemplateNames;
private final List<String> transformNames;
private final List<Point3D> positions;
private final List<Integer> transformWeightCounts;
private final List<TransformWeightData> transformWeights;
private final List<OcclusionZone> occlusionZones;
private int maxTransformsPerVertex;
private int maxTransformsPerShader;
private int occlusionLayer;
private InfoChunk infoChunk;
public SkeletalMeshGeneratorTemplateData() {
skeletonTemplateNames = new HashMap<>();
transformNames = new ArrayList<>();
positions = new ArrayList<>();
transformWeightCounts = new ArrayList<>();
transformWeights = new ArrayList<>();
occlusionZones = new ArrayList<>();
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0004":
readForm4(iff);
break;
default:
System.err.println("Unknown SkeletalMeshGeneratorTemplateData version: " + node.getTag());
break;
}
iff.exitForm();
}
public Map<String, ClientData> getSkeletonTemplateNames() {
return skeletonTemplateNames;
}
public List<String> getTransformNames() {
return transformNames;
}
public List<Point3D> getPositions() {
return positions;
}
public List<Integer> getTransformWeightCounts() {
return transformWeightCounts;
}
public List<TransformWeightData> getTransformWeights() {
return transformWeights;
}
public int getMaxTransformsPerVertex() {
return maxTransformsPerVertex;
}
public int getMaxTransformsPerShader() {
return maxTransformsPerShader;
}
public int getOcclusionLayer() {
return occlusionLayer;
}
public InfoChunk getInfoChunk() {
return infoChunk;
}
private void readForm4(SWGFile iff) {
readInfo(iff.enterChunk("INFO"));
readSkeletonTemplateNames(iff.enterChunk("SKTM"));
readTransformNames(iff.enterChunk("XFNM"));
readPositionVectors(iff.enterChunk("POSN"));
readTransformWeightingHeader(iff.enterChunk("TWHD"));
readTransformWeightingData(iff.enterChunk("TWDT"));
if (infoChunk.getOcclusionZoneCount() > 0)
readOcclusionZoneNames(iff.enterChunk("OZN "));
}
private void readInfo(IffNode node) {
maxTransformsPerVertex = node.readInt();
maxTransformsPerShader = node.readInt();
infoChunk = new InfoChunk(node);
occlusionLayer = node.readShort();
}
private void readSkeletonTemplateNames(IffNode node) {
for (int i = 0; i < infoChunk.getSkeletonTemplateNameCount(); i++) {
String name = node.readString();
skeletonTemplateNames.put(name, ClientFactory.getInfoFromFile(name));
}
}
private void readTransformNames(IffNode node) {
for (int i = 0; i < infoChunk.getTransformNameCount(); i++) {
transformNames.add(node.readString());
}
}
private void readPositionVectors(IffNode node) {
for (int i = 0; i < infoChunk.getPositionCount(); i++) {
positions.add(new Point3D(node.readFloat(), node.readFloat(), node.readFloat()));
}
}
private void readTransformWeightingHeader(IffNode node) {
for (int i = 0; i < infoChunk.getPositionCount(); i++) {
transformWeightCounts.add(node.readInt());
}
}
private void readTransformWeightingData(IffNode node) {
for (int i = 0; i < infoChunk.getTransformWeightDataCount(); i++) {
transformWeights.add(new TransformWeightData(node.readInt(), node.readFloat()));
}
}
private void readOcclusionZoneNames(IffNode node) {
for (int i = 0; i < infoChunk.getOcclusionZoneCount(); i++) {
String name = node.readString();
boolean found = false;
for (int j = 0; j < i && !found; j++) {
if (occlusionZones.get(j).getName().equals(name))
found = true;
}
if (!found)
occlusionZones.add(new OcclusionZone(occlusionZones.size(), name));
}
}
public static class TransformWeightData {
private int index;
private float weight;
public TransformWeightData(int index, float weight) {
this.index = index;
this.weight = weight;
}
public int getIndex() { return index; }
public float getWeight() { return weight; }
public String toString() { return String.format("TransformWeightData[index=%d weight=%.2f]", index, weight); }
}
public static class OcclusionZone {
private final int id;
private final String name;
public OcclusionZone(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() { return id; }
public String getName() { return name; }
}
public static class InfoChunk {
private int skeletonTemplateNameCount;
private int transformNameCount;
private int positionCount;
private int transformWeightDataCount;
private int normalCount;
private int perShaderDataCount;
private int blendTargetCount;
private int occlusionZoneCount;
private int occlusionZoneCombinationCount;
private int zonesThisOccludesCount;
public InfoChunk(IffNode node) {
skeletonTemplateNameCount = node.readInt();
transformNameCount = node.readInt();
positionCount = node.readInt();
transformWeightDataCount = node.readInt();
normalCount = node.readInt();
perShaderDataCount = node.readInt();
blendTargetCount = node.readInt();
occlusionZoneCount = node.readShort();
occlusionZoneCombinationCount = node.readShort();
zonesThisOccludesCount = node.readShort();
}
public int getSkeletonTemplateNameCount() { return skeletonTemplateNameCount; }
public int getTransformNameCount() { return transformNameCount; }
public int getPositionCount() { return positionCount; }
public int getTransformWeightDataCount() { return transformWeightDataCount; }
public int getNormalCount() { return normalCount; }
public int getPerShaderDataCount() { return perShaderDataCount; }
public int getBlendTargetCount() { return blendTargetCount; }
public int getOcclusionZoneCount() { return occlusionZoneCount; }
public int getOcclusionZoneCombinationCount() { return occlusionZoneCombinationCount; }
public int getZonesThisOccludesCount() { return zonesThisOccludesCount; }
}
}

View File

@@ -0,0 +1,53 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance.render;
import java.util.ArrayList;
import java.util.List;
public class RenderData {
private final List<RenderSegment> segments;
public RenderData() {
segments = new ArrayList<>();
}
public void addSegment(RenderSegment segment) {
this.segments.add(segment);
}
public void clear() {
segments.clear();
}
public List<RenderSegment> getSegments() {
return segments;
}
}

View File

@@ -0,0 +1,84 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance.render;
import java.util.List;
public class RenderSegment {
private static final Vertex [] EMPTY_VERTICES = new Vertex[0];
private static final int [] EMPTY_INDICES = new int[0];
private Vertex [] vertices;
private int [] indices;
private String textureFile;
public RenderSegment() {
vertices = EMPTY_VERTICES;
indices = EMPTY_INDICES;
textureFile = "";
}
public void setVertices(Vertex [] vertices) {
this.vertices = vertices;
}
public void setVertices(List <Vertex> vertices) {
this.vertices = new Vertex[vertices.size()];
this.vertices = vertices.toArray(this.vertices);
}
public void setIndices(int [] indices) {
this.indices = indices;
}
public void setIndices(List <Integer> indices) {
this.indices = new int[indices.size()];
for (int i = 0; i < indices.size(); ++i) {
this.indices[i] = indices.get(i);
}
}
public void setTextureFile(String textureFile) {
this.textureFile = textureFile;
}
public Vertex [] getVertices() {
return vertices;
}
public int [] getIndices() {
return indices;
}
public String getTextureFile() {
return textureFile;
}
}

View File

@@ -0,0 +1,38 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance.render;
import java.util.List;
public interface RenderableData {
public List<RenderData> getAllRenderData();
public RenderData getHighestRenderData();
public RenderData getProportionalRenderData(double percent);
}

View File

@@ -0,0 +1,35 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance.render;
public interface RenderableDataChild {
public RenderData getRenderData();
}

View File

@@ -0,0 +1,68 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.appearance.render;
import com.projectswg.common.data.location.Point3D;
public class Vertex {
private Point3D point;
private float texCoordinateX;
private float texCoordinateY;
public Vertex() {
point = null;
texCoordinateX = 0;
texCoordinateY = 0;
}
public Point3D getPoint() {
return point;
}
public float getTexCoordinateX() {
return texCoordinateX;
}
public float getTexCoordinateY() {
return texCoordinateY;
}
public void setPoint(Point3D p) {
this.point = p;
}
public void setTexCoordinateX(float x) {
texCoordinateX = x;
}
public void setTexCoordinateY(float y) {
texCoordinateY = y;
}
}

View File

@@ -0,0 +1,85 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.shader;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class CustomizableShaderData extends ShaderData {
private String ddsFile;
public CustomizableShaderData() {
ddsFile = "";
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0000":
readForm0(iff);
break;
case "0001":
readForm1(iff);
break;
default:
System.err.println("Unknown CustomizableShaderData version: " + node.getTag());
break;
}
iff.exitForm();
}
@Override
public String getTextureFile() {
return ddsFile;
}
private void readForm0(SWGFile iff) {
iff.enterForm("TXMS");
while (iff.enterForm("TXM ") != null) {
iff.enterForm("0001");
IffNode nameChunk = iff.enterChunk("NAME");
IffNode dataChunk = iff.enterChunk("DATA");
if (dataChunk.readInt() == 'M'*256*256*256+'A'*256*256+'I'*256+'N')
ddsFile = nameChunk.readString();
iff.exitForm();
iff.exitForm();
}
}
private void readForm1(SWGFile iff) {
StaticShaderData staticData = new StaticShaderData();
iff.enterForm("SSHT");
staticData.readIff(iff);
iff.exitForm();
ddsFile = staticData.getTextureFile();
}
}

View File

@@ -0,0 +1,37 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.shader;
import com.projectswg.common.data.swgfile.ClientData;
public abstract class ShaderData extends ClientData {
public abstract String getTextureFile();
}

View File

@@ -0,0 +1,73 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.data.swgfile.visitors.shader;
import com.projectswg.common.data.swgfile.IffNode;
import com.projectswg.common.data.swgfile.SWGFile;
public class StaticShaderData extends ShaderData {
private String ddsFile;
public StaticShaderData() {
ddsFile = "";
}
@Override
public void readIff(SWGFile iff) {
IffNode node = iff.enterNextForm();
switch (node.getTag()) {
case "0000":
readForm0(iff);
break;
default:
System.err.println("Unknown StaticShaderData version: " + node.getTag());
break;
}
iff.exitForm();
}
@Override
public String getTextureFile() {
return ddsFile;
}
private void readForm0(SWGFile iff) {
iff.enterForm("TXMS");
while (iff.enterForm("TXM ") != null) {
iff.enterForm("0001");
IffNode nameChunk = iff.enterChunk("NAME");
IffNode dataChunk = iff.enterChunk("DATA");
if (dataChunk.readInt() == 'M'*256*256*256+'A'*256*256+'I'*256+'N')
ddsFile = nameChunk.readString();
iff.exitForm();
iff.exitForm();
}
}
}

View File

@@ -0,0 +1,55 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.encoding;
public class CachedEncode {
private final EncodeOnly encodable;
private byte [] cached;
public CachedEncode(EncodeOnly encodable) {
this.encodable = encodable;
this.cached = null;
}
public void clearCached() {
this.cached = null;
}
public byte[] encode() {
if (cached == null)
cached = encodable.encode();
return cached;
}
public interface EncodeOnly {
byte [] encode();
}
}

View File

@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com
*
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
* Our goal is to create an emulator which will provide a server for players to
* continue playing a game similar to the one they used to play. We are basing
* it on the final publish of the game prior to end-game events.
*
* This file is part of Holocore.
*
* --------------------------------------------------------------------------------
*
* Holocore is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Holocore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package com.projectswg.common.encoding;
import java.nio.ByteBuffer;
public interface Encodable {
byte [] encode();
void decode(ByteBuffer data);
}

View File

@@ -0,0 +1,127 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.encoding;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import com.projectswg.common.debug.Log;
public class Encoder {
public static byte[] encode(Object object) {
return encode(object, StringType.UNSPECIFIED);
}
public static byte[] encode(Object object, StringType strType) {
if (strType != StringType.UNSPECIFIED && object instanceof String) {
switch (strType) {
case ASCII:
return encodeAscii((String) object);
case UNICODE:
return encodeUnicode((String) object);
default:
break;
}
} else {
if (object instanceof Encodable) {
return encodeObject((Encodable) object);
} else if (object instanceof Integer) {
return encodeInteger((Integer) object);
} else if (object instanceof Long) {
return encodeLong((Long) object);
} else if (object instanceof Short) {
return encodeShort((Short) object);
} else if (object instanceof Byte) {
return encodeByte((Byte) object);
} else if (object instanceof Boolean) {
return encodeBoolean((boolean) object);
} else if (object instanceof Float || object instanceof Double) {
return encodeFloat(object);
} else if (object instanceof String) {
throw new UnsupportedOperationException("You must specify a String type!");
} else {
Log.e("Do not know how to encode instance type " + object.getClass().getName());
}
}
return null;
}
public static byte[] encodeObject(Encodable encodable) {
return encodable.encode();
}
private static byte[] encodeFloat(Object object) {
ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
buffer.putFloat((object instanceof Float ? (Float) object : ((Double) object).floatValue()));
return buffer.array();
}
private static byte[] encodeByte(Byte object) {
return new byte[] {(object.byteValue())};
}
private static byte[] encodeBoolean(boolean object) {
return encodeByte((byte) (object ? 1 : 0));
}
public static byte[] encodeShort(Short object) {
ByteBuffer buffer = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort(object);
return buffer.array();
}
public static byte[] encodeInteger(int integer) {
ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(integer);
return buffer.array();
}
public static byte[] encodeLong(long l) {
ByteBuffer buffer = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
buffer.putLong(l);
return buffer.array();
}
public static byte[] encodeAscii(String string) {
ByteBuffer buffer = ByteBuffer.allocate(2 + string.length()).order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort((short) string.length());
buffer.put(string.getBytes(Charset.forName("UTF-8")));
return buffer.array();
}
public static byte[] encodeUnicode(String string) {
ByteBuffer buffer = ByteBuffer.allocate(4 + (string.length() * 2)).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(string.length());
buffer.put(string.getBytes(Charset.forName("UTF-16LE")));
return buffer.array();
}
}

View File

@@ -0,0 +1,7 @@
package com.projectswg.common.encoding;
public enum StringType {
UNSPECIFIED,
ASCII,
UNICODE
}

View File

@@ -32,6 +32,10 @@ import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import com.projectswg.common.debug.Log;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.encoding.StringType;
public class NetBuffer {
@@ -148,6 +152,10 @@ public class NetBuffer {
data.put(b);
}
public void addEncodable(Encodable e) {
data.put(e.encode());
}
public boolean getBoolean() {
return getByte() == 1 ? true : false;
}
@@ -172,6 +180,14 @@ public class NetBuffer {
return new String(str, UNICODE);
}
public String getString(StringType type) {
if (type == StringType.ASCII)
return getAscii();
if (type == StringType.UNICODE)
return getUnicode();
throw new IllegalArgumentException("Unknown StringType: " + type);
}
public byte getByte() {
return data.get();
}
@@ -216,6 +232,42 @@ public class NetBuffer {
return bData;
}
public <T> Object getGeneric(Class<T> type) {
if (Encodable.class.isAssignableFrom(type)) {
T instance = null;
try {
instance = type.newInstance();
((Encodable) instance).decode(data);
} catch (InstantiationException | IllegalAccessException e) {
Log.e(e);
}
return instance;
} else if (Integer.class.isAssignableFrom(type) || Integer.TYPE.isAssignableFrom(type))
return getInt();
else if (Long.class.isAssignableFrom(type) || Long.TYPE.isAssignableFrom(type))
return getLong();
else if (Float.class.isAssignableFrom(type) || Float.TYPE.isAssignableFrom(type))
return getFloat();
else if (StringType.ASCII.getClass().isAssignableFrom(type))
return getAscii();
else if (StringType.UNICODE.getClass().isAssignableFrom(type))
return getAscii();
return null;
}
public <T extends Encodable> T getEncodable(Class<T> type) {
T instance = null;
try {
instance = type.newInstance();
instance.decode(data);
} catch (InstantiationException | IllegalAccessException e) {
Log.e(e);
}
return instance;
}
public byte [] array() {
return data.array();
}

View File

@@ -0,0 +1,111 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.persistable;
import java.io.IOException;
import java.io.InputStream;
import com.projectswg.common.network.NetBufferStream;
public class InputPersistenceStream extends InputStream {
private final InputStream is;
public InputPersistenceStream(InputStream is) {
this.is = is;
}
public int read() {
throw new UnsupportedOperationException("Unable to read raw data");
}
public int read(byte[] b) {
throw new UnsupportedOperationException("Unable to read raw data");
}
public int read(byte[] b, int off, int len) {
throw new UnsupportedOperationException("Unable to read raw data");
}
public <T extends Persistable> T read(PersistableCreator<T> creator) throws IOException {
int size = readInt();
try (NetBufferStream stream = new NetBufferStream(size)) {
byte [] buffer = new byte[Math.min(size, 2048)];
int pos = 0;
while (pos < size) {
int n = is.read(buffer, 0, Math.min(size-pos, buffer.length));
if (n == -1)
break;
stream.write(buffer, 0, n);
pos += n;
}
stream.position(0);
return creator.create(stream);
}
}
public long skip(long n) throws IOException {
return is.skip(n);
}
public int available() throws IOException {
return is.available();
}
public void close() throws IOException {
is.close();
}
public void mark(int readlimit) {
is.mark(readlimit);
}
public void reset() throws IOException {
is.reset();
}
public boolean markSupported() {
return is.markSupported();
}
private int readInt() throws IOException {
int ret = 0;
int b;
for (int i = 0; i < 4; i++) {
b = is.read();
if (b != -1)
ret |= b << (i * 8);
}
return ret;
}
public static interface PersistableCreator<T extends Persistable> {
T create(NetBufferStream stream);
}
}

View File

@@ -0,0 +1,98 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.persistable;
import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import com.projectswg.common.network.NetBufferStream;
public class OutputPersistenceStream extends OutputStream implements Closeable {
private final OutputStream os;
public OutputPersistenceStream(OutputStream os) {
this.os = os;
}
@Override
public void write(int b) {
throw new UnsupportedOperationException("Unable to write raw data");
}
@Override
public void write(byte[] b) {
throw new UnsupportedOperationException("Unable to write raw data");
}
@Override
public void write(byte[] b, int off, int len) {
throw new UnsupportedOperationException("Unable to write raw data");
}
public void write(Persistable p) throws IOException {
NetBufferStream buffer = new NetBufferStream();
p.save(buffer);
writeInt(buffer.size());
os.write(buffer.array(), 0, buffer.size());
flush();
buffer.close();
}
public <T extends Persistable> void write(T obj, PersistableSaver<T> saver) throws IOException {
NetBufferStream buffer = new NetBufferStream();
saver.save(obj, buffer);
writeInt(buffer.size());
os.write(buffer.array(), 0, buffer.size());
flush();
buffer.close();
}
@Override
public void flush() throws IOException {
os.flush();
}
@Override
public void close() throws IOException {
os.close();
}
private void writeInt(int i) throws IOException {
os.write(i >>> 0);
os.write(i >>> 8);
os.write(i >>> 16);
os.write(i >>> 24);
}
public static interface PersistableSaver<T extends Persistable> {
void save(T obj, NetBufferStream stream);
}
}

View File

@@ -0,0 +1,35 @@
/************************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.persistable;
import com.projectswg.common.network.NetBufferStream;
public interface Persistable {
void save(NetBufferStream stream);
void read(NetBufferStream stream);
}

View File

@@ -0,0 +1,96 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.common.utilities;
import java.nio.ByteBuffer;
public class ByteUtilities {
private static final ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE);
private static final char [] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
public static String getHexString(byte [] bytes) {
char [] data = new char[bytes.length*2+(bytes.length>0?bytes.length-1:0)];
byte b;
for (int i = 0; i < bytes.length; i++) {
b = bytes[i];
data[i*3+0] = HEX[(b&0xFF) >>> 4];
data[i*3+1] = HEX[b & 0x0F];
if (i*3+2 < data.length)
data[i*3+2] = ' ';
}
return new String(data);
}
public static byte [] getHexStringArray(String string) {
int len = string.length();
if (len % 2 != 0)
return new byte[0];
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(string.charAt(i), 16) << 4) + Character.digit(string.charAt(i+1), 16));
}
return data;
}
public static byte [] longToBytes(long l) {
byte [] b = new byte[Long.SIZE];
synchronized (buffer) {
buffer.putLong(0, l);
System.arraycopy(buffer.array(), 0, b, 0, Long.SIZE);
}
return b;
}
public static long bytesToLong(byte [] a) {
return bytesToLong(a, 0);
}
public static long bytesToLong(byte [] a, int offset) {
long l = 0;
synchronized (buffer) {
for (int i = 0; i < Long.SIZE; i++) {
if (i < a.length)
buffer.put(i, a[i+offset]);
else
buffer.put(i, (byte)0);
}
l = buffer.getLong(0);
}
return l;
}
public static String nextString(ByteBuffer data) {
byte [] bData = data.array();
StringBuilder str = new StringBuilder("");
for (int i = data.position(); i < bData.length && bData[i] >= ' ' && bData[i] <= '~'; i++)
str.append((char) data.get());
return str.toString();
}
}