smodusermc commited on
Commit
36aebcb
·
verified ·
1 Parent(s): cbdccdc

Create start.sh

Browse files
Files changed (1) hide show
  1. start.sh +710 -0
start.sh ADDED
@@ -0,0 +1,710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ JAVA_HOME_DIR=$(find /usr/lib/jvm -maxdepth 1 -name "java-17-openjdk-*" -type d 2>/dev/null | head -1)
4
+ if [ -z "$JAVA_HOME_DIR" ]; then
5
+ echo "ERROR: Java 17 not found!"
6
+ exit 1
7
+ fi
8
+ JAVA="$JAVA_HOME_DIR/bin/java"
9
+
10
+ BUNGEE_DIR="/opt/server/bungee"
11
+ BACKEND_DIR="/opt/server/backend"
12
+ PLUGIN_DIR="$BACKEND_DIR/plugins"
13
+
14
+ mkdir -p "$PLUGIN_DIR"
15
+
16
+ HF_BUCKET_HANDLE="${HF_BUCKET_HANDLE:-hf://buckets/${SPACE_AUTHOR_NAME:-your-username}/eaglercraft-saves}"
17
+ SAVE_DIRS="world world_nether world_the_end players banned-ips.json banned-players.json ops.json whitelist.json"
18
+ SYNC_INTERVAL="${SYNC_INTERVAL:-300}"
19
+
20
+ IDLE_MODE=false
21
+
22
+ # =============================================
23
+ # OP ACCOUNT — set your username here
24
+ # =============================================
25
+ OP_USERNAME="CreppyBitch"
26
+
27
+ CPU_CORES=$(nproc 2>/dev/null || echo 2)
28
+ NETTY_THREADS=$CPU_CORES
29
+
30
+ TOTAL_MEM_MB=$(free -m | awk '/^Mem:/{print $2}')
31
+ BUNGEE_MAX_MB=1024
32
+ PAPER_MAX_MB=$(( TOTAL_MEM_MB - BUNGEE_MAX_MB - 768 ))
33
+ [ "$PAPER_MAX_MB" -gt 8192 ] && PAPER_MAX_MB=8192
34
+ [ "$PAPER_MAX_MB" -lt 1024 ] && PAPER_MAX_MB=1024
35
+ PAPER_MIN_MB=8192
36
+
37
+ echo "========================================"
38
+ echo " Eaglercraft 1.8.8 Survival"
39
+ echo " WindSpigot + HuggingFace Buckets"
40
+ echo "========================================"
41
+ echo ""
42
+ echo " CPUs: $CPU_CORES | RAM: ${TOTAL_MEM_MB}MB"
43
+ echo " Server: ${PAPER_MIN_MB}-${PAPER_MAX_MB}MB | Bungee: ${BUNGEE_MAX_MB}MB"
44
+ echo " Java: $($JAVA -version 2>&1 | head -1)"
45
+ echo " Bucket: $HF_BUCKET_HANDLE"
46
+ [ -n "$OP_USERNAME" ] && echo " OP Account: $OP_USERNAME"
47
+ echo ""
48
+
49
+ # =============================================
50
+ # JVM FLAGS — no GC thread limits
51
+ # =============================================
52
+ PAPER_JVM_FLAGS=(
53
+ -Xmx${PAPER_MAX_MB}M
54
+ -Xms${PAPER_MIN_MB}M
55
+ -XX:+UseG1GC
56
+ -XX:+ParallelRefProcEnabled
57
+ -XX:MaxGCPauseMillis=25
58
+ -XX:+UnlockExperimentalVMOptions
59
+ -XX:+DisableExplicitGC
60
+ -XX:G1NewSizePercent=40
61
+ -XX:G1MaxNewSizePercent=50
62
+ -XX:G1HeapRegionSize=8M
63
+ -XX:G1ReservePercent=15
64
+ -XX:G1HeapWastePercent=10
65
+ -XX:G1MixedGCCountTarget=8
66
+ -XX:InitiatingHeapOccupancyPercent=60
67
+ -XX:G1MixedGCLiveThresholdPercent=90
68
+ -XX:G1RSetUpdatingPauseTimePercent=5
69
+ -XX:SurvivorRatio=32
70
+ -XX:+PerfDisableSharedMem
71
+ -XX:MaxTenuringThreshold=1
72
+ -XX:+OptimizeStringConcat
73
+ -XX:+UseCompressedOops
74
+ -XX:MaxMetaspaceSize=256M
75
+ -XX:CompressedClassSpaceSize=128M
76
+ -XX:ReservedCodeCacheSize=128M
77
+ -XX:-UseCodeCacheFlushing
78
+ -Xss256k
79
+ -Djline.terminal=jline.UnsupportedTerminal
80
+ -Dio.netty.allocator.maxCachedBufferCapacity=524288
81
+ -Dio.netty.recycler.maxCapacityPerThread=0
82
+ -Dio.netty.eventLoopThreads=${NETTY_THREADS}
83
+ -Dio.netty.allocator.numDirectArenas=${NETTY_THREADS}
84
+ -Dio.netty.allocator.numHeapArenas=${NETTY_THREADS}
85
+ -Dcom.mojang.eula.agree=true
86
+ -DIReallyKnowWhatIAmDoingISwear
87
+ -Dusing.aikars.flags=https://mcflags.emc.gs
88
+ -Daikars.new.flags=true
89
+ )
90
+
91
+ BUNGEE_JVM_FLAGS=(
92
+ -Xmx${BUNGEE_MAX_MB}M
93
+ -Xms128M
94
+ -XX:+UseG1GC
95
+ -XX:+ParallelRefProcEnabled
96
+ -XX:MaxGCPauseMillis=30
97
+ -XX:+UnlockExperimentalVMOptions
98
+ -XX:+DisableExplicitGC
99
+ -XX:+PerfDisableSharedMem
100
+ -XX:+OptimizeStringConcat
101
+ -XX:+UseCompressedOops
102
+ -XX:MaxMetaspaceSize=128M
103
+ -XX:ReservedCodeCacheSize=64M
104
+ -Xss256k
105
+ -Dio.netty.allocator.maxCachedBufferCapacity=524288
106
+ -Dio.netty.recycler.maxCapacityPerThread=0
107
+ -Dio.netty.eventLoopThreads=${NETTY_THREADS}
108
+ -Dio.netty.allocator.numDirectArenas=${NETTY_THREADS}
109
+ -Dio.netty.allocator.numHeapArenas=${NETTY_THREADS}
110
+ -Deaglerxbungee.stfu=true
111
+ )
112
+
113
+ # =============================================================
114
+ # RCON
115
+ # =============================================================
116
+ RCON_PASS="chunkystart"
117
+
118
+ get_player_count() {
119
+ local RESULT
120
+ RESULT=$(mcrcon -H 127.0.0.1 -P 25575 -p "$RCON_PASS" "list" 2>/dev/null)
121
+ echo "$RESULT" | grep -oE 'are [0-9]+' | grep -oE '[0-9]+' || echo "0"
122
+ }
123
+
124
+ mc_command() {
125
+ mcrcon -H 127.0.0.1 -P 25575 -p "$RCON_PASS" "$@" 2>/dev/null
126
+ }
127
+
128
+ # =============================================================
129
+ # WindSpigot starter
130
+ # =============================================================
131
+ start_windspigot() {
132
+ cd "$BACKEND_DIR"
133
+ $JAVA "${PAPER_JVM_FLAGS[@]}" -jar server.jar nogui --noconsole >> /tmp/paper.log 2>&1 &
134
+ BACKEND_PID=$!
135
+ }
136
+
137
+ # =============================================================
138
+ # OP Account Setup
139
+ # =============================================================
140
+ setup_op_account() {
141
+ if [ -z "$OP_USERNAME" ]; then
142
+ return
143
+ fi
144
+
145
+ echo " Setting up OP for: $OP_USERNAME"
146
+
147
+ local OFFLINE_UUID
148
+ OFFLINE_UUID=$(echo -n "OfflinePlayer:${OP_USERNAME}" | md5sum | sed 's/\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)/\1\2\3\4-\5\6-\7\8-\9\10-\11\12\13\14\15\16/')
149
+ local V3_UUID
150
+ V3_UUID=$(echo "$OFFLINE_UUID" | sed 's/.\{1\}\(.\{3\}-\)/3\1/' | sed 's/\(.\{14\}-\).\(.\{3\}-\)/\1'"$(echo "$OFFLINE_UUID" | cut -c15 | tr '0-9a-f' '89ab89ab89ab89ab')"'\2/')
151
+
152
+ cat > "$BACKEND_DIR/ops.json" << OPEOF
153
+ [
154
+ {
155
+ "uuid": "${V3_UUID}",
156
+ "name": "${OP_USERNAME}",
157
+ "level": 4,
158
+ "bypassesPlayerLimit": true
159
+ }
160
+ ]
161
+ OPEOF
162
+ echo " ops.json written (level 4, UUID: ${V3_UUID})"
163
+
164
+ mc_command "op ${OP_USERNAME}" 2>/dev/null
165
+ echo " RCON op command sent"
166
+ }
167
+
168
+ # =============================================================
169
+ # IDLE MODE
170
+ # =============================================================
171
+ enter_idle_mode() {
172
+ [ "$IDLE_MODE" = true ] && return
173
+ IDLE_MODE=true
174
+ mc_command "gamerule randomTickSpeed 0" "gamerule doMobSpawning false" "kill @e[type=!Player]"
175
+ echo "[IDLE] Active"
176
+ }
177
+
178
+ exit_idle_mode() {
179
+ [ "$IDLE_MODE" = false ] && return
180
+ IDLE_MODE=false
181
+ mc_command "gamerule randomTickSpeed 3" "gamerule doMobSpawning true"
182
+ echo "[IDLE] Gameplay restored"
183
+ }
184
+
185
+ # =============================================================
186
+ # Port fix
187
+ # =============================================================
188
+ find_listeners_yml() {
189
+ find "$BUNGEE_DIR/plugins" -name "listeners.yml" -type f 2>/dev/null | head -1
190
+ }
191
+
192
+ patch_eagler_port() {
193
+ local FILE=$(find_listeners_yml)
194
+ [ -z "$FILE" ] && return 1
195
+ grep -q ":7860" "$FILE" && return 0
196
+ sed -i 's/\(address:[[:space:]]*"[^:]*:\)[0-9]*/\17860/' "$FILE"
197
+ sed -i "s/\(address:[[:space:]]*[^\"][^:]*:\)[0-9]*/\17860/" "$FILE"
198
+ echo " Port -> 7860"
199
+ }
200
+
201
+ start_bungee() {
202
+ cd "$BUNGEE_DIR"
203
+ $JAVA "${BUNGEE_JVM_FLAGS[@]}" \
204
+ -cp "sqlite-jdbc.jar:BungeeCord.jar" \
205
+ net.md_5.bungee.Bootstrap >> /tmp/bungee.log 2>&1 &
206
+ BUNGEE_PID=$!
207
+ }
208
+
209
+ # =============================================================
210
+ # HuggingFace Bucket
211
+ # =============================================================
212
+ hf_authenticate() {
213
+ if [ -n "$HF_TOKEN" ]; then
214
+ hf auth login --token "$HF_TOKEN" --add-to-git-credential 2>/dev/null || true
215
+ echo " Authenticated"
216
+ else
217
+ echo " No HF_TOKEN"
218
+ fi
219
+ }
220
+
221
+ hf_ensure_bucket() {
222
+ local BUCKET_ID=$(echo "$HF_BUCKET_HANDLE" | sed 's|hf://buckets/||')
223
+ hf buckets create "$BUCKET_ID" --exist-ok 2>/dev/null
224
+ }
225
+
226
+ hf_restore_saves() {
227
+ echo " Restoring game data..."
228
+ hf buckets sync "${HF_BUCKET_HANDLE}/game-data" "$BACKEND_DIR" 2>&1 | tail -5
229
+ for dir in $SAVE_DIRS; do
230
+ [ -e "$BACKEND_DIR/$dir" ] && echo " Found: $dir"
231
+ done
232
+ }
233
+
234
+ hf_push_saves() {
235
+ local STAGING="/tmp/hf-staging"
236
+ rm -rf "$STAGING" && mkdir -p "$STAGING"
237
+ for item in $SAVE_DIRS; do
238
+ [ -e "$BACKEND_DIR/$item" ] && cp -a "$BACKEND_DIR/$item" "$STAGING/$item"
239
+ done
240
+ hf buckets sync "$STAGING" "${HF_BUCKET_HANDLE}/game-data" --delete 2>&1 | tail -3
241
+ [ $? -eq 0 ] && echo "[SYNC] OK $(date '+%H:%M:%S')" \
242
+ || echo "[SYNC] FAIL $(date '+%H:%M:%S')"
243
+ rm -rf "$STAGING"
244
+ }
245
+
246
+ hf_sync_loop() {
247
+ while true; do
248
+ sleep "$SYNC_INTERVAL"
249
+ hf_push_saves
250
+ done
251
+ }
252
+
253
+ # =============================================================
254
+ # STEP 0: Bucket
255
+ # =============================================================
256
+ echo "[0/6] Bucket setup..."
257
+ hf_authenticate
258
+ hf_ensure_bucket
259
+ hf_restore_saves
260
+ echo ""
261
+
262
+ # =============================================================
263
+ # STEP 1: World size
264
+ # =============================================================
265
+ echo "[1/6] World analysis..."
266
+ for WORLD_DIR in world world_nether world_the_end; do
267
+ if [ -d "$BACKEND_DIR/$WORLD_DIR" ]; then
268
+ SIZE=$(du -sh "$BACKEND_DIR/$WORLD_DIR" 2>/dev/null | awk '{print $1}')
269
+ REGIONS=$(find "$BACKEND_DIR/$WORLD_DIR" -name "*.mca" 2>/dev/null | wc -l)
270
+ echo " $WORLD_DIR: $SIZE ($REGIONS region files)"
271
+ fi
272
+ done
273
+ echo ""
274
+
275
+ # =============================================================
276
+ # STEP 2: Start WindSpigot
277
+ # =============================================================
278
+ cd "$BACKEND_DIR"
279
+ echo "eula=true" > eula.txt
280
+
281
+ cat > server.properties << 'EOF'
282
+ server-port=25565
283
+ server-ip=127.0.0.1
284
+ online-mode=false
285
+ spawn-protection=0
286
+ max-players=10
287
+ view-distance=4
288
+ gamemode=0
289
+ difficulty=2
290
+ level-name=world
291
+ level-type=DEFAULT
292
+ level-seed=8678942899319966093
293
+ generate-structures=true
294
+ motd=Eaglercraft Server
295
+ pvp=true
296
+ allow-flight=false
297
+ white-list=false
298
+ spawn-npcs=true
299
+ spawn-animals=true
300
+ spawn-monsters=true
301
+ enable-command-block=true
302
+ allow-nether=true
303
+ use-native-transport=true
304
+ network-compression-threshold=-1
305
+ entity-broadcast-range-percentage=50
306
+ max-tick-time=-1
307
+ enable-rcon=true
308
+ rcon.port=25575
309
+ rcon.password=chunkystart
310
+ EOF
311
+
312
+ cat > bukkit.yml << 'EOF'
313
+ settings:
314
+ allow-end: true
315
+ warn-on-overload: true
316
+ connection-throttle: -1
317
+ shutdown-message: Server closed
318
+ save-user-cache-on-stop-only: true
319
+ spawn-limits:
320
+ monsters: 30
321
+ animals: 6
322
+ water-animals: 2
323
+ ambient: 1
324
+ chunk-gc:
325
+ period-in-ticks: 600
326
+ ticks-per:
327
+ animal-spawns: 600
328
+ monster-spawns: 4
329
+ autosave: 12000
330
+ EOF
331
+
332
+ cat > spigot.yml << 'EOF'
333
+ config-version: 8
334
+ settings:
335
+ bungeecord: true
336
+ timeout-time: 60
337
+ netty-threads: 2
338
+ async-catcher-enabled: false
339
+ save-user-cache-on-stop-only: true
340
+ moved-wrongly-threshold: 0.0625
341
+ moved-too-quickly-multiplier: 10.0
342
+ item-dirty-ticks: 20
343
+ player-shuffle: 0
344
+ commands:
345
+ tab-complete: 0
346
+ log: false
347
+ world-settings:
348
+ default:
349
+ verbose: false
350
+ view-distance: 4
351
+ mob-spawn-range: 3
352
+ entity-activation-range:
353
+ animals: 12
354
+ monsters: 20
355
+ misc: 6
356
+ tick-inactive-villagers: false
357
+ entity-tracking-range:
358
+ players: 48
359
+ animals: 32
360
+ monsters: 32
361
+ misc: 16
362
+ other: 48
363
+ ticks-per:
364
+ hopper-transfer: 8
365
+ hopper-check: 1
366
+ hopper-amount: 1
367
+ max-entity-collisions: 2
368
+ merge-radius:
369
+ exp: 6.0
370
+ item: 4.0
371
+ arrow-despawn-rate: 60
372
+ item-despawn-rate: 3000
373
+ nerf-spawner-mobs: true
374
+ zombie-aggressive-towards-villager: false
375
+ enable-zombie-pigmen-portal-spawns: false
376
+ EOF
377
+
378
+ cat > windspigot.yml << 'EOF'
379
+ settings:
380
+ async:
381
+ entity-tracking: true
382
+ path-searching: true
383
+ tnt-explosions: true
384
+ lighting: true
385
+ tnt:
386
+ optimize-movement: true
387
+ optimize-liquid-explosions: true
388
+ fast-operators: true
389
+ stop-decoding-itemstack-on-place: true
390
+ modern-tick-loop:
391
+ enabled: false
392
+ tcp-fast-open: true
393
+ reduced-chunk-loads: true
394
+ lag-compensated-potions: false
395
+ anti-xray:
396
+ enabled: false
397
+ hit-detection:
398
+ enabled: true
399
+ threshold: 1.0
400
+ combat:
401
+ knockback:
402
+ friction: 2.0
403
+ horizontal: 0.35
404
+ vertical: 0.35
405
+ vertical-limit: 0.4
406
+ extra-horizontal: 0.425
407
+ extra-vertical: 0.085
408
+ chunk:
409
+ threads: 1
410
+ players-per-thread: 25
411
+ EOF
412
+
413
+ cat > nacho.yml << 'EOF'
414
+ settings:
415
+ stop-notify-bungee: true
416
+ anti-malware: true
417
+ use-tcp-nodelay: true
418
+ brand-name: "Survival"
419
+ EOF
420
+
421
+ # Write ops.json before server starts
422
+ setup_op_account
423
+
424
+ echo "[2/6] Starting WindSpigot (--noconsole to fix CPU bug)..."
425
+ > /tmp/paper.log
426
+
427
+ start_windspigot
428
+ echo " WindSpigot PID: $BACKEND_PID"
429
+
430
+ for i in $(seq 1 120); do
431
+ if grep -q "Done" /tmp/paper.log 2>/dev/null; then
432
+ echo " WindSpigot READY (~${i}s)"
433
+ break
434
+ fi
435
+ if ! kill -0 $BACKEND_PID 2>/dev/null; then
436
+ echo " WINDSPIGOT CRASHED!"
437
+ tail -30 /tmp/paper.log
438
+ exit 1
439
+ fi
440
+ [ $((i % 15)) -eq 0 ] && echo " Loading... (${i}s)"
441
+ sleep 1
442
+ done
443
+
444
+ for i in $(seq 1 30); do
445
+ nc -z 127.0.0.1 25575 2>/dev/null && break
446
+ sleep 1
447
+ done
448
+
449
+ # Send OP command via RCON as backup
450
+ if [ -n "$OP_USERNAME" ]; then
451
+ mc_command "op ${OP_USERNAME}"
452
+ echo " OP granted to ${OP_USERNAME} via RCON"
453
+ fi
454
+
455
+ echo ""
456
+ echo " === PLUGINS ==="
457
+ grep -i "Enabling" /tmp/paper.log | grep -oP "Enabling \K[^\s]+" 2>/dev/null | while read p; do
458
+ echo " - $p"
459
+ done
460
+ echo " ==============="
461
+ echo ""
462
+
463
+ # =============================================================
464
+ # STEP 3: Skip CPU check (removed)
465
+ # =============================================================
466
+ echo "[3/6] Skipping CPU check..."
467
+ echo ""
468
+
469
+ # =============================================================
470
+ # STEP 4: Apply idle mode
471
+ # =============================================================
472
+ echo "[4/6] Applying idle mode (no players)..."
473
+ mc_command "gamerule randomTickSpeed 0" "gamerule doMobSpawning false" "kill @e[type=!Player]"
474
+ IDLE_MODE=true
475
+ echo ""
476
+
477
+ # =============================================================
478
+ # STEP 5: BungeeCord
479
+ # =============================================================
480
+ echo "[5/6] BungeeCord config..."
481
+ cd "$BUNGEE_DIR"
482
+
483
+ cat > config.yml << 'EOF'
484
+ server_connect_timeout: 5000
485
+ remote_ping_cache: -1
486
+ forge_support: false
487
+ player_limit: 10
488
+ permissions:
489
+ default:
490
+ - bungeecord.command.server
491
+ admin:
492
+ - bungeecord.command.alert
493
+ timeout: 30000
494
+ log_commands: false
495
+ network_compression_threshold: 256
496
+ online_mode: false
497
+ disabled_commands:
498
+ - disabledcommandhere
499
+ servers:
500
+ lobby:
501
+ motd: '&aEaglercraft Survival'
502
+ address: 127.0.0.1:25565
503
+ restricted: false
504
+ listeners:
505
+ - query_port: 25577
506
+ motd: '&6Eaglercraft 1.8.8'
507
+ tab_list: GLOBAL_PING
508
+ query_enabled: false
509
+ proxy_protocol: false
510
+ forced_hosts: {}
511
+ ping_passthrough: false
512
+ priorities:
513
+ - lobby
514
+ bind_local_address: true
515
+ host: 127.0.0.1:25577
516
+ max_players: 10
517
+ tab_size: 60
518
+ force_default_server: true
519
+ ip_forward: true
520
+ remote_ping_timeout: 5000
521
+ prevent_proxy_connections: false
522
+ groups:
523
+ default:
524
+ - default
525
+ connection_throttle: -1
526
+ connection_throttle_limit: 0
527
+ stats: none
528
+ log_pings: false
529
+ EOF
530
+
531
+ LISTENERS_FILE=$(find_listeners_yml)
532
+
533
+ if [ -z "$LISTENERS_FILE" ]; then
534
+ echo "[6/6] Generating EaglerXBungee config..."
535
+ cd "$BUNGEE_DIR"
536
+ $JAVA "${BUNGEE_JVM_FLAGS[@]}" \
537
+ -cp "sqlite-jdbc.jar:BungeeCord.jar" \
538
+ net.md_5.bungee.Bootstrap >> /tmp/bungee-gen.log 2>&1 &
539
+ GEN_PID=$!
540
+
541
+ for i in $(seq 1 60); do
542
+ if nc -z 127.0.0.1 8081 2>/dev/null || nc -z 127.0.0.1 7860 2>/dev/null; then
543
+ echo " EaglerXBungee started (~$((i*2))s)"
544
+ break
545
+ fi
546
+ if ! kill -0 $GEN_PID 2>/dev/null; then
547
+ echo " Generation failed"
548
+ tail -20 /tmp/bungee-gen.log
549
+ break
550
+ fi
551
+ sleep 2
552
+ done
553
+
554
+ sleep 3
555
+ kill $GEN_PID 2>/dev/null
556
+ wait $GEN_PID 2>/dev/null
557
+ for i in $(seq 1 15); do
558
+ nc -z 127.0.0.1 8081 2>/dev/null || break
559
+ sleep 1
560
+ done
561
+ sleep 2
562
+ else
563
+ echo "[6/6] EaglerXBungee config exists"
564
+ fi
565
+
566
+ echo " Starting BungeeCord..."
567
+
568
+ patch_eagler_port
569
+
570
+ EAGLER_DIR=$(dirname "$(find_listeners_yml)" 2>/dev/null)
571
+ if [ -n "$EAGLER_DIR" ]; then
572
+ mkdir -p "$EAGLER_DIR/drivers"
573
+ cp -f "$BUNGEE_DIR/sqlite-jdbc.jar" "$EAGLER_DIR/drivers/sqlite-jdbc.jar" 2>/dev/null
574
+ fi
575
+
576
+ > /tmp/bungee.log
577
+ start_bungee
578
+ echo " BungeeCord PID: $BUNGEE_PID"
579
+
580
+ PORT_READY=false
581
+ for i in $(seq 1 45); do
582
+ if nc -z 127.0.0.1 7860 2>/dev/null; then
583
+ PORT_READY=true
584
+ echo " Port 7860 OPEN (~$((i*2))s)"
585
+ break
586
+ fi
587
+ if ! kill -0 $BUNGEE_PID 2>/dev/null; then
588
+ echo " BungeeCord crashed!"
589
+ tail -20 /tmp/bungee.log
590
+ break
591
+ fi
592
+ sleep 2
593
+ done
594
+
595
+ if [ "$PORT_READY" = true ]; then
596
+ echo ""
597
+ echo "============================================"
598
+ echo " SERVER READY — EaglerCraft on :7860"
599
+ [ -n "$OP_USERNAME" ] && echo " OP: $OP_USERNAME (level 4)"
600
+ echo "============================================"
601
+ else
602
+ echo " Port 7860 NOT open!"
603
+ for port in 7860 8081 25565 25577; do
604
+ nc -z 127.0.0.1 $port 2>/dev/null && echo " OK $port" || echo " FAIL $port"
605
+ done
606
+ LISTENERS_NOW=$(find_listeners_yml)
607
+ if [ -n "$LISTENERS_NOW" ] && grep -q ":8081" "$LISTENERS_NOW"; then
608
+ kill $BUNGEE_PID 2>/dev/null
609
+ wait $BUNGEE_PID 2>/dev/null
610
+ sleep 3
611
+ patch_eagler_port
612
+ start_bungee
613
+ sleep 20
614
+ nc -z 127.0.0.1 7860 2>/dev/null && echo " Port 7860 open!" || echo " Failed"
615
+ fi
616
+ fi
617
+
618
+ # =============================================================
619
+ # Sync loop
620
+ # =============================================================
621
+ hf_sync_loop &
622
+ SYNC_PID=$!
623
+
624
+ # =============================================================
625
+ # Shutdown
626
+ # =============================================================
627
+ graceful_shutdown() {
628
+ echo " Shutting down..."
629
+ mc_command "gamerule doMobSpawning true" "gamerule randomTickSpeed 3" "save-all"
630
+ sleep 5
631
+ hf_push_saves
632
+ kill $SYNC_PID $BACKEND_PID $BUNGEE_PID 2>/dev/null
633
+ exit 0
634
+ }
635
+
636
+ trap graceful_shutdown SIGTERM SIGINT SIGHUP
637
+
638
+ # =============================================================
639
+ # Monitor loop
640
+ # =============================================================
641
+ echo ""
642
+ echo "Monitor loop started..."
643
+
644
+ LAST_LOG_LINE=$(wc -l < /tmp/paper.log 2>/dev/null || echo 0)
645
+ LOOP_COUNT=0
646
+
647
+ while true; do
648
+ LOOP_COUNT=$((LOOP_COUNT + 1))
649
+
650
+ if ! kill -0 $BACKEND_PID 2>/dev/null; then
651
+ echo "[$(date '+%H:%M:%S')] WindSpigot crashed — restarting..."
652
+ hf_push_saves
653
+ IDLE_MODE=false
654
+ start_windspigot
655
+ sleep 45
656
+ # Re-OP after restart
657
+ if [ -n "$OP_USERNAME" ]; then
658
+ mc_command "op ${OP_USERNAME}" 2>/dev/null
659
+ fi
660
+ enter_idle_mode
661
+ fi
662
+
663
+ if ! kill -0 $BUNGEE_PID 2>/dev/null; then
664
+ echo "[$(date '+%H:%M:%S')] BungeeCord crashed — restarting..."
665
+ patch_eagler_port
666
+ start_bungee
667
+ fi
668
+
669
+ if ! kill -0 $SYNC_PID 2>/dev/null; then
670
+ hf_sync_loop &
671
+ SYNC_PID=$!
672
+ fi
673
+
674
+ if kill -0 $BACKEND_PID 2>/dev/null; then
675
+ PLAYER_COUNT=$(get_player_count)
676
+ if [ "$PLAYER_COUNT" != "0" ] && [ "$IDLE_MODE" = true ]; then
677
+ exit_idle_mode
678
+ elif [ "$PLAYER_COUNT" = "0" ] && [ "$IDLE_MODE" = false ]; then
679
+ enter_idle_mode
680
+ fi
681
+ fi
682
+
683
+ if [ $((LOOP_COUNT % 5)) -eq 0 ]; then
684
+ CURRENT_LINE=$(wc -l < /tmp/paper.log 2>/dev/null || echo 0)
685
+ if [ "$CURRENT_LINE" -gt "$LAST_LOG_LINE" ]; then
686
+ NEW_ERRORS=$(tail -n +"$((LAST_LOG_LINE + 1))" /tmp/paper.log | grep -c "ERROR\|SEVERE" || echo 0)
687
+ [ "$NEW_ERRORS" -gt 0 ] && echo "[$(date '+%H:%M:%S')] $NEW_ERRORS errors" && \
688
+ tail -n +"$((LAST_LOG_LINE + 1))" /tmp/paper.log | grep "ERROR\|SEVERE" | tail -3
689
+ LAST_LOG_LINE=$CURRENT_LINE
690
+ fi
691
+ fi
692
+
693
+ if [ $((LOOP_COUNT % 30)) -eq 0 ]; then
694
+ for LF in /tmp/paper.log /tmp/bungee.log; do
695
+ LS=$(stat -c%s "$LF" 2>/dev/null || echo 0)
696
+ if [ "$LS" -gt 10485760 ]; then
697
+ tail -1000 "$LF" > "${LF}.tmp" && mv "${LF}.tmp" "$LF"
698
+ echo "[$(date '+%H:%M:%S')] Trimmed $(basename $LF)"
699
+ fi
700
+ done
701
+ LAST_LOG_LINE=$(wc -l < /tmp/paper.log 2>/dev/null || echo 0)
702
+ fi
703
+
704
+ if [ $((LOOP_COUNT % 5)) -eq 0 ]; then
705
+ RSS=$(ps -p $BACKEND_PID -o rss= 2>/dev/null | awk '{printf "%.0f", $1/1024}')
706
+ echo "[STATUS] Players: ${PLAYER_COUNT:-?} | RAM: ${RSS:-?}MB | $([ "$IDLE_MODE" = true ] && echo IDLE || echo ACTIVE)"
707
+ fi
708
+
709
+ sleep 60
710
+ done