hytopia 0.1.15 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. package/bin/scripts.js +28 -9
  2. package/docs/server.hytopia.md +1 -1
  3. package/docs/server.hytopia.port.md +2 -2
  4. package/docs/server.hytopia.supported_input_keys.md +1 -1
  5. package/docs/server.md +1 -1
  6. package/docs/server.port.md +2 -2
  7. package/docs/server.supported_input_keys.md +1 -1
  8. package/examples/character-controller/MyCharacterController.ts +230 -0
  9. package/examples/character-controller/README.md +15 -0
  10. package/examples/character-controller/assets/audio/sfx/damage.wav +0 -0
  11. package/examples/character-controller/assets/audio/sfx/step.wav +0 -0
  12. package/examples/character-controller/assets/certs/README.md +11 -0
  13. package/examples/character-controller/assets/certs/localhost.crt +20 -0
  14. package/examples/character-controller/assets/certs/localhost.key +27 -0
  15. package/examples/character-controller/assets/cubemaps/skybox/+x.png +0 -0
  16. package/examples/character-controller/assets/cubemaps/skybox/+y.png +0 -0
  17. package/examples/character-controller/assets/cubemaps/skybox/+z.png +0 -0
  18. package/examples/character-controller/assets/cubemaps/skybox/-x.png +0 -0
  19. package/examples/character-controller/assets/cubemaps/skybox/-y.png +0 -0
  20. package/examples/character-controller/assets/cubemaps/skybox/-z.png +0 -0
  21. package/examples/character-controller/assets/map.json +2623 -0
  22. package/examples/character-controller/assets/models/player.gltf +1 -0
  23. package/examples/character-controller/assets/textures/bricks.png +0 -0
  24. package/examples/character-controller/assets/textures/clay.png +0 -0
  25. package/examples/character-controller/assets/textures/diamond_ore.png +0 -0
  26. package/examples/character-controller/assets/textures/dirt.png +0 -0
  27. package/examples/character-controller/assets/textures/dragons_stone.png +0 -0
  28. package/examples/character-controller/assets/textures/glass.png +0 -0
  29. package/examples/character-controller/assets/textures/grass/+x.png +0 -0
  30. package/examples/character-controller/assets/textures/grass/+y.png +0 -0
  31. package/examples/character-controller/assets/textures/grass/+z.png +0 -0
  32. package/examples/character-controller/assets/textures/grass/-x.png +0 -0
  33. package/examples/character-controller/assets/textures/grass/-y.png +0 -0
  34. package/examples/character-controller/assets/textures/grass/-z.png +0 -0
  35. package/examples/character-controller/assets/textures/grass.png +0 -0
  36. package/examples/character-controller/assets/textures/gravel.png +0 -0
  37. package/examples/character-controller/assets/textures/ice.png +0 -0
  38. package/examples/character-controller/assets/textures/infected_shadowrock.png +0 -0
  39. package/examples/character-controller/assets/textures/log_side.png +0 -0
  40. package/examples/character-controller/assets/textures/log_top.png +0 -0
  41. package/examples/character-controller/assets/textures/mossy_coblestone.png +0 -0
  42. package/examples/character-controller/assets/textures/nuit.png +0 -0
  43. package/examples/character-controller/assets/textures/oak_leaves.png +0 -0
  44. package/examples/character-controller/assets/textures/oak_planks.png +0 -0
  45. package/examples/character-controller/assets/textures/sand.png +0 -0
  46. package/examples/character-controller/assets/textures/shadowrock.png +0 -0
  47. package/examples/character-controller/assets/textures/stone.png +0 -0
  48. package/examples/character-controller/assets/textures/stone_bricks.png +0 -0
  49. package/examples/character-controller/assets/textures/void_sand.png +0 -0
  50. package/examples/character-controller/assets/textures/water_still.png +0 -0
  51. package/examples/character-controller/bun.lockb +0 -0
  52. package/examples/character-controller/index.ts +43 -0
  53. package/examples/character-controller/package.json +14 -0
  54. package/examples/character-controller/tsconfig.json +27 -0
  55. package/examples/entity-spawn/README.md +15 -0
  56. package/examples/entity-spawn/assets/certs/README.md +11 -0
  57. package/examples/entity-spawn/assets/certs/localhost.crt +20 -0
  58. package/examples/entity-spawn/assets/certs/localhost.key +27 -0
  59. package/examples/entity-spawn/assets/cubemaps/skybox/+x.png +0 -0
  60. package/examples/entity-spawn/assets/cubemaps/skybox/+y.png +0 -0
  61. package/examples/entity-spawn/assets/cubemaps/skybox/+z.png +0 -0
  62. package/examples/entity-spawn/assets/cubemaps/skybox/-x.png +0 -0
  63. package/examples/entity-spawn/assets/cubemaps/skybox/-y.png +0 -0
  64. package/examples/entity-spawn/assets/cubemaps/skybox/-z.png +0 -0
  65. package/examples/entity-spawn/assets/map.json +2623 -0
  66. package/examples/entity-spawn/assets/models/player.gltf +1 -0
  67. package/examples/entity-spawn/assets/models/spider.gltf +1 -0
  68. package/examples/entity-spawn/assets/textures/bricks.png +0 -0
  69. package/examples/entity-spawn/assets/textures/clay.png +0 -0
  70. package/examples/entity-spawn/assets/textures/diamond_ore.png +0 -0
  71. package/examples/entity-spawn/assets/textures/dirt.png +0 -0
  72. package/examples/entity-spawn/assets/textures/dragons_stone.png +0 -0
  73. package/examples/entity-spawn/assets/textures/glass.png +0 -0
  74. package/examples/entity-spawn/assets/textures/grass/+x.png +0 -0
  75. package/examples/entity-spawn/assets/textures/grass/+y.png +0 -0
  76. package/examples/entity-spawn/assets/textures/grass/+z.png +0 -0
  77. package/examples/entity-spawn/assets/textures/grass/-x.png +0 -0
  78. package/examples/entity-spawn/assets/textures/grass/-y.png +0 -0
  79. package/examples/entity-spawn/assets/textures/grass/-z.png +0 -0
  80. package/examples/entity-spawn/assets/textures/grass.png +0 -0
  81. package/examples/entity-spawn/assets/textures/gravel.png +0 -0
  82. package/examples/entity-spawn/assets/textures/ice.png +0 -0
  83. package/examples/entity-spawn/assets/textures/infected_shadowrock.png +0 -0
  84. package/examples/entity-spawn/assets/textures/log_side.png +0 -0
  85. package/examples/entity-spawn/assets/textures/log_top.png +0 -0
  86. package/examples/entity-spawn/assets/textures/mossy_coblestone.png +0 -0
  87. package/examples/entity-spawn/assets/textures/nuit.png +0 -0
  88. package/examples/entity-spawn/assets/textures/oak_leaves.png +0 -0
  89. package/examples/entity-spawn/assets/textures/oak_planks.png +0 -0
  90. package/examples/entity-spawn/assets/textures/sand.png +0 -0
  91. package/examples/entity-spawn/assets/textures/shadowrock.png +0 -0
  92. package/examples/entity-spawn/assets/textures/stone.png +0 -0
  93. package/examples/entity-spawn/assets/textures/stone_bricks.png +0 -0
  94. package/examples/entity-spawn/assets/textures/void_sand.png +0 -0
  95. package/examples/entity-spawn/assets/textures/water_still.png +0 -0
  96. package/examples/entity-spawn/bun.lockb +0 -0
  97. package/examples/entity-spawn/index.ts +93 -0
  98. package/examples/entity-spawn/package.json +14 -0
  99. package/examples/entity-spawn/tsconfig.json +27 -0
  100. package/examples/payload-game/README.md +15 -0
  101. package/examples/payload-game/assets/certs/README.md +11 -0
  102. package/examples/payload-game/assets/certs/localhost.crt +20 -0
  103. package/examples/payload-game/assets/certs/localhost.key +27 -0
  104. package/examples/payload-game/bun.lockb +0 -0
  105. package/examples/payload-game/index.ts +12 -3
  106. package/examples/payload-game/package.json +14 -0
  107. package/examples/payload-game/tsconfig.json +27 -0
  108. package/package.json +1 -1
  109. package/server.api.json +6 -6
  110. package/server.d.ts +10 -3
  111. package/server.js +1 -1
  112. package/tsconfig.json +1 -4
package/bin/scripts.js CHANGED
@@ -6,6 +6,14 @@ const path = require('path');
6
6
 
7
7
  (async () => {
8
8
  const command = process.argv[2];
9
+ const flags = {};
10
+ for (let i = 3; i < process.argv.length; i += 2) {
11
+ if (i % 2 === 1) { // Odd indices are flags
12
+ const flag = process.argv[i].replace('--', '');
13
+ const value = process.argv[i + 1];
14
+ flags[flag] = value;
15
+ }
16
+ }
9
17
 
10
18
  /**
11
19
  * Init command
@@ -17,16 +25,27 @@ const path = require('path');
17
25
  * `bunx hytopia init my-project-name`
18
26
  */
19
27
  if (command === 'init') {
20
- const srcDir = path.join(__dirname, '..', 'boilerplate');
21
28
  const destDir = process.cwd();
22
-
23
- // Initialize project
24
- execSync('bun init --yes');
25
- execSync('bun add hytopia');
26
-
27
- // Copy boilerplate
28
- console.log(`🖨️ Copying boilerplate to ${destDir}`);
29
- fs.cpSync(srcDir, destDir, { recursive: true });
29
+
30
+ if (flags.template) {
31
+ console.log(`🔧 Initializing project with examples template ${flags.template}`);
32
+
33
+ const templateDir = path.join(__dirname, '..', 'examples', flags.template);
34
+
35
+ if (!fs.existsSync(templateDir)) {
36
+ console.error(`Examples template ${flags.template} does not exist in the examples directory, could not initialize project!`);
37
+ return;
38
+ }
39
+
40
+ fs.cpSync(templateDir, destDir, { recursive: true });
41
+ execSync('bun install');
42
+ } else {
43
+ console.log('🔧 Initializing project');
44
+ execSync('bun init --yes');
45
+ execSync('bun add hytopia');
46
+
47
+ fs.cpSync(srcDir, destDir, { recursive: true });
48
+ }
30
49
 
31
50
  // Done, lfg!
32
51
  console.log('🚀 Hytopia project initialized successfully!');
@@ -741,7 +741,7 @@ The default rigid body options when EntityOptions.rigidBodyOptions is not provid
741
741
 
742
742
  </td><td>
743
743
 
744
- The port the server will listen on. You can override this in your .env by setting PORT.
744
+ The port the server will run on. You can override this in your .env by setting PORT. When deployed in production to HYTOPIA servers, any .env value will be ignored and 8080 will be used.
745
745
 
746
746
 
747
747
  </td></tr>
@@ -4,10 +4,10 @@
4
4
 
5
5
  ## HYTOPIA.PORT variable
6
6
 
7
- The port the server will listen on. You can override this in your .env by setting PORT.
7
+ The port the server will run on. You can override this in your .env by setting PORT. When deployed in production to HYTOPIA servers, any .env value will be ignored and 8080 will be used.
8
8
 
9
9
  **Signature:**
10
10
 
11
11
  ```typescript
12
- PORT: string | number
12
+ PORT: string | 8080
13
13
  ```
@@ -9,5 +9,5 @@ The input keys included in the PlayerInputState.
9
9
  **Signature:**
10
10
 
11
11
  ```typescript
12
- SUPPORTED_INPUT_KEYS: string[]
12
+ SUPPORTED_INPUT_KEYS: readonly ["w", "a", "s", "d", "sp", "sh", "tb", "ml", "mr", "q", "e", "r", "f", "z", "x", "c", "v", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
13
13
  ```
package/docs/server.md CHANGED
@@ -750,7 +750,7 @@ The default rigid body options when EntityOptions.rigidBodyOptions is not provid
750
750
 
751
751
  </td><td>
752
752
 
753
- The port the server will listen on. You can override this in your .env by setting PORT.
753
+ The port the server will run on. You can override this in your .env by setting PORT. When deployed in production to HYTOPIA servers, any .env value will be ignored and 8080 will be used.
754
754
 
755
755
 
756
756
  </td></tr>
@@ -4,10 +4,10 @@
4
4
 
5
5
  ## PORT variable
6
6
 
7
- The port the server will listen on. You can override this in your .env by setting PORT.
7
+ The port the server will run on. You can override this in your .env by setting PORT. When deployed in production to HYTOPIA servers, any .env value will be ignored and 8080 will be used.
8
8
 
9
9
  **Signature:**
10
10
 
11
11
  ```typescript
12
- PORT: string | number
12
+ PORT: string | 8080
13
13
  ```
@@ -9,5 +9,5 @@ The input keys included in the PlayerInputState.
9
9
  **Signature:**
10
10
 
11
11
  ```typescript
12
- SUPPORTED_INPUT_KEYS: string[]
12
+ SUPPORTED_INPUT_KEYS: readonly ["w", "a", "s", "d", "sp", "sh", "tb", "ml", "mr", "q", "e", "r", "f", "z", "x", "c", "v", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
13
13
  ```
@@ -0,0 +1,230 @@
1
+ import {
2
+ Audio,
3
+ BaseCharacterController,
4
+ CollisionGroup,
5
+ Collider,
6
+ Entity,
7
+ ColliderShape,
8
+ BlockType,
9
+ } from 'hytopia';
10
+
11
+ import type {
12
+ PlayerInputState,
13
+ PlayerOrientationState,
14
+ Vector3,
15
+ } from 'hytopia';
16
+
17
+ export default class MyCharacterController extends BaseCharacterController {
18
+ public jumpVelocity: number = 10;
19
+ public runVelocity: number = 8;
20
+ public walkVelocity: number = 4;
21
+
22
+ private _stepAudio: Audio;
23
+ private _groundContactCount: number = 0;
24
+ private _platform: Entity | undefined;
25
+
26
+ public constructor(entity: Entity) {
27
+ super(entity);
28
+
29
+ // Setup any audio or dependencies in the constructor.
30
+ this._stepAudio = new Audio({
31
+ uri: 'audio/sfx/step.wav',
32
+ loop: true,
33
+ volume: 0.1,
34
+ attachedToEntity: this.entity,
35
+ });
36
+
37
+ this.entity.lockAllRotations(); // prevent physics from applying rotation to the entity.
38
+ }
39
+
40
+ /** Whether the entity is grounded. */
41
+ public get isGrounded(): boolean { return this._groundContactCount > 0; }
42
+
43
+ /** Whether the entity is on a platform, a platform is any entity with a kinematic rigid body. */
44
+ public get isOnPlatform(): boolean { return !!this._platform; }
45
+
46
+ /** The platform the entity is on, if any. */
47
+ public get platform(): Entity | undefined { return this._platform; }
48
+
49
+ /**
50
+ * Create the sensor colliders for the character controller.
51
+ */
52
+ public createSensorColliders(): Collider[] {
53
+ if (!this.entity.isSpawned) {
54
+ throw new Error('CharacterController.createSensorColliders(): Entity is not spawned!');
55
+ }
56
+
57
+ const sensorColliders: Collider[] = [];
58
+
59
+ /**
60
+ * Our ground sensor detects when we're on the ground.
61
+ * It assumes a cylinder shape and is positioned manually
62
+ * relative to the default entity rigid body as defined
63
+ * by the DEFAULT_ENTITY_RIGID_BODY_OPTIONS constant of
64
+ * the hytopia package.
65
+ */
66
+ sensorColliders.push(new Collider({
67
+ shape: ColliderShape.CYLINDER,
68
+ radius: 0.30,
69
+ halfHeight: 0.125,
70
+ collisionGroups: {
71
+ belongsTo: [ CollisionGroup.ENTITY_SENSOR ],
72
+ collidesWith: [ CollisionGroup.BLOCK, CollisionGroup.ENTITY ],
73
+ },
74
+ isSensor: true,
75
+ relativeTranslation: { x: 0, y: -0.75, z: 0 },
76
+ tag: 'groundSensor',
77
+ onCollision: (_other: BlockType | Entity, started: boolean) => {
78
+ // Ground contact
79
+ this._groundContactCount += started ? 1 : -1;
80
+
81
+ if (!this._groundContactCount) { // Trigger animations
82
+ this.entity.startModelOneshotAnimations([ 'jump_loop' ]);
83
+ } else {
84
+ this.entity.stopModelAnimations([ 'jump_loop' ]);
85
+ }
86
+
87
+ // Platform contact
88
+ if (!(_other instanceof Entity) || !_other.isKinematic) return;
89
+
90
+ if (started) {
91
+ this._platform = _other;
92
+ } else if (_other === this._platform && !started) {
93
+ this._platform = undefined;
94
+ }
95
+ },
96
+ }));
97
+
98
+ return sensorColliders;
99
+ }
100
+
101
+ /**
102
+ * Handles movement of the entity based on player's input
103
+ * each tick. tickPlayerMovement is called internally if the entity
104
+ * is of the PlayerEntity class.
105
+ */
106
+ public tickPlayerMovement(inputState: PlayerInputState, orientationState: PlayerOrientationState, deltaTimeMs: number) {
107
+ if (!this.entity.isSpawned || !this.entity.world) return; // type guard.
108
+
109
+ super.tickPlayerMovement(inputState, orientationState, deltaTimeMs);
110
+
111
+ const { w, a, s, d, sp, sh, ml, mr } = inputState; // See PlayerInputState type for all possible inputs.
112
+ const { yaw } = orientationState; // Camera/perspectie orientation of player.
113
+ const currentVelocity = this.entity.getLinearVelocity();
114
+ const targetVelocities = { x: 0, y: 0, z: 0 };
115
+ const isRunning = sh;
116
+
117
+ // Handle movement animations if relevant.
118
+ if (w || a || s || d) {
119
+ if (isRunning) {
120
+ // We stop irrelevant animations to prevent blending issues.
121
+ this.entity.stopModelAnimations(Array.from(this.entity.modelLoopedAnimations).filter(v => v !== 'run'));
122
+ // If run is already playing, internally startModelLoopedAnimations will do nothing.
123
+ this.entity.startModelLoopedAnimations([ 'run' ]);
124
+ // Manually set a playback rate of our step audio to audibly sync to our walk speed.
125
+ this._stepAudio.setPlaybackRate(0.83);
126
+ } else {
127
+ this.entity.stopModelAnimations(Array.from(this.entity.modelLoopedAnimations).filter(v => v !== 'walk'));
128
+ this.entity.startModelLoopedAnimations([ 'walk' ]);
129
+ this._stepAudio.setPlaybackRate(0.5);
130
+ }
131
+
132
+ this._stepAudio.play(this.entity.world, !this._stepAudio.isPlaying);
133
+ } else {
134
+ this._stepAudio.pause();
135
+ this.entity.stopModelAnimations(Array.from(this.entity.modelLoopedAnimations).filter(v => v !== 'idle'));
136
+ this.entity.startModelLoopedAnimations([ 'idle' ]);
137
+ }
138
+
139
+ // Play a simple interact animation on left mouse click then clear the input.
140
+ if (ml) {
141
+ this.entity.startModelOneshotAnimations([ 'simple_interact' ]);
142
+ inputState['ml'] = false;
143
+ }
144
+
145
+ // Rocket the player up on mouse right click.
146
+ if (mr) {
147
+ targetVelocities.y = 20;
148
+ inputState['mr'] = false;
149
+ }
150
+
151
+ // Calculate target horizontal velocities (run/walk)
152
+ const velocity = isRunning ? this.runVelocity : this.walkVelocity;
153
+
154
+ if (w) {
155
+ targetVelocities.x -= velocity * Math.sin(yaw);
156
+ targetVelocities.z -= velocity * Math.cos(yaw);
157
+ }
158
+
159
+ if (s) {
160
+ targetVelocities.x += velocity * Math.sin(yaw);
161
+ targetVelocities.z += velocity * Math.cos(yaw);
162
+ }
163
+
164
+ if (a) {
165
+ targetVelocities.x -= velocity * Math.cos(yaw);
166
+ targetVelocities.z += velocity * Math.sin(yaw);
167
+ }
168
+
169
+ if (d) {
170
+ targetVelocities.x += velocity * Math.cos(yaw);
171
+ targetVelocities.z -= velocity * Math.sin(yaw);
172
+ }
173
+
174
+ // Normalize for diagonals
175
+ const length = Math.sqrt(targetVelocities.x * targetVelocities.x + targetVelocities.z * targetVelocities.z);
176
+ if (length > velocity) {
177
+ const factor = velocity / length;
178
+ targetVelocities.x *= factor;
179
+ targetVelocities.z *= factor;
180
+ }
181
+
182
+ // Calculate target vertical velocity (jump)
183
+ if (sp) {
184
+ if (this.isGrounded && currentVelocity.y <= 3) {
185
+ targetVelocities.y = this.jumpVelocity;
186
+ }
187
+ }
188
+
189
+ // Apply impulse relative to target velocities, taking platform velocity into account
190
+ const platformVelocity = this._platform ? this._platform.getLinearVelocity() : { x: 0, y: 0, z: 0 };
191
+ const deltaVelocities = {
192
+ x: targetVelocities.x - currentVelocity.x + platformVelocity.x,
193
+ y: targetVelocities.y + platformVelocity.y,
194
+ z: targetVelocities.z - currentVelocity.z + platformVelocity.z,
195
+ };
196
+
197
+ const hasExternalVelocity =
198
+ Math.abs(currentVelocity.x) > this.runVelocity ||
199
+ Math.abs(currentVelocity.y) > this.jumpVelocity ||
200
+ Math.abs(currentVelocity.z) > this.runVelocity;
201
+
202
+ if (!hasExternalVelocity) { // allow external velocities like impulses to resolve, otherwise our deltas will cancel them out.
203
+ if (Object.values(deltaVelocities).some(v => v !== 0)) {
204
+ const mass = this.entity.getMass();
205
+
206
+ this.entity.applyImpulse({ // multiply by mass for the impulse to result in applying the correct target velocity
207
+ x: deltaVelocities.x * mass,
208
+ y: deltaVelocities.y * mass,
209
+ z: deltaVelocities.z * mass,
210
+ });
211
+ }
212
+ }
213
+
214
+ // Apply rotation relative to camera orientation.
215
+ if (yaw !== undefined) {
216
+ const halfYaw = yaw / 2;
217
+
218
+ this.entity.setRotation({
219
+ x: 0,
220
+ y: Math.fround(Math.sin(halfYaw)),
221
+ z: 0,
222
+ w: Math.fround(Math.cos(halfYaw)),
223
+ });
224
+ }
225
+ }
226
+
227
+ public tickPathfindingMovement(_destination: Vector3, _deltaTimeMs: number) {
228
+ console.log('Non-player pathfinding not implemented!');
229
+ }
230
+ }
@@ -0,0 +1,15 @@
1
+ # character-controller
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.1.26. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
@@ -0,0 +1,11 @@
1
+ For local development self-signed certs are stored here.
2
+ The server when GameServer.instance.webServer.enableLocalSSL();
3
+ is used, will look for assets/certs/localhost.key and
4
+ assets/certs/localhost.cert and use those for SSL.
5
+
6
+ We use these self-signed certs to allow https://localhost
7
+ & wss://localhost support. Without this, play.hytopia.com
8
+ requires a bunch of funky browser flag workarounds in
9
+ order to connect to your local server. This is only used
10
+ for local development and will be ignored when your game
11
+ is deployed to HYTOPIA servers.
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDRjCCAi6gAwIBAgIFOTEzNTIwDQYJKoZIhvcNAQELBQAwWDEQMA4GA1UEAxMH
3
+ SFlUT1BJQTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
4
+ BAcTB1NlYXR0bGUxEDAOBgNVBAoTB0hZVE9QSUEwHhcNMjQxMTEzMjIyMjEwWhcN
5
+ MzQxMTExMjIyMjEwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3
6
+ DQEBAQUAA4IBDwAwggEKAoIBAQCo2i9L13+4KxvR9dxBeE3Xrj5WtoGFBwbUZkeV
7
+ 3B8n+ehJ2LWD13sGvCuHvSDovbSOxLxqbESQzWBRVrmfJMR1qe+o7kd/SMaLHosC
8
+ 2BWASn1oV9rGLktvd2Xs6xRf75cejzrr/OrNoTpICp3j1Z0Kd+73TuYyVFPfCbqH
9
+ N6mwS+yCmG2/w3sXwbOGymNuYpaPoD8XVcIhO7GPZsCVqqSKP2xsGF+oP5+Isma+
10
+ y3usNUnFnVW5ckk6SWWdxP9kuOW2xXoFFwj43STaE4OvXbTPCG7jowUpDH1aMvFA
11
+ ceXUfuaE7H8QfZqoUNu8jCb8LiqTL+uL5kHbl2kQ7sQCN9gjAgMBAAGjWzBZMAwG
12
+ A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB
13
+ BggrBgEFBQcDAjAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN
14
+ AQELBQADggEBAHSINJsVuu11kmzx7/2yEiDSIQVzdzk/+hnx0iQt6rDy9ZNVdI8w
15
+ JOUYaPjxDFfZ5gaPqrlb0n248lBMdGrp6xmhbgXL8eWkXRDcR6kuYBQrQmFitg7G
16
+ KFFWnzCuQMLn5Mn6VA+sBf9n2LVaOQCci9jU0awRpaQTUNf894USjILo+PvbcUGU
17
+ XlMtqc1abkN4NehDdaXsxMwyPgUCPkN5X80s8hxx5NgzwtwDtoTYj/PBRBXBddA+
18
+ oN1rwkugWiTpIPU0wKb0ufLsq96I24UDQWd2jJGbD2W23Z0lwVz/Bq6uc4aOJn68
19
+ JbejJgFyF3/m6oFDxgqMnuV5q5olVZHAWL8=
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEAqNovS9d/uCsb0fXcQXhN164+VraBhQcG1GZHldwfJ/noSdi1
3
+ g9d7Brwrh70g6L20jsS8amxEkM1gUVa5nyTEdanvqO5Hf0jGix6LAtgVgEp9aFfa
4
+ xi5Lb3dl7OsUX++XHo866/zqzaE6SAqd49WdCnfu907mMlRT3wm6hzepsEvsgpht
5
+ v8N7F8GzhspjbmKWj6A/F1XCITuxj2bAlaqkij9sbBhfqD+fiLJmvst7rDVJxZ1V
6
+ uXJJOkllncT/ZLjltsV6BRcI+N0k2hODr120zwhu46MFKQx9WjLxQHHl1H7mhOx/
7
+ EH2aqFDbvIwm/C4qky/ri+ZB25dpEO7EAjfYIwIDAQABAoIBAA6dvGRbRiICEUlu
8
+ d99u84YM/jZxW+rQ/eVa6S1uvX+vYU0rJiNAftTJaxc35uZerYeCPjEUKCdEr+a6
9
+ lBzTiPIKgMVlwuiguxcF0NCxNcNCL3Ld0AFBtqPyeO82NjBLxBAQI/CTlxuvriTY
10
+ TmyPbCWg1h2wRbrrk8sFw5C638Rz2evbBfsUcTICr6QQa51YXgxawtew3Xy3aR3G
11
+ PPuS7zlvjJYDApQs3+nakEj3DnM2nz5oJNS2YEsMKQRhmNrhen6Ose5G0jf6F6up
12
+ 8HVpN3XW01D7qVT1Og6Y5dE2EM/l3isKZWXif6CcFKoOy87z8HRMIoZJS62WtKtu
13
+ liBmYxkCgYEA4VDPtFAGnChCTGLVwo7MKmH6/KU5Qj2fuufGNw8jcW3H0Ea52OFC
14
+ qOGA9pRJVXCap7Wa7XCJXENLYWpSfB7H7GnhFLwHw7jAVB52DLDCdUnRv5fP3o8K
15
+ xEseMJQaJm95eFVfTETcnjDixWtIzNbXULQbGjF3AY74aFjc1fhc/yUCgYEAv9jj
16
+ Zrc+UzR0oi00Ip8O5C5Uvu2W35M+j2XoV/xPkX+Hcr12U40Gnc/rnzVp2lGTwNZS
17
+ ImQcjLEd31qLOy90F9lcaKvOfgcx0JvGEp5SdzQQaS3RJqn0xWLh1O4NMsiVbLNi
18
+ Zi5qFv7pW/DO174xSa7cMVE8qp8YHAOZdpcqm6cCgYB9FL2ZnetteTQE78E3NsrE
19
+ pIwPATIeQdOQkOaK3k6Qw57vUrQNYE//LODJAl0Ln21buQd+1MCMhZctRzbvTK8z
20
+ 4TtgpVmyH7g1eouSU/Y/4nEcaYyuQr55ZjImSbGSsMPAN7SlxHytHPpnGj3Z6VKy
21
+ rKl3CwrDxLjGRL6j0jLeOQKBgBiu3xMoIGy0Iw16o2qQ7GmPTHgEOZUqbLImem5X
22
+ mCUwM00f80lsq51CUx540NW2CTyWVpr2JnYzk5RZIfDLejRXUvxknny4kEA2ypU6
23
+ qYGMwU/HBVHkLAn5XvT2a9xM0mzZ558d+ahbw8qAgRxg7BZ+2PW/bf7F2WRBUk1f
24
+ xauhAoGBALEspoxQozwohGQnP7EMF0/0JoKNpdNv0b0qCVvNiMo0+N297lI2mFQp
25
+ 6xYlW/1l9afLokklF/J2IsyBrTCZoY7SaEk/lMMrQSyra+y0z71ogZ8A4ny9fxsj
26
+ 0dDYJZGllL+3E/MQfd7k+KnOM/+A+cPoAnci76+L3vdkUb2P8SJk
27
+ -----END RSA PRIVATE KEY-----