+ digmeout minigame, usability fixes

meow
Dominika 2022-02-14 01:54:31 +01:00
parent 4bdc24558e
commit 59d995019d
6 changed files with 314 additions and 81 deletions

180
demos/digmeout.sh Normal file
View File

@ -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
}

View File

@ -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() {
}

62
mc.sh
View File

@ -4,6 +4,7 @@ dyed=0
keepalive=0 keepalive=0
pos=(0 0 0) pos=(0 0 0)
players=() players=()
time=1609000
TEMP=/dev/shm/witchcraft/ TEMP=/dev/shm/witchcraft/
mkdir -p $TEMP $TEMP/players $TEMP/world mkdir -p $TEMP $TEMP/players $TEMP/world
@ -22,10 +23,16 @@ fi
function keep_alive() { function keep_alive() {
while true; do while true; do
sleep 5 sleep 1
log "sending keepalive" log "sending keepalive"
echo '092100000000000000ff' | xxd -p -r echo '092100000000000000ff' | xxd -p -r
# random data # 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 done
} }
@ -106,30 +113,13 @@ while true; do
exit exit
fi 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 if [[ $a == "00"* ]]; then
log "responding to 00; state: $state" log "responding to 00; state: $state"
if [[ "$state" == '01' ]]; then if [[ "$state" == '01' ]]; then
log "status response" 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"}}' hook_ping
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
state='' state=''
elif [[ "$state" == '02' ]]; then elif [[ "$state" == '02' ]]; then
@ -137,7 +127,6 @@ while true; do
eid=$(printf "%04x" $RANDOM | cut -c 1-4) eid=$(printf "%04x" $RANDOM | cut -c 1-4)
mkdir -p $TEMP/players/$nick mkdir -p $TEMP/players/$nick
echo -n $eid > $TEMP/players/$nick/eid echo -n $eid > $TEMP/players/$nick/eid
pkt_chatmessage "+ $nick" "00000000000000000000000000000000" > $TEMP/players/$nick/broadcast
log "login response" log "login response"
if [[ $keepalive == 0 ]]; then if [[ $keepalive == 0 ]]; then
hook_keepalive hook_keepalive
@ -149,14 +138,7 @@ while true; do
log "$(hexpacket_len "$res")02$res" log "$(hexpacket_len "$res")02$res"
echo -n "$(hexpacket_len "$res")02$res" | xxd -p -r echo -n "$(hexpacket_len "$res")02$res" | xxd -p -r
#res="$eid" # entity id
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+="00" # not hardcore #res+="00" # not hardcore
#res+="00" # survival mode #res+="00" # survival mode
#res+="01" # ... as previously seen on Creative Mode (ignored) #res+="01" # ... as previously seen on Creative Mode (ignored)
@ -179,25 +161,19 @@ while true; do
#log "sent join game" #log "sent join game"
cat nbt_ cat nbt_
log "sent (hardcoded) join game" log "sent (hardcoded) join game"
#res="$(encode_position 10 10 10)"
# send inventory (0x14) #res+="00000000" # angle as float
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 #echo -n "$(hexpacket_len "$res")4B$res" | xxd -p -r
log "sent inventory" #log "sent spawn position"
hook_inventory
hook_chunks hook_chunks
pkt_pos pkt_pos ${spawn_pos[0]} ${spawn_pos[1]} ${spawn_pos[2]}
spawn_players spawn_players
(sleep 1; hook_start) &
state='' state=''
else else
if [[ $a == *"01" ]]; then # 01 - next state: status if [[ $a == *"01" ]]; then # 01 - next state: status
@ -230,7 +206,7 @@ while true; do
elif [[ $a == "13"* ]]; then elif [[ $a == "13"* ]]; then
log "received Player Rotation" log "received Player Rotation"
elif [[ $a == "1a"* ]]; then elif [[ $a == "1a"* ]]; then
#cut -c 3- decode_position $(cut -c 5-20 <<< "$a")
hook_dig hook_dig
elif [[ $a == "2c"* ]]; then elif [[ $a == "2c"* ]]; then
hook_swing hook_swing

View File

@ -7,6 +7,8 @@ function chunk_header() {
chunk+="$(int2varint ${#palette[@]})" # palette - entries amount chunk+="$(int2varint ${#palette[@]})" # palette - entries amount
chunk+="${palette[@]}" chunk+="${palette[@]}"
chunk+="8004" # len of next array
} }
function chunk_footer() { function chunk_footer() {

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# hooks.sh - dummy hooks functions # hooks.sh - dummy hooks functions
spawn_pos=(0 0 0) # default spawn position
# on player dig # on player dig
function hook_dig() { function hook_dig() {
log "received Player Dig" log "received Player Dig"
@ -51,10 +53,30 @@ function hook_chunks() {
pkt_chunk 00000001 00000002 pkt_chunk 00000001 00000002
} }
# after spawning the player
function hook_start() {
:
}
# during login; useful for disabling all multiplayer functionality # during login; useful for disabling all multiplayer functionality
function hook_keepalive() { function hook_keepalive() {
keep_alive & keep_alive &
# sleep probably only needed for testing # sleep probably only needed for testing
sleep 1 && position_delta & sleep 1 && position_delta &
sleep 1 && handle_broadcast & 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
} }

View File

@ -1,10 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# packet.sh - play state packets # packet.sh - play state packets
# pkt_pos(x, y, z)
function pkt_pos() { function pkt_pos() {
res="0000001000000000" # X res="$(to_ieee754 $1)" # X
res+="0000000000000000" # Y res+="$(to_ieee754 $2)" # Y
res+="0000000000000000" # Z res+="$(to_ieee754 $3)" # Z
res+="00000000" # yaw res+="00000000" # yaw
res+="00000000" # pitch res+="00000000" # pitch
res+="00" # bit field; all absolute res+="00" # bit field; all absolute
@ -40,7 +41,6 @@ function pkt_chunk() {
else else
chunk_header chunk_header
chunk+="8004" # len of next array
l=$(echo -n "8002" | xxd -p -r | varint2int) l=$(echo -n "8002" | xxd -p -r | varint2int)
chunk+="$(repeat $((l*16)) "$fill")" chunk+="$(repeat $((l*16)) "$fill")"
@ -73,9 +73,9 @@ function pkt_effect() {
function pkt_particle() { function pkt_particle() {
res="$(printf '%08x' $4)" # particle id res="$(printf '%08x' $4)" # particle id
res+="01" # long distance res+="01" # long distance
res+="0000000000000000" # X res+="$(to_ieee754 $1)" # X
res+="0000000000000000" # Y res+="$(to_ieee754 $2)" # Y
res+="0000000000000000" # Z res+="$(to_ieee754 $3)" # Z
res+="3f800000" # X offset res+="3f800000" # X offset
res+="3f800000" # Y offset res+="3f800000" # Y offset
res+="3f800000" # Z offset res+="3f800000" # Z offset
@ -84,6 +84,7 @@ function pkt_particle() {
res+="" # data (left blank) res+="" # data (left blank)
echo -n "$(hexpacket_len "$res")24$res" | xxd -p -r echo -n "$(hexpacket_len "$res")24$res" | xxd -p -r
log $(to_ieee754 $1) $(to_ieee754 $2) $(to_ieee754 $3)
rhexlog "$res" rhexlog "$res"
log "sending particle" log "sending particle"
@ -209,3 +210,86 @@ function pkt_title() {
res="$(str_len "$txt")$(echo -n "$txt" | xxd -p)" res="$(str_len "$txt")$(echo -n "$txt" | xxd -p)"
echo -n "$(hexpacket_len "$res")5a$res" | xxd -p -r 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
}