OrbitMC commited on
Commit
14796db
·
verified ·
1 Parent(s): c9c22d5

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +123 -75
server.js CHANGED
@@ -4,100 +4,148 @@ const { Server } = require('socket.io');
4
 
5
  const app = express();
6
  const server = http.createServer(app);
7
- const io = new Server(server, {
8
  cors: { origin: "*" },
9
- pingInterval: 1000,
10
- pingTimeout: 5000
11
  });
12
 
13
  app.use(express.static('public'));
14
 
15
- // GLOBAL STATE
16
- const players = {};
17
- // A static seed ensuring everyone gets the exact same map logic
18
- const GLOBAL_SEED = Math.floor(Math.random() * 1000000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  io.on('connection', (socket) => {
21
- // 1. Send configuration immediately
22
- socket.emit('config', { seed: GLOBAL_SEED });
23
 
24
- // 2. Player joins
25
- socket.on('join', (data) => {
26
- players[socket.id] = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  id: socket.id,
28
- name: (data.name || "Guest").substring(0, 12),
29
- skin: data.skin || "square",
30
- x: 0,
31
- y: 0,
32
- score: 0,
33
- isDead: false,
34
- lastSeen: Date.now()
35
- };
36
  });
37
 
38
- // 3. Receive player updates
39
- socket.on('update', (data) => {
40
  const p = players[socket.id];
41
- if (p) {
42
- // Data comes in array: [x, y, vx, vy, score, isDead]
43
- p.x = data[0];
44
- p.y = data[1];
45
- p.vx = data[2];
46
- p.vy = data[3];
47
- p.score = data[4];
48
- p.isDead = data[5];
49
- p.lastSeen = Date.now();
50
- }
51
  });
52
 
53
- socket.on('disconnect', () => {
54
- delete players[socket.id];
55
- });
56
- });
57
 
58
- // BROADCAST LOOP (30 TPS)
59
- // 30 times a second is the sweet spot for browser games.
60
- // 60 TPS over internet often causes packet choking (the 0.1fps issue).
61
- setInterval(() => {
62
- const pack = [];
63
- const leaderboard = [];
64
- const now = Date.now();
65
 
66
- for (const id in players) {
67
- const p = players[id];
68
-
69
- // Timeout check (remove stale players)
70
- if (now - p.lastSeen > 10000000000) {
71
- delete players[id];
72
- continue;
73
- }
74
 
75
- // COMPRESSION: Send Array instead of Object
76
- // [id, x, y, skin, isDead, name]
77
- pack.push([
78
- p.id,
79
- Math.round(p.x),
80
- Math.round(p.y),
81
- p.skin,
82
- p.isDead ? 1 : 0,
83
- p.name
84
- ]);
85
-
86
- if (!p.isDead) {
87
- leaderboard.push({ name: p.name, score: p.score });
88
- }
89
- }
90
 
91
- // Top 3 Leaderboard
92
- leaderboard.sort((a, b) => b.score - a.score);
93
- const top3 = leaderboard.slice(0, 3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- // Send world state
96
- io.emit('w', { p: pack, l: top3 });
 
 
 
 
 
 
 
 
 
 
97
 
98
- }, 33);
 
 
 
 
 
99
 
100
  const PORT = process.env.PORT || 3000;
101
- server.listen(PORT, () => {
102
- console.log(`Server running on port ${PORT} | Seed: ${GLOBAL_SEED}`);
103
- });
 
4
 
5
  const app = express();
6
  const server = http.createServer(app);
7
+ const io = new Server(server, {
8
  cors: { origin: "*" },
9
+ pingTimeout: 60000, // No timeout unless connection lost
 
10
  });
11
 
12
  app.use(express.static('public'));
13
 
14
+ // CONFIG
15
+ const GROWTH_RATE = 3; // Pixels per tick (must match client)
16
+ const PLATFORM_HEIGHT = 100;
17
+ const PLAYER_SIZE = 20;
18
+
19
+ // STATE
20
+ let platforms = []; // Shared world for everyone
21
+ let players = {}; // { socketId: { id, name, score, x, state, ... } }
22
+
23
+ // Generate infinite world logic
24
+ function generatePlatform(prevX, prevW) {
25
+ const gap = 80 + Math.random() * 120; // Random gap
26
+ const width = 40 + Math.random() * 60; // Random width
27
+ return {
28
+ x: prevX + prevW + gap,
29
+ w: width,
30
+ id: Math.random().toString(36).substr(2, 9)
31
+ };
32
+ }
33
+
34
+ // Init first few platforms
35
+ platforms.push({ x: 50, w: 100, id: 'start' });
36
+ for (let i = 0; i < 10; i++) {
37
+ const last = platforms[platforms.length - 1];
38
+ platforms.push(generatePlatform(last.x, last.w));
39
+ }
40
 
41
  io.on('connection', (socket) => {
42
+ console.log(`Player connected: ${socket.id}`);
 
43
 
44
+ // Init Player State
45
+ players[socket.id] = {
46
+ id: socket.id,
47
+ name: "Guest",
48
+ score: 0,
49
+ x: platforms[0].x + platforms[0].w - PLAYER_SIZE - 5,
50
+ currentPlatIndex: 0,
51
+ stickHeight: 0,
52
+ isGrowing: false,
53
+ growStartTime: 0,
54
+ state: 'ready' // ready, growing, moving, dead
55
+ };
56
+
57
+ // 1. Join Game
58
+ socket.on('join', (name) => {
59
+ players[socket.id].name = name.substring(0, 12) || "Guest";
60
+ // Send initial World State
61
+ socket.emit('init', {
62
  id: socket.id,
63
+ platforms: platforms,
64
+ players: players
65
+ });
66
+ io.emit('player_update', players[socket.id]); // Tell others
 
 
 
 
67
  });
68
 
69
+ // 2. Start Growing Stick
70
+ socket.on('start_grow', () => {
71
  const p = players[socket.id];
72
+ if (p.state !== 'ready') return;
73
+
74
+ p.state = 'growing';
75
+ p.growStartTime = Date.now();
76
+ p.isGrowing = true;
77
+
78
+ // Broadcast visual state to others
79
+ io.emit('player_action', { id: socket.id, type: 'grow_start' });
 
 
80
  });
81
 
82
+ // 3. Stop Growing (The Critical Physics Check)
83
+ socket.on('stop_grow', () => {
84
+ const p = players[socket.id];
85
+ if (p.state !== 'growing') return;
86
 
87
+ const duration = Date.now() - p.growStartTime;
88
+ // Server calculates length based on time. Client cannot fake stick length.
89
+ // We divide by approx frame rate (16ms) to match client visual loop
90
+ // Or simpler: stick grows based on ms duration directly
91
+ // Let's align with the client loop logic: roughly 60fps loop adds 3px
92
+ // 3px per ~16.6ms = ~0.18px per ms
93
+ p.stickHeight = Math.min((duration / 16.66) * GROWTH_RATE, 2000);
94
 
95
+ p.isGrowing = false;
96
+ p.state = 'moving';
 
 
 
 
 
 
97
 
98
+ io.emit('player_action', { id: socket.id, type: 'grow_stop', height: p.stickHeight });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
+ // Logic Check
101
+ const currentPlat = platforms[p.currentPlatIndex];
102
+ const nextPlat = platforms[p.currentPlatIndex + 1];
103
+
104
+ // Ensure we have platforms
105
+ if (!nextPlat) {
106
+ const last = platforms[platforms.length - 1];
107
+ platforms.push(generatePlatform(last.x, last.w));
108
+ io.emit('new_platform', platforms[platforms.length - 1]);
109
+ }
110
+
111
+ const stickEnd = currentPlat.x + currentPlat.w + p.stickHeight;
112
+
113
+ setTimeout(() => {
114
+ // Did they land?
115
+ if (stickEnd >= nextPlat.x && stickEnd <= nextPlat.x + nextPlat.w) {
116
+ // SUCCESS
117
+ p.score++;
118
+ p.currentPlatIndex++;
119
+ p.x = nextPlat.x + nextPlat.w - PLAYER_SIZE - 5;
120
+ p.state = 'ready';
121
+
122
+ // Generate more world if needed
123
+ if (platforms.length < p.currentPlatIndex + 5) {
124
+ const last = platforms[platforms.length - 1];
125
+ const newPlat = generatePlatform(last.x, last.w);
126
+ platforms.push(newPlat);
127
+ io.emit('new_platform', newPlat);
128
+ }
129
 
130
+ io.emit('player_result', { id: socket.id, success: true, score: p.score, x: p.x });
131
+ } else {
132
+ // FAIL
133
+ p.score = 0;
134
+ p.currentPlatIndex = 0;
135
+ p.x = platforms[0].x + platforms[0].w - PLAYER_SIZE - 5;
136
+ p.state = 'ready';
137
+
138
+ io.emit('player_result', { id: socket.id, success: false, score: 0, x: p.x });
139
+ }
140
+ }, 1000); // Wait for fall animation roughly
141
+ });
142
 
143
+ socket.on('disconnect', () => {
144
+ console.log(`Player disconnected: ${socket.id}`);
145
+ delete players[socket.id];
146
+ io.emit('player_leave', socket.id);
147
+ });
148
+ });
149
 
150
  const PORT = process.env.PORT || 3000;
151
+ server.listen(PORT, () => console.log(`Server running on port ${PORT}`));