action-engine-js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +348 -0
- package/actionengine/3rdparty/goblin/goblin.js +9609 -0
- package/actionengine/3rdparty/goblin/goblin.min.js +5 -0
- package/actionengine/camera/actioncamera.js +90 -0
- package/actionengine/camera/cameracollisionhandler.js +69 -0
- package/actionengine/character/actioncharacter.js +360 -0
- package/actionengine/character/actioncharacter3D.js +61 -0
- package/actionengine/core/app.js +430 -0
- package/actionengine/debug/basedebugpanel.js +858 -0
- package/actionengine/display/canvasmanager.js +75 -0
- package/actionengine/display/gl/programmanager.js +570 -0
- package/actionengine/display/gl/shaders/lineshader.js +118 -0
- package/actionengine/display/gl/shaders/objectshader.js +1756 -0
- package/actionengine/display/gl/shaders/particleshader.js +43 -0
- package/actionengine/display/gl/shaders/shadowshader.js +319 -0
- package/actionengine/display/gl/shaders/spriteshader.js +100 -0
- package/actionengine/display/gl/shaders/watershader.js +67 -0
- package/actionengine/display/graphics/actionmodel3D.js +191 -0
- package/actionengine/display/graphics/actionsprite3D.js +230 -0
- package/actionengine/display/graphics/lighting/actiondirectionalshadowlight.js +864 -0
- package/actionengine/display/graphics/lighting/actionlight.js +211 -0
- package/actionengine/display/graphics/lighting/actionomnidirectionalshadowlight.js +862 -0
- package/actionengine/display/graphics/lighting/lightingconstants.js +263 -0
- package/actionengine/display/graphics/lighting/lightmanager.js +789 -0
- package/actionengine/display/graphics/renderableobject.js +44 -0
- package/actionengine/display/graphics/renderers/actionrenderer2D.js +341 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/actionrenderer3D.js +655 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/canvasmanager3D.js +82 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/debugrenderer3D.js +493 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/objectrenderer3D.js +790 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/spriteRenderer3D.js +266 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/sunrenderer3D.js +140 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/waterrenderer3D.js +173 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/weatherrenderer3D.js +87 -0
- package/actionengine/display/graphics/texture/proceduraltexture.js +192 -0
- package/actionengine/display/graphics/texture/texturemanager.js +242 -0
- package/actionengine/display/graphics/texture/textureregistry.js +177 -0
- package/actionengine/input/actionscrollablearea.js +1405 -0
- package/actionengine/input/inputhandler.js +1647 -0
- package/actionengine/math/geometry/geometrybuilder.js +161 -0
- package/actionengine/math/geometry/glbexporter.js +364 -0
- package/actionengine/math/geometry/glbloader.js +722 -0
- package/actionengine/math/geometry/modelcodegenerator.js +97 -0
- package/actionengine/math/geometry/triangle.js +33 -0
- package/actionengine/math/geometry/triangleutils.js +34 -0
- package/actionengine/math/mathutils.js +25 -0
- package/actionengine/math/matrix4.js +785 -0
- package/actionengine/math/physics/actionphysics.js +108 -0
- package/actionengine/math/physics/actionphysicsobject3D.js +164 -0
- package/actionengine/math/physics/actionphysicsworld3D.js +238 -0
- package/actionengine/math/physics/actionraycast.js +129 -0
- package/actionengine/math/physics/shapes/actionphysicsbox3D.js +158 -0
- package/actionengine/math/physics/shapes/actionphysicscapsule3D.js +200 -0
- package/actionengine/math/physics/shapes/actionphysicscompoundshape3D.js +147 -0
- package/actionengine/math/physics/shapes/actionphysicscone3D.js +126 -0
- package/actionengine/math/physics/shapes/actionphysicsconvexshape3D.js +72 -0
- package/actionengine/math/physics/shapes/actionphysicscylinder3D.js +117 -0
- package/actionengine/math/physics/shapes/actionphysicsmesh3D.js +74 -0
- package/actionengine/math/physics/shapes/actionphysicsplane3D.js +100 -0
- package/actionengine/math/physics/shapes/actionphysicssphere3D.js +95 -0
- package/actionengine/math/quaternion.js +61 -0
- package/actionengine/math/vector2.js +277 -0
- package/actionengine/math/vector3.js +318 -0
- package/actionengine/math/viewfrustum.js +136 -0
- package/actionengine/network/ACTIONNETREADME.md +810 -0
- package/actionengine/network/client/ActionNetManager.js +802 -0
- package/actionengine/network/client/ActionNetManagerGUI.js +1709 -0
- package/actionengine/network/client/ActionNetManagerP2P.js +1537 -0
- package/actionengine/network/client/SyncSystem.js +422 -0
- package/actionengine/network/p2p/ActionNetPeer.js +142 -0
- package/actionengine/network/p2p/ActionNetTrackerClient.js +623 -0
- package/actionengine/network/p2p/DataConnection.js +282 -0
- package/actionengine/network/p2p/README.md +510 -0
- package/actionengine/network/p2p/example.html +502 -0
- package/actionengine/network/server/ActionNetServer.js +577 -0
- package/actionengine/network/server/ActionNetServerSSL.js +579 -0
- package/actionengine/network/server/ActionNetServerUtils.js +458 -0
- package/actionengine/network/server/SERVERREADME.md +314 -0
- package/actionengine/network/server/package-lock.json +35 -0
- package/actionengine/network/server/package.json +13 -0
- package/actionengine/network/server/start.bat +27 -0
- package/actionengine/network/server/start.sh +25 -0
- package/actionengine/network/server/startwss.bat +27 -0
- package/actionengine/sound/audiomanager.js +1589 -0
- package/actionengine/sound/soundfont/ACTIONSOUNDFONT_README.md +205 -0
- package/actionengine/sound/soundfont/actionparser.js +718 -0
- package/actionengine/sound/soundfont/actionreverb.js +252 -0
- package/actionengine/sound/soundfont/actionsoundfont.js +543 -0
- package/actionengine/sound/soundfont/sf2playerlicence.txt +29 -0
- package/actionengine/sound/soundfont/soundfont.js +2 -0
- package/dist/action-engine.min.js +328 -0
- package/package.json +35 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataConnection - App Data Layer
|
|
3
|
+
*
|
|
4
|
+
* Standalone RTCPeerConnection for app data negotiation.
|
|
5
|
+
* Receives offer/answer/ICE candidates via signal() method.
|
|
6
|
+
* Emits 'data' events when data channel receives messages.
|
|
7
|
+
*
|
|
8
|
+
* USAGE:
|
|
9
|
+
* ```javascript
|
|
10
|
+
* const connection = new DataConnection({
|
|
11
|
+
* localPeerId: 'peer1',
|
|
12
|
+
* remotePeerId: 'peer2'
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* // Handle tracker messages
|
|
16
|
+
* connection.signal(offerFromTracker);
|
|
17
|
+
* connection.signal(answerFromTracker);
|
|
18
|
+
* connection.signal(iceCandidate);
|
|
19
|
+
*
|
|
20
|
+
* connection.on('connect', () => {
|
|
21
|
+
* connection.send({ type: 'greeting' });
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
class DataConnection {
|
|
27
|
+
constructor(options = {}) {
|
|
28
|
+
this.pc = null;
|
|
29
|
+
this.dataChannel = null;
|
|
30
|
+
this.handlers = new Map();
|
|
31
|
+
|
|
32
|
+
// Store peer IDs
|
|
33
|
+
this.localPeerId = options.localPeerId;
|
|
34
|
+
this.remotePeerId = options.remotePeerId;
|
|
35
|
+
|
|
36
|
+
// Store ICE servers
|
|
37
|
+
this.iceServers = options.iceServers || [
|
|
38
|
+
{ urls: 'stun:stun.l.google.com:19302' },
|
|
39
|
+
{ urls: 'stun:stun1.l.google.com:19302' }
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// Determine initiator: either explicitly set or by peer ID comparison
|
|
43
|
+
if (options.initiator !== undefined) {
|
|
44
|
+
this.isInitiator = options.initiator;
|
|
45
|
+
} else {
|
|
46
|
+
this.isInitiator = options.localPeerId > options.remotePeerId;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.connected = false;
|
|
50
|
+
this.ready = false;
|
|
51
|
+
|
|
52
|
+
this._setup();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Setup DataConnection with standalone RTCPeerConnection
|
|
57
|
+
*/
|
|
58
|
+
_setup() {
|
|
59
|
+
// Create RTCPeerConnection for app data channel
|
|
60
|
+
this.pc = new RTCPeerConnection({
|
|
61
|
+
iceServers: this.iceServers
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Listen for ICE candidates
|
|
65
|
+
this.pc.onicecandidate = (evt) => {
|
|
66
|
+
if (evt.candidate) {
|
|
67
|
+
// Emit ICE candidate so caller can relay it
|
|
68
|
+
this.emit('signal', {
|
|
69
|
+
type: 'ice-candidate',
|
|
70
|
+
candidate: evt.candidate
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Listen for remote data channel
|
|
76
|
+
this.pc.ondatachannel = (evt) => {
|
|
77
|
+
this.dataChannel = evt.channel;
|
|
78
|
+
this._setupDataChannel();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// If initiator, create offer
|
|
82
|
+
if (this.isInitiator) {
|
|
83
|
+
this._createOffer();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create and send offer
|
|
89
|
+
*/
|
|
90
|
+
async _createOffer() {
|
|
91
|
+
try {
|
|
92
|
+
// Create data channel
|
|
93
|
+
const channel = this.pc.createDataChannel('app', { ordered: true });
|
|
94
|
+
this.dataChannel = channel;
|
|
95
|
+
this._setupDataChannel();
|
|
96
|
+
|
|
97
|
+
// Create offer
|
|
98
|
+
const offer = await this.pc.createOffer();
|
|
99
|
+
await this.pc.setLocalDescription(offer);
|
|
100
|
+
|
|
101
|
+
// Wait for ICE gathering to complete
|
|
102
|
+
await new Promise((resolve) => {
|
|
103
|
+
if (this.pc.iceGatheringState === 'complete') {
|
|
104
|
+
resolve();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const checkComplete = () => {
|
|
109
|
+
if (this.pc.iceGatheringState === 'complete') {
|
|
110
|
+
this.pc.removeEventListener('icegatheringstatechange', checkComplete);
|
|
111
|
+
resolve();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
this.pc.addEventListener('icegatheringstatechange', checkComplete);
|
|
116
|
+
|
|
117
|
+
// Fallback timeout
|
|
118
|
+
setTimeout(() => {
|
|
119
|
+
this.pc.removeEventListener('icegatheringstatechange', checkComplete);
|
|
120
|
+
resolve();
|
|
121
|
+
}, 3000);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Emit offer
|
|
125
|
+
this.emit('signal', {
|
|
126
|
+
type: 'offer',
|
|
127
|
+
sdp: this.pc.localDescription.sdp
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
this.ready = true;
|
|
131
|
+
} catch (e) {
|
|
132
|
+
this.emit('error', e);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Handle incoming offer/answer/ICE from caller
|
|
138
|
+
*/
|
|
139
|
+
signal(data) {
|
|
140
|
+
if (!this.pc) return;
|
|
141
|
+
|
|
142
|
+
if (data.type === 'offer') {
|
|
143
|
+
// Responder receives offer
|
|
144
|
+
this._handleOffer(data);
|
|
145
|
+
} else if (data.type === 'answer') {
|
|
146
|
+
// Initiator receives answer
|
|
147
|
+
this.pc.setRemoteDescription({ type: 'answer', sdp: data.sdp })
|
|
148
|
+
.catch((error) => {
|
|
149
|
+
this.emit('error', new Error(`Failed to set remote answer: ${error.message}`));
|
|
150
|
+
});
|
|
151
|
+
} else if (data.candidate) {
|
|
152
|
+
// ICE candidate
|
|
153
|
+
this.pc.addIceCandidate(new RTCIceCandidate(data.candidate))
|
|
154
|
+
.catch((e) => {
|
|
155
|
+
console.debug('[DataConnection] ICE candidate error (non-fatal):', e.message);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Handle incoming offer (responder side)
|
|
162
|
+
*/
|
|
163
|
+
async _handleOffer(data) {
|
|
164
|
+
try {
|
|
165
|
+
await this.pc.setRemoteDescription({ type: 'offer', sdp: data.sdp });
|
|
166
|
+
|
|
167
|
+
const answer = await this.pc.createAnswer();
|
|
168
|
+
await this.pc.setLocalDescription(answer);
|
|
169
|
+
|
|
170
|
+
// Wait for ICE gathering to complete
|
|
171
|
+
await new Promise((resolve) => {
|
|
172
|
+
if (this.pc.iceGatheringState === 'complete') {
|
|
173
|
+
resolve();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const checkComplete = () => {
|
|
178
|
+
if (this.pc.iceGatheringState === 'complete') {
|
|
179
|
+
this.pc.removeEventListener('icegatheringstatechange', checkComplete);
|
|
180
|
+
resolve();
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
this.pc.addEventListener('icegatheringstatechange', checkComplete);
|
|
185
|
+
|
|
186
|
+
// Fallback timeout
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
this.pc.removeEventListener('icegatheringstatechange', checkComplete);
|
|
189
|
+
resolve();
|
|
190
|
+
}, 3000);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Emit answer
|
|
194
|
+
this.emit('signal', {
|
|
195
|
+
type: 'answer',
|
|
196
|
+
sdp: this.pc.localDescription.sdp
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
this.ready = true;
|
|
200
|
+
} catch (e) {
|
|
201
|
+
this.emit('error', e);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Setup data channel handlers
|
|
207
|
+
*/
|
|
208
|
+
_setupDataChannel() {
|
|
209
|
+
this.dataChannel.onopen = () => {
|
|
210
|
+
this.connected = true;
|
|
211
|
+
this.emit('connect');
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
this.dataChannel.onclose = () => {
|
|
215
|
+
this.connected = false;
|
|
216
|
+
this.emit('close');
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
this.dataChannel.onerror = (evt) => {
|
|
220
|
+
this.emit('error', evt.error);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
this.dataChannel.onmessage = (evt) => {
|
|
224
|
+
try {
|
|
225
|
+
const message = JSON.parse(evt.data);
|
|
226
|
+
this.emit('data', message);
|
|
227
|
+
} catch (e) {
|
|
228
|
+
// Non-JSON messages are ignored
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Send a message through the data channel
|
|
235
|
+
*/
|
|
236
|
+
send(message) {
|
|
237
|
+
if (!this.connected || !this.dataChannel || this.dataChannel.readyState !== 'open') {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
this.dataChannel.send(JSON.stringify(message));
|
|
243
|
+
return true;
|
|
244
|
+
} catch (e) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Event handling
|
|
251
|
+
*/
|
|
252
|
+
on(event, handler) {
|
|
253
|
+
if (!this.handlers.has(event)) {
|
|
254
|
+
this.handlers.set(event, []);
|
|
255
|
+
}
|
|
256
|
+
this.handlers.get(event).push(handler);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
emit(event, ...args) {
|
|
260
|
+
if (!this.handlers.has(event)) return;
|
|
261
|
+
for (const handler of this.handlers.get(event)) {
|
|
262
|
+
try {
|
|
263
|
+
handler(...args);
|
|
264
|
+
} catch (e) {
|
|
265
|
+
console.error(`[DataConnection] Error in ${event} handler:`, e);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Cleanup
|
|
272
|
+
*/
|
|
273
|
+
close() {
|
|
274
|
+
if (this.dataChannel) {
|
|
275
|
+
this.dataChannel.close();
|
|
276
|
+
}
|
|
277
|
+
if (this.pc) {
|
|
278
|
+
this.pc.close();
|
|
279
|
+
}
|
|
280
|
+
this.connected = false;
|
|
281
|
+
}
|
|
282
|
+
}
|