put newfound gddocs info to use

fun fact: this exists https://docs.gdprogra.me/

:slugclose:
This commit is contained in:
Jill 2023-01-03 08:58:24 +03:00
parent 09ff7b4800
commit 46a4d06983
10 changed files with 117 additions and 81 deletions

View File

@ -21,7 +21,8 @@ CREATE TABLE levels (
extra_data BLOB NOT NULL, extra_data BLOB NOT NULL,
level_info BLOB NOT NULL, level_info BLOB NOT NULL,
-- checksums, presumably -- times spent in the editor
-- wt1 doesn't count copies, wt2 does
wt1 TEXT NOT NULL, wt1 TEXT NOT NULL,
wt2 TEXT NOT NULL, wt2 TEXT NOT NULL,

View File

@ -9,7 +9,7 @@ CrystalGauntlet.endpoints["/downloadGJLevel22.php"] = ->(body : String): String
response = [] of String response = [] of String
DATABASE.query("select levels.id, levels.name, levels.level_data, levels.extra_data, levels.level_info, levels.password, levels.user_id, levels.description, levels.original, levels.game_version, levels.requested_stars, levels.version, levels.song_id, levels.length, levels.objects, levels.coins, levels.has_ldm, levels.two_player, levels.downloads, levels.likes, levels.difficulty, levels.community_difficulty, levels.demon_difficulty, levels.stars, levels.featured, levels.epic, levels.rated_coins, users.username, users.udid, users.account_id, users.registered from levels join users on levels.user_id = users.id where levels.id = ?", params["levelID"].to_i32) do |rs| DATABASE.query("select levels.id, levels.name, levels.level_data, levels.extra_data, levels.level_info, levels.password, levels.user_id, levels.description, levels.original, levels.game_version, levels.requested_stars, levels.version, levels.song_id, levels.length, levels.objects, levels.coins, levels.has_ldm, levels.two_player, levels.downloads, levels.likes, levels.difficulty, levels.community_difficulty, levels.demon_difficulty, levels.stars, levels.featured, levels.epic, levels.rated_coins, users.username, users.udid, users.account_id, users.registered, wt1, wt2 from levels join users on levels.user_id = users.id where levels.id = ?", params["levelID"].to_i32) do |rs|
if rs.move_next if rs.move_next
id = rs.read(Int32) id = rs.read(Int32)
name = rs.read(String) name = rs.read(String)
@ -48,6 +48,9 @@ CrystalGauntlet.endpoints["/downloadGJLevel22.php"] = ->(body : String): String
user_account_id = rs.read(Int32 | Nil) user_account_id = rs.read(Int32 | Nil)
user_registered = rs.read(Bool) user_registered = rs.read(Bool)
wt1 = rs.read(String)
wt2 = rs.read(String)
xor_pass = "0" xor_pass = "0"
if !password if !password
password = "0" password = "0"
@ -65,36 +68,47 @@ CrystalGauntlet.endpoints["/downloadGJLevel22.php"] = ->(body : String): String
4 => level_data, 4 => level_data,
5 => version, 5 => version,
6 => user_id, 6 => user_id,
# this is suppoused to be the amount of people who have
# voted on a level, but this is unused by the game, so
# we just always tell the game 10 people have voted
8 => 10, 8 => 10,
9 => difficulty ? difficulty.to_star_difficulty : 0, # 0=N/A 10=EASY 20=NORMAL 30=HARD 40=HARDER 50=INSANE 50=AUTO 50=DEMON # 0=N/A 10=EASY 20=NORMAL 30=HARD 40=HARDER 50=INSANE 50=AUTO 50=DEMON
# divided by above value, which is why its multiplied by 10
9 => (difficulty ? difficulty.to_star_difficulty : 0).not_nil! * 10,
10 => downloads, 10 => downloads,
11 => 1,
12 => !Songs.is_custom_song(song_id) ? song_id : 0, 12 => !Songs.is_custom_song(song_id) ? song_id : 0,
13 => game_version, 13 => game_version,
# likes - dislikes
14 => likes, 14 => likes,
# dislikes - likes
16 => -likes,
15 => length,
17 => difficulty && difficulty.demon?, 17 => difficulty && difficulty.demon?,
# 0 for n/a, 10 for easy, 20, for medium, ...
43 => (demon_difficulty || DemonDifficulty::Hard).to_demon_difficulty,
25 => difficulty && difficulty.auto?,
18 => stars || 0, 18 => stars || 0,
19 => featured, 19 => featured,
42 => epic, 25 => difficulty && difficulty.auto?,
45 => objects, 27 => xor_pass,
15 => length, # todo
30 => original || 0, # upload date
31 => two_player,
28 => "1", 28 => "1",
# update date
29 => "1", 29 => "1",
30 => original || 0,
31 => two_player,26 => params.has_key?("extras") ? level_info : nil,
35 => Songs.is_custom_song(song_id) ? song_id : 0, 35 => Songs.is_custom_song(song_id) ? song_id : 0,
36 => extra_data, 36 => extra_data,
37 => coins, 37 => coins,
38 => rated_coins, 38 => rated_coins,
39 => requested_stars || 0, 39 => requested_stars || 0,
46 => 1,
47 => 2,
40 => has_ldm, 40 => has_ldm,
27 => xor_pass, 42 => epic,
26 => params.has_key?("extras") ? level_info : nil # 0 for n/a, 10 for easy, 20, for medium, ...
43 => (demon_difficulty || DemonDifficulty::Hard).to_demon_difficulty,
# todo
44 => false,
45 => objects,
46 => wt1,
47 => wt2
}) })
response << Hashes.gen_solo(level_data) response << Hashes.gen_solo(level_data)

View File

@ -38,31 +38,30 @@ CrystalGauntlet.endpoints["/getGJComments21.php"] = ->(body : String): String {
special = rs.read(Int32) special = rs.read(Int32)
comment_str = Format.fmt_comment({ users_str << [
2 => GDBase64.encode(comment), Format.fmt_comment({
3 => user_id, 2 => GDBase64.encode(comment),
4 => likes, 3 => user_id,
5 => 0, 4 => likes,
7 => likes < -3, 5 => 0,
9 => Time.parse(created_at, Format::TIME_FORMAT, Time::Location::UTC), 6 => id,
6 => id, 7 => likes < -3,
10 => percent || 0, 8 => account_id,
12 => "0,0,0", # todo: badge 9 => Time.parse(created_at, Format::TIME_FORMAT, Time::Location::UTC),
11 => "0", 10 => percent || 0,
}) 11 => "0",
12 => "0,0,0", # todo: badge
comment_str += ":" + Format.fmt_comment({ }),
1 => username || "-", Format.fmt_comment({
7 => 1, 1 => username || "-",
9 => icon_value, 9 => icon_value,
10 => color1, 10 => color1,
11 => color2, 11 => color2,
14 => icon_type, 14 => icon_type,
15 => special, 15 => special,
16 => account_id || udid 16 => account_id || udid
}) })
].join(":")
users_str << comment_str
end end
end end

View File

@ -182,7 +182,7 @@ CrystalGauntlet.endpoints["/getGJLevels21.php"] = ->(body : String): String {
hash_data = [] of Tuple(Int32, Int32, Bool) hash_data = [] of Tuple(Int32, Int32, Bool)
# fucking help # fucking help
DATABASE.query_all("select levels.id, levels.name, levels.user_id, levels.description, levels.original, levels.game_version, levels.requested_stars, levels.version, levels.song_id, levels.length, levels.objects, levels.coins, levels.has_ldm, levels.two_player, levels.downloads, levels.likes, levels.difficulty, levels.community_difficulty, levels.demon_difficulty, levels.stars, levels.featured, levels.epic, levels.rated_coins, users.username, users.udid, users.account_id, users.registered #{query_base} limit #{levels_per_page} offset #{page_offset}", as: {Int32, String, Int32, String, Int32 | Nil, Int32, Int32 | Nil, Int32, Int32, Int32, Int32, Int32, Bool, Bool, Int32, Int32, Int32 | Nil, Int32 | Nil, Int32 | Nil, Int32 | Nil, Bool, Bool, Bool, String, String | Nil, Int32 | Nil, Bool}).map() do |id, name, user_id, description, original, game_version, requested_stars, version, song_id, length, objects, coins, has_ldm, two_player, downloads, likes, set_difficulty_int, community_difficulty_int, demon_difficulty_int, stars, featured, epic, rated_coins, user_username, user_udid, user_account_id, user_registered| DATABASE.query_all("select levels.id, levels.name, levels.user_id, levels.description, levels.original, levels.game_version, levels.requested_stars, levels.version, levels.song_id, levels.length, levels.objects, levels.coins, levels.has_ldm, levels.two_player, levels.downloads, levels.likes, levels.difficulty, levels.community_difficulty, levels.demon_difficulty, levels.stars, levels.featured, levels.epic, levels.rated_coins, users.username, users.udid, users.account_id, users.registered, wt1, wt2 #{query_base} limit #{levels_per_page} offset #{page_offset}", as: {Int32, String, Int32, String, Int32 | Nil, Int32, Int32 | Nil, Int32, Int32, Int32, Int32, Int32, Bool, Bool, Int32, Int32, Int32 | Nil, Int32 | Nil, Int32 | Nil, Int32 | Nil, Bool, Bool, Bool, String, String | Nil, Int32 | Nil, Bool, String, String}).map() do |id, name, user_id, description, original, game_version, requested_stars, version, song_id, length, objects, coins, has_ldm, two_player, downloads, likes, set_difficulty_int, community_difficulty_int, demon_difficulty_int, stars, featured, epic, rated_coins, user_username, user_udid, user_account_id, user_registered, wt1, wt2|
set_difficulty = set_difficulty_int && LevelDifficulty.new(set_difficulty_int) set_difficulty = set_difficulty_int && LevelDifficulty.new(set_difficulty_int)
community_difficulty = community_difficulty_int && LevelDifficulty.new(community_difficulty_int) community_difficulty = community_difficulty_int && LevelDifficulty.new(community_difficulty_int)
difficulty = set_difficulty || community_difficulty difficulty = set_difficulty || community_difficulty
@ -192,33 +192,44 @@ CrystalGauntlet.endpoints["/getGJLevels21.php"] = ->(body : String): String {
results << Format.fmt_hash({ results << Format.fmt_hash({
1 => id, 1 => id,
2 => name, 2 => name,
3 => GDBase64.encode(description),
5 => version, 5 => version,
6 => user_id, 6 => user_id,
# this is suppoused to be the amount of people who have
# voted on a level, but this is unused by the game, so
# we just always tell the game 10 people have voted
8 => 10, 8 => 10,
9 => difficulty ? difficulty.to_star_difficulty : 0, # 0=N/A 10=EASY 20=NORMAL 30=HARD 40=HARDER 50=INSANE 50=AUTO 50=DEMON # 0=N/A 10=EASY 20=NORMAL 30=HARD 40=HARDER 50=INSANE 50=AUTO 50=DEMON
# divided by above value, which is why its multiplied by 10
9 => (difficulty ? difficulty.to_star_difficulty : 0).not_nil! * 10,
10 => downloads, 10 => downloads,
12 => !Songs.is_custom_song(song_id) ? song_id : 0, 12 => !Songs.is_custom_song(song_id) ? song_id : 0,
13 => game_version, 13 => game_version,
# likes - dislikes
14 => likes, 14 => likes,
# dislikes - likes
16 => -likes,
15 => length,
17 => difficulty && difficulty.demon?, 17 => difficulty && difficulty.demon?,
# 0 for n/a, 10 for easy, 20, for medium, ...
43 => (demon_difficulty || DemonDifficulty::Hard).to_demon_difficulty,
25 => difficulty && difficulty.auto?,
18 => stars || 0, 18 => stars || 0,
19 => featured, 19 => featured,
42 => epic, # 0 for n/a, 10 for easy, 20, for medium, ...
45 => objects, 25 => difficulty && difficulty.auto?,
3 => GDBase64.encode(description),
15 => length,
30 => original || 0, 30 => original || 0,
31 => two_player, 31 => two_player,
35 => Songs.is_custom_song(song_id) ? song_id : 0,
37 => coins, 37 => coins,
38 => rated_coins, 38 => rated_coins,
39 => requested_stars || 0, 39 => requested_stars || 0,
46 => 1,
47 => 2,
40 => has_ldm, 40 => has_ldm,
35 => Songs.is_custom_song(song_id) ? song_id : 0, 42 => epic,
43 => (demon_difficulty || DemonDifficulty::Hard).to_demon_difficulty,
# is in gauntlet
# todo
44 => false,
45 => objects,
46 => wt1,
47 => wt2
}) })
users << "#{user_id}:#{user_username}:#{user_registered ? user_account_id : user_udid}" users << "#{user_id}:#{user_username}:#{user_registered ? user_account_id : user_udid}"

View File

@ -44,6 +44,8 @@ CrystalGauntlet.endpoints["/uploadGJLevel21.php"] = ->(body : String): String {
# todo: verify object count, coins and twoplayer (i'm sure it's possible) # todo: verify object count, coins and twoplayer (i'm sure it's possible)
# todo: check seed2?
if DATABASE.scalar("select count(*) from levels where id = ? and user_id = ?", params["levelID"], params["accountID"]).as(Int64) > 0 if DATABASE.scalar("select count(*) from levels where id = ? and user_id = ?", params["levelID"], params["accountID"]).as(Int64) > 0
# update existing level # update existing level
# todo # todo

View File

@ -24,10 +24,10 @@ CrystalGauntlet.endpoints["/getGJSongInfo.php"] = ->(body : String): String {
3 => song_author_id, 3 => song_author_id,
4 => song_author_name, 4 => song_author_name,
5 => (song_size || 0) / (1000 * 1000), 5 => (song_size || 0) / (1000 * 1000),
6 => "", 6 => "", # yt video id; unused i think?
7 => "", # yt video url; unused also??
8 => "1", # if the song is verified/scouted
10 => song_download || "", 10 => song_download || "",
7 => "",
8 => "1"
}) })
end end
else else

View File

@ -27,10 +27,10 @@ CrystalGauntlet.endpoints["/getGJAccountComments20.php"] = ->(body : String): St
2 => Base64.encode(comment).strip("\n"), 2 => Base64.encode(comment).strip("\n"),
3 => account_id, 3 => account_id,
4 => likes, 4 => likes,
5 => 0, 5 => 0, # dislikes; unused
6 => id,
7 => likes < -3, # todo: config? 7 => likes < -3, # todo: config?
9 => Time.parse(created_at, Format::TIME_FORMAT, Time::Location::UTC), 9 => Time.parse(created_at, Format::TIME_FORMAT, Time::Location::UTC),
6 => id
}) })
end end
end end

View File

@ -43,17 +43,17 @@ CrystalGauntlet.endpoints["/getGJUserInfo20.php"] = ->(body : String): String {
return CrystalGauntlet::Format.fmt_hash({ return CrystalGauntlet::Format.fmt_hash({
1 => username, 1 => username,
2 => user_id, 2 => user_id,
13 => coins,
17 => user_coins,
10 => color1,
11 => color2,
3 => stars, 3 => stars,
46 => diamonds,
4 => demons, 4 => demons,
8 => creator_points, 8 => creator_points,
10 => color1,
11 => color2,
13 => coins,
16 => id,
17 => user_coins,
# todo: messages can actually be disabled for _everyone_; this is actually an enum (0: all, 1: only friends, 2: none)
18 => !messages_enabled, 18 => !messages_enabled,
19 => !friend_requests_enabled, 19 => !friend_requests_enabled,
50 => !comments_enabled,
20 => youtube_url || "", 20 => youtube_url || "",
21 => cube, 21 => cube,
22 => ship, 22 => ship,
@ -62,10 +62,9 @@ CrystalGauntlet.endpoints["/getGJUserInfo20.php"] = ->(body : String): String {
25 => wave, 25 => wave,
26 => robot, 26 => robot,
28 => glow, 28 => glow,
43 => spider, # registered or not; always 1 here
47 => explosion, 29 => 1,
30 => 1, # rank; todo 30 => 1, # rank; todo
16 => id,
# 31 = isnt (0) or is (1) friend or (3) incoming request or (4) outgoing request # 31 = isnt (0) or is (1) friend or (3) incoming request or (4) outgoing request
# todo # todo
31 => 0, 31 => 0,
@ -73,11 +72,21 @@ CrystalGauntlet.endpoints["/getGJUserInfo20.php"] = ->(body : String): String {
# 32 => id, # 32 => id,
# 35 => comment, # 35 => comment,
# 37 => date, # 37 => date,
# todo: how many messages you have; exclusive to if you're viewing your own profile
38 => 0,
# todo: above, but friend requests
39 => 0,
# todo: above: but how many new friends the user has
40 => 0,
43 => spider,
44 => twitter_url || "", 44 => twitter_url || "",
45 => twitch_url || "", 45 => twitch_url || "",
29 => 1, 46 => diamonds,
48 => explosion,
# badge, todo # badge, todo
49 => 0 49 => 0,
# todo: this is actually also an enum (0: all, 1: only friends, 2: none)
50 => !comments_enabled,
}) })
else else
"-1" "-1"

View File

@ -32,17 +32,17 @@ CrystalGauntlet.endpoints["/getGJUsers20.php"] = ->(body : String): String {
results << Format.fmt_hash({ results << Format.fmt_hash({
1 => username, 1 => username,
2 => id, 2 => id,
13 => coins, 3 => stars,
17 => user_coins, 4 => demons,
8 => creator_points,
9 => icon_value, 9 => icon_value,
10 => color1, 10 => color1,
11 => color2, 11 => color2,
13 => coins,
14 => icon_type, 14 => icon_type,
15 => special, 15 => special,
16 => account_id || udid, 16 => account_id || udid,
3 => stars, 17 => user_coins,
8 => creator_points,
4 => demons
}) })
end end
end end

View File

@ -19,19 +19,19 @@ module CrystalGauntlet
def to_star_difficulty def to_star_difficulty
case self case self
when .auto? when .auto?
50 5
when .easy? when .easy?
10 1
when .normal? when .normal?
20 2
when .hard? when .hard?
30 3
when .harder? when .harder?
40 4
when .insane? when .insane?
50 5
when .demon? when .demon?
50 5
end end
end end
end end