+ digmeout minigame, usability fixes
parent
4bdc24558e
commit
59d995019d
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/env bash
|
||||
# digmeout - a score-based minigame
|
||||
# mine out as much ores before the time runs out
|
||||
|
||||
time_left=30
|
||||
score=0
|
||||
spawn_pos=(8 -40 8)
|
||||
|
||||
# palette expanded for easier randomization
|
||||
palette+=("45") # gold
|
||||
palette+=("47") # iron
|
||||
palette+=("49") # coal
|
||||
palette+=("8702") # lapis
|
||||
palette+=("d21a") # diamond
|
||||
palette+=("cf2a") # emerald
|
||||
palette+=("9a8b01") # copper
|
||||
palette+=("f11e") # redstone
|
||||
for i in {1..15}; do
|
||||
palette+=("01") # stone
|
||||
palette+=("02") # granite
|
||||
palette+=("04") # diorite
|
||||
done
|
||||
|
||||
function hook_chunks() {
|
||||
local ore
|
||||
local plane
|
||||
|
||||
log "hooking chunks"
|
||||
rm -R $TEMP/world/*
|
||||
chunk_header
|
||||
|
||||
oremap=()
|
||||
for (( y=0; y<16; y++ )); do
|
||||
plane=''
|
||||
for (( x=0; x<16; x++ )); do
|
||||
for (( z=0; z<16; z++ )); do
|
||||
ore=$(printf '%02x' $(((RANDOM%52)+31)))
|
||||
chunk+="$ore"
|
||||
plane+="$ore"
|
||||
done
|
||||
done
|
||||
oremap+=("$plane")
|
||||
done
|
||||
|
||||
chunk_footer
|
||||
|
||||
echo "${oremap[@]}" > $TEMP/players/$nick/oremap
|
||||
echo "$chunk" > $TEMP/world/0000000000000000
|
||||
|
||||
pkt_chunk FFFFFFFF FFFFFFFF 00
|
||||
pkt_chunk FFFFFFFF 00000000 00
|
||||
pkt_chunk FFFFFFFF 00000001 00
|
||||
|
||||
pkt_chunk 00000000 FFFFFFFF 00
|
||||
pkt_chunk 00000000 00000000
|
||||
pkt_chunk 00000000 00000001 00
|
||||
|
||||
pkt_chunk 00000001 FFFFFFFF 00
|
||||
pkt_chunk 00000001 00000000 00
|
||||
pkt_chunk 00000001 00000001 00
|
||||
|
||||
echo '0' > $TEMP/players/$nick/score
|
||||
pkt_title "Get, set..."
|
||||
}
|
||||
|
||||
function hook_start() {
|
||||
timer &
|
||||
pkt_title "Go!"
|
||||
}
|
||||
|
||||
function timer() {
|
||||
while true; do
|
||||
if [[ $time_left -le 0 ]]; then
|
||||
pos=$(cat $TEMP/players/$nick/position)
|
||||
pkt_effect $(awk -F, '{print $1}' <<< "$pos") $(awk -F, '{print $2}' <<< "$pos") $(awk -F, '{print $3}' <<< "$pos") 1032
|
||||
sleep 1
|
||||
break
|
||||
elif [[ $time_left -le 5 ]]; then
|
||||
sleep 1
|
||||
pos=$(cat $TEMP/players/$nick/position)
|
||||
pkt_effect $(awk -F, '{print $1}' <<< "$pos") $(awk -F, '{print $2}' <<< "$pos") $(awk -F, '{print $3}' <<< "$pos") 1000
|
||||
time_left=$((time_left-1))
|
||||
elif [[ $time_left -le 10 ]]; then
|
||||
sleep 5
|
||||
time_left=$((time_left-5))
|
||||
else
|
||||
sleep 10
|
||||
time_left=$((time_left-10))
|
||||
fi
|
||||
pkt_chatmessage "§aTime left: §r${time_left}s" "00000000000000000000000000000000"
|
||||
done
|
||||
pkt_disconnect "Time's up! Your final score: §a$(cat $TEMP/players/$nick/score)"
|
||||
}
|
||||
|
||||
function score() {
|
||||
# egh, async in Bash sucks
|
||||
score=$(cat $TEMP/players/$nick/score)
|
||||
if [[ "$block" == 45 ]]; then
|
||||
score=$((score+7))
|
||||
elif [[ "$block" == 47 ]]; then
|
||||
score=$((score+5))
|
||||
elif [[ "$block" == 49 ]]; then
|
||||
score=$((score+1))
|
||||
elif [[ "$block" == 8702 ]]; then
|
||||
score=$((score+6))
|
||||
elif [[ "$block" == d21a ]]; then
|
||||
score=$((score+25))
|
||||
elif [[ "$block" == cf2a ]]; then
|
||||
score=$((score+15))
|
||||
elif [[ "$block" == 9a8b01 ]]; then
|
||||
score=$((score+3))
|
||||
elif [[ "$block" == f11e ]]; then
|
||||
score=$((score+15))
|
||||
fi
|
||||
pkt_experience "$score"
|
||||
echo "$score" > $TEMP/players/$nick/score
|
||||
}
|
||||
|
||||
function dig_async() {
|
||||
if [[ $block == 01 ]]; then
|
||||
d=0.03
|
||||
else
|
||||
d=0.07
|
||||
fi
|
||||
for i in {1..9}; do
|
||||
pkt_blockbreak $x $y $z 0$i
|
||||
sleep $d
|
||||
if [[ $(cat $TEMP/players/$nick/mining) != "$x,$y,$z" ]]; then
|
||||
pkt_blockbreak $x $y $z ff
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $(cat $TEMP/players/$nick/mining) == "$x,$y,$z" ]]; then
|
||||
pkt_diggingack $x $y $z 00 02
|
||||
score
|
||||
fi
|
||||
}
|
||||
|
||||
function hook_dig() {
|
||||
log $x
|
||||
log $y
|
||||
log $z
|
||||
log $a
|
||||
ore=$(cat $TEMP/players/$nick/oremap | awk '{print $'"$((y+64))"'}' | sed -E 's/.{32}/&\n/g' | head -n $((z+1)) | tail -n 1 | sed -E 's/(.{16})(.{16})/\2\1/g;s/.{2}/&\n/g' | tail -n $((x+2)) | head -n1)
|
||||
block=${palette[$((0x$ore))]}
|
||||
if [[ $a == "1a02"* ]]; then # finished digging?
|
||||
score
|
||||
elif [[ $a == "1a00"* ]]; then
|
||||
echo "$x,$y,$z" > $TEMP/players/$nick/mining
|
||||
dig_async &
|
||||
elif [[ $a == "1a01"* ]]; then
|
||||
echo "catgirls" > $TEMP/players/$nick/mining
|
||||
fi
|
||||
}
|
||||
|
||||
function hook_move() {
|
||||
if [[ ${pos[1]} -lt -96 ]]; then
|
||||
# utf-8 is actually only valid for strings created in the UTF world region
|
||||
# everything else is just sparkling unicode
|
||||
pkt_disconnect "$(xxd -p -r <<< "c2af5c5c5f28e38384295f2fc2af")"
|
||||
fi
|
||||
}
|
||||
|
||||
function hook_keepalive() {
|
||||
keep_alive &
|
||||
}
|
||||
|
||||
function hook_ping() {
|
||||
json='{"version":{"name":"1.18.1","protocol":757},"players":{"max":1,"online":0,"sample":[]},"description":{"text":"Minigame: §adigmeout§r | '"$time_left"' seconds per game"},"favicon":"data:image/png;base64,'"$(base64 -w0 icon.png)"'"}'
|
||||
res="$(str_len "$json")$(echo -n "$json" | xxd -p)"
|
||||
echo "$(hexpacket_len "$res")00$res" | xxd -p -r
|
||||
}
|
||||
|
||||
function hook_inventory() {
|
||||
items=($(repeat 36 "0 "))
|
||||
items+=("721")
|
||||
log ${items[1]}
|
||||
pkt_inventory items
|
||||
}
|
31
demos/map.sh
31
demos/map.sh
|
@ -1,31 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
function hook_chunks() {
|
||||
log "hooking chunks"
|
||||
echo "ffff081f00 01 09 0a 0e 0f 15 21 00 31 00 41 42 44 45 47 49 4d 9401 8402 8602 8702 8902 00 9602 00 00 00 00 00 f60a8004" > $TEMP/world/0000000000000000
|
||||
|
||||
map=""
|
||||
for (( i=0; i<4097; i++ )); do
|
||||
map+="$(printf '%02x' $((RANDOM%15)))"
|
||||
done
|
||||
|
||||
echo "$map" >> $TEMP/world/0000000000000000
|
||||
|
||||
echo "000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001" >> $TEMP/world/0000000000000000
|
||||
|
||||
pkt_chunk FFFFFFFF FFFFFFFF
|
||||
pkt_chunk FFFFFFFF 00000000
|
||||
pkt_chunk FFFFFFFF 00000001
|
||||
|
||||
pkt_chunk 00000000 FFFFFFFF
|
||||
pkt_chunk 00000000 00000000
|
||||
pkt_chunk 00000000 00000001
|
||||
|
||||
pkt_chunk 00000001 FFFFFFFF
|
||||
pkt_chunk 00000001 00000000
|
||||
pkt_chunk 00000001 00000001
|
||||
}
|
||||
|
||||
function hook_block() {
|
||||
|
||||
}
|
60
mc.sh
60
mc.sh
|
@ -4,6 +4,7 @@ dyed=0
|
|||
keepalive=0
|
||||
pos=(0 0 0)
|
||||
players=()
|
||||
time=1609000
|
||||
TEMP=/dev/shm/witchcraft/
|
||||
mkdir -p $TEMP $TEMP/players $TEMP/world
|
||||
|
||||
|
@ -22,10 +23,16 @@ fi
|
|||
|
||||
function keep_alive() {
|
||||
while true; do
|
||||
sleep 5
|
||||
sleep 1
|
||||
log "sending keepalive"
|
||||
echo '092100000000000000ff' | xxd -p -r
|
||||
# random data
|
||||
|
||||
res=$(printf '%016x' $time)
|
||||
res=$res$res
|
||||
log time: $res
|
||||
time=$((time+240))
|
||||
echo -n "$(hexpacket_len "$res")59$res" | xxd -p -r
|
||||
done
|
||||
}
|
||||
|
||||
|
@ -106,30 +113,13 @@ while true; do
|
|||
exit
|
||||
fi
|
||||
|
||||
if [[ -f /tmp/block ]]; then
|
||||
res="$(encode_position 10 -10 10)"
|
||||
res+="01"
|
||||
|
||||
log "$res"
|
||||
echo -n "$(hexpacket_len "$res")0c$res" | xxd -p -r
|
||||
rm -R /tmp/block
|
||||
fi
|
||||
|
||||
if [[ -f /tmp/spawn ]]; then
|
||||
spawn_players
|
||||
rm /tmp/spawn
|
||||
fi
|
||||
|
||||
if [[ $a == "00"* ]]; then
|
||||
log "responding to 00; state: $state"
|
||||
|
||||
if [[ "$state" == '01' ]]; then
|
||||
log "status response"
|
||||
|
||||
#json='{"version":{"name":"1.18.1","protocol":757},"players":{"max":100,"online":5,"sample":[{"name":"uwu","id":"4566e69f-c907-48ee-8d71-d7ba5aa00d20"}]},"description":{"text":"Hello world"}}'
|
||||
json='{"version":{"name":"§a§kaaa§aUwU§kaaa","protocol":756},"players":{"max":1,"online":0,"sample":[]},"description":{"text":"§aUwU"},"favicon":"data:image/png;base64,'"$(base64 -w0 icon.png)"'"}'
|
||||
res="$(str_len "$json")$(echo -n "$json" | xxd -p)"
|
||||
echo "$(hexpacket_len "$res")00$res" | xxd -p -r
|
||||
hook_ping
|
||||
|
||||
state=''
|
||||
elif [[ "$state" == '02' ]]; then
|
||||
|
@ -137,7 +127,6 @@ while true; do
|
|||
eid=$(printf "%04x" $RANDOM | cut -c 1-4)
|
||||
mkdir -p $TEMP/players/$nick
|
||||
echo -n $eid > $TEMP/players/$nick/eid
|
||||
pkt_chatmessage "+ $nick" "00000000000000000000000000000000" > $TEMP/players/$nick/broadcast
|
||||
log "login response"
|
||||
if [[ $keepalive == 0 ]]; then
|
||||
hook_keepalive
|
||||
|
@ -149,14 +138,7 @@ while true; do
|
|||
log "$(hexpacket_len "$res")02$res"
|
||||
echo -n "$(hexpacket_len "$res")02$res" | xxd -p -r
|
||||
|
||||
|
||||
res="$(encode_position 0 0 0)"
|
||||
res+="00000000" # angle as float
|
||||
|
||||
echo -n "$(hexpacket_len "$res")4B$res" | xxd -p -r
|
||||
log "sent spawn position"
|
||||
|
||||
#res="00000000" # entity id (0 or -2147483648, idk)
|
||||
#res="$eid" # entity id
|
||||
#res+="00" # not hardcore
|
||||
#res+="00" # survival mode
|
||||
#res+="01" # ... as previously seen on Creative Mode (ignored)
|
||||
|
@ -180,24 +162,18 @@ while true; do
|
|||
|
||||
cat nbt_
|
||||
log "sent (hardcoded) join game"
|
||||
#res="$(encode_position 10 10 10)"
|
||||
#res+="00000000" # angle as float
|
||||
|
||||
# send inventory (0x14)
|
||||
res="00" # inventory id
|
||||
res+="00" # state
|
||||
res+="09" # item count
|
||||
for i in {1..9}; do
|
||||
res+="01 0$i 7f 00" # stone block
|
||||
done
|
||||
res+="01 00 01 00" # again, for held
|
||||
|
||||
echo -n "$(hexpacket_len "$res")14$res" | xxd -p -r
|
||||
log "sent inventory"
|
||||
#echo -n "$(hexpacket_len "$res")4B$res" | xxd -p -r
|
||||
#log "sent spawn position"
|
||||
|
||||
hook_inventory
|
||||
hook_chunks
|
||||
pkt_pos
|
||||
pkt_pos ${spawn_pos[0]} ${spawn_pos[1]} ${spawn_pos[2]}
|
||||
spawn_players
|
||||
|
||||
|
||||
(sleep 1; hook_start) &
|
||||
state=''
|
||||
else
|
||||
if [[ $a == *"01" ]]; then # 01 - next state: status
|
||||
|
@ -230,7 +206,7 @@ while true; do
|
|||
elif [[ $a == "13"* ]]; then
|
||||
log "received Player Rotation"
|
||||
elif [[ $a == "1a"* ]]; then
|
||||
#cut -c 3-
|
||||
decode_position $(cut -c 5-20 <<< "$a")
|
||||
hook_dig
|
||||
elif [[ $a == "2c"* ]]; then
|
||||
hook_swing
|
||||
|
|
|
@ -7,6 +7,8 @@ function chunk_header() {
|
|||
chunk+="$(int2varint ${#palette[@]})" # palette - entries amount
|
||||
|
||||
chunk+="${palette[@]}"
|
||||
|
||||
chunk+="8004" # len of next array
|
||||
}
|
||||
|
||||
function chunk_footer() {
|
||||
|
|
22
src/hooks.sh
22
src/hooks.sh
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# hooks.sh - dummy hooks functions
|
||||
|
||||
spawn_pos=(0 0 0) # default spawn position
|
||||
|
||||
# on player dig
|
||||
function hook_dig() {
|
||||
log "received Player Dig"
|
||||
|
@ -51,10 +53,30 @@ function hook_chunks() {
|
|||
pkt_chunk 00000001 00000002
|
||||
}
|
||||
|
||||
# after spawning the player
|
||||
function hook_start() {
|
||||
:
|
||||
}
|
||||
|
||||
# during login; useful for disabling all multiplayer functionality
|
||||
function hook_keepalive() {
|
||||
keep_alive &
|
||||
# sleep probably only needed for testing
|
||||
sleep 1 && position_delta &
|
||||
sleep 1 && handle_broadcast &
|
||||
pkt_chatmessage "+ $nick" "00000000000000000000000000000000" > $TEMP/players/$nick/broadcast
|
||||
}
|
||||
|
||||
# during server ping; allows you to respond with a custom message.
|
||||
function hook_ping() {
|
||||
#json='{"version":{"name":"1.18.1","protocol":757},"players":{"max":100,"online":5,"sample":[{"name":"uwu","id":"4566e69f-c907-48ee-8d71-d7ba5aa00d20"}]},"description":{"text":"Hello world"}}'
|
||||
json='{"version":{"name":"§a§kaaa§aUwU§kaaa","protocol":756},"players":{"max":1,"online":0,"sample":[]},"description":{"text":"§aUwU"},"favicon":"data:image/png;base64,'"$(base64 -w0 icon.png)"'"}'
|
||||
res="$(str_len "$json")$(echo -n "$json" | xxd -p)"
|
||||
echo "$(hexpacket_len "$res")00$res" | xxd -p -r
|
||||
}
|
||||
|
||||
# on defining inventory contents
|
||||
function hook_inventory() {
|
||||
items=()
|
||||
pkt_inventory items
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
# packet.sh - play state packets
|
||||
|
||||
# pkt_pos(x, y, z)
|
||||
function pkt_pos() {
|
||||
res="0000001000000000" # X
|
||||
res+="0000000000000000" # Y
|
||||
res+="0000000000000000" # Z
|
||||
res="$(to_ieee754 $1)" # X
|
||||
res+="$(to_ieee754 $2)" # Y
|
||||
res+="$(to_ieee754 $3)" # Z
|
||||
res+="00000000" # yaw
|
||||
res+="00000000" # pitch
|
||||
res+="00" # bit field; all absolute
|
||||
|
@ -40,7 +41,6 @@ function pkt_chunk() {
|
|||
else
|
||||
chunk_header
|
||||
|
||||
chunk+="8004" # len of next array
|
||||
l=$(echo -n "8002" | xxd -p -r | varint2int)
|
||||
|
||||
chunk+="$(repeat $((l*16)) "$fill")"
|
||||
|
@ -73,9 +73,9 @@ function pkt_effect() {
|
|||
function pkt_particle() {
|
||||
res="$(printf '%08x' $4)" # particle id
|
||||
res+="01" # long distance
|
||||
res+="0000000000000000" # X
|
||||
res+="0000000000000000" # Y
|
||||
res+="0000000000000000" # Z
|
||||
res+="$(to_ieee754 $1)" # X
|
||||
res+="$(to_ieee754 $2)" # Y
|
||||
res+="$(to_ieee754 $3)" # Z
|
||||
res+="3f800000" # X offset
|
||||
res+="3f800000" # Y offset
|
||||
res+="3f800000" # Z offset
|
||||
|
@ -84,6 +84,7 @@ function pkt_particle() {
|
|||
res+="" # data (left blank)
|
||||
echo -n "$(hexpacket_len "$res")24$res" | xxd -p -r
|
||||
|
||||
log $(to_ieee754 $1) $(to_ieee754 $2) $(to_ieee754 $3)
|
||||
|
||||
rhexlog "$res"
|
||||
log "sending particle"
|
||||
|
@ -209,3 +210,86 @@ function pkt_title() {
|
|||
res="$(str_len "$txt")$(echo -n "$txt" | xxd -p)"
|
||||
echo -n "$(hexpacket_len "$res")5a$res" | xxd -p -r
|
||||
}
|
||||
|
||||
# pkt_disconnect(reason)
|
||||
function pkt_disconnect() {
|
||||
txt='{"text":"'"$1"'"}'
|
||||
res="$(str_len "$txt")$(echo -n "$txt" | xxd -p)"
|
||||
log "$txt"
|
||||
echo -n "$(hexpacket_len "$res")1a$res" | xxd -p -r
|
||||
|
||||
pkill -P $$
|
||||
pkt_chatmessage "- $nick" "00000000000000000000000000000000" > $TEMP/players/$nick/broadcast
|
||||
sleep 0.3
|
||||
rm -R "$TEMP/players/$nick"
|
||||
exit
|
||||
}
|
||||
|
||||
# pkt_experience(lvl)
|
||||
function pkt_experience() {
|
||||
res="00000000" # experience bar
|
||||
res+="$(int2varint $1)"
|
||||
res+="00"
|
||||
echo -n "$(hexpacket_len "$res")51$res" | xxd -p -r
|
||||
}
|
||||
|
||||
# pkt_inventory(items)
|
||||
function pkt_inventory() {
|
||||
local -n _items=$1
|
||||
|
||||
res="00" # inventory id
|
||||
res+="00" # state
|
||||
res+="$(int2varint ${#_items[@]})" # item count
|
||||
for i in ${!_items[@]}; do
|
||||
if [[ $i == 0 ]]; then
|
||||
res+="00"
|
||||
else
|
||||
res+="01 $(int2varint ${_items[$i]}) 01 00"
|
||||
fi
|
||||
done
|
||||
res+="01 00 01 00"
|
||||
|
||||
echo -n "$(hexpacket_len "$res")14$res" | xxd -p -r
|
||||
log "sent inventory"
|
||||
}
|
||||
|
||||
# pkt_digginack(x, y, z, block, status)
|
||||
function pkt_diggingack() {
|
||||
res="$(encode_position $1 $2 $3)"
|
||||
res+="$4"
|
||||
res+="$5"
|
||||
res+="01"
|
||||
echo -n "$(hexpacket_len "$res")08$res" | xxd -p -r
|
||||
log "sent dig ack"
|
||||
}
|
||||
|
||||
# pkt_blockbreak(x, y, z, stage)
|
||||
function pkt_blockbreak() {
|
||||
res="$(int2varint $((0x$eid)))"
|
||||
res+="$(encode_position $1 $2 $3)"
|
||||
res+="$4"
|
||||
echo -n "$(hexpacket_len "$res")09$res" | xxd -p -r
|
||||
}
|
||||
|
||||
# pkt_soundeffect(x, y, z, id)
|
||||
# TODO: unbreak this
|
||||
function pkt_soundeffect() {
|
||||
res="$(int2varint $4)" # sound ID
|
||||
res+="05" # "block" category
|
||||
res+="$(printf '%08x' $(($1*8)))" # x
|
||||
res+="$(printf '%08x' $(($2*8)))" # y
|
||||
res+="$(printf '%08x' $(($3*8)))" # z
|
||||
res+="3f800000" # volume
|
||||
res+="3f800000" # pitch
|
||||
|
||||
echo -n "$(hexpacket_len "$res")5d$res" | xxd -p -r
|
||||
log "sound $(hexpacket_len "$res")5d$res"
|
||||
}
|
||||
|
||||
# pkt_sendblock(x, y, z, id)
|
||||
function pkt_sendblock() {
|
||||
res="$(encode_position $1 $2 $3)"
|
||||
res+="$(int2varint $4)"
|
||||
|
||||
echo -n "$(hexpacket_len "$res")0c$res" | xxd -p -r
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue