This commit is contained in:
WoolyAypa
2023-04-26 16:12:15 -03:00
77 changed files with 1535 additions and 476 deletions
+2 -2
View File
@@ -199,7 +199,7 @@
aroused_state = FALSE
/obj/item/organ/genital/proc/generate_fluid(datum/reagents/R)
var/amount = clamp((fluid_rate * ((world.time - last_orgasmed) / (10 SECONDS)) * fluid_mult),0,fluid_max_volume)
var/amount = get_fluid()
R.clear_reagents()
R.maximum_volume = fluid_max_volume
if(fluid_id)
@@ -338,7 +338,7 @@
var/obj/item/organ/genital/G = A
var/datum/sprite_accessory/S
var/size = G.size
var/size = G.size_to_state()
switch(G.type)
if(/obj/item/organ/genital/penis)
S = GLOB.cock_shapes_list[G.shape]
+42 -48
View File
@@ -8,7 +8,7 @@
icon = 'icons/obj/genitals/breasts.dmi'
zone = BODY_ZONE_CHEST
slot = ORGAN_SLOT_BREASTS
size = BREASTS_SIZE_DEF // "c". Refer to the breast_values static list below for the cups associated number values
size = 3
fluid_id = /datum/reagent/consumable/milk
fluid_rate = MILK_RATE
shape = DEF_BREASTS_SHAPE
@@ -19,19 +19,12 @@
orgasm_verb = "leaking"
fluid_transfer_factor = 0.5
layer_index = BREASTS_LAYER_INDEX
var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "massive" = 17, "giga" = 25, "impossible" = 30, "flat" = 0)
var/cached_size //these two vars pertain size modifications and so should be expressed in NUMBERS.
var/prev_size //former cached_size value, to allow update_size() to early return should be there no significant changes.
/obj/item/organ/genital/breasts/Initialize(mapload, do_update = TRUE)
if(do_update)
cached_size = breast_values[size]
prev_size = cached_size
return ..()
/obj/item/organ/genital/breasts/update_appearance()
. = ..()
var/lowershape = lowertext(shape)
var/size_state = size_to_state()
switch(lowershape)
if("pair")
desc = "You see a pair of breasts."
@@ -41,13 +34,13 @@
desc = "You see three sets of breasts, running from their chest to their belly."
else
desc = "You see some breasts, they seem to be quite exotic."
if(size == "huge")
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size*(owner ? get_size(owner) : 1))]cm in diameter."
if(size_state == "huge")
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(size*(owner ? get_size(owner) : 1))]cm in diameter."
else
if (size == "flat")
if (size_state == "flat")
desc += " They're very small and flatchested, however."
else
desc += " You estimate that they're [uppertext(size)]-cups."
desc += " You estimate that they're [uppertext(size_state)]-cups."
if((genital_flags & GENITAL_FUID_PRODUCTION) && aroused_state)
var/datum/reagent/R = GLOB.chemical_reagents_list[fluid_id]
@@ -55,7 +48,7 @@
desc += " They're leaking [lowertext(R.name)]."
var/datum/sprite_accessory/S = GLOB.breasts_shapes_list[shape]
var/icon_shape = S ? S.icon_state : "pair"
var/icon_size = clamp(breast_values[size], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
var/icon_size = clamp(GLOB.breast_values[size_state], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
icon_state = "breasts_[icon_shape]_[icon_size]"
if(owner)
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
@@ -74,45 +67,49 @@
//this is far too lewd wah
/obj/item/organ/genital/breasts/modify_size(modifier, min = -INFINITY, max = INFINITY)
var/new_value = clamp(cached_size + modifier, min, max)
if(new_value == cached_size)
var/new_value = clamp(size + modifier, max(min, min_size ? min_size : -INFINITY), min(max_size ? max_size : INFINITY, max))
if(new_value == size)
return
prev_size = cached_size
cached_size = new_value
prev_size = size
size = new_value
update()
..()
/obj/item/organ/genital/breasts/size_to_state()
var/str_size
switch(size)
if(0) //flatchested
str_size = "flat"
if(1 to 8) //modest
str_size = GLOB.breast_values[size]
if(9 to 15) //massive
str_size = GLOB.breast_values[size]
if(16 to 17) //ridiculous
str_size = GLOB.breast_values[size]
if(18 to 24) //AWOOOOGAAAAAAA
str_size = "massive"
if(25 to 29) //AWOOOOOOGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
str_size = "giga"
if(30 to INFINITY) //AWWWWWWWWWWWWWOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOGGGGGAAAAAAAAAAAAAAAAAAAAAA
str_size = "impossible"
return str_size
/obj/item/organ/genital/breasts/update_size()//wah
var/rounded_cached = round(cached_size)
if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
var/rounded_size = round(size)
var/size_state = size_to_state()
if(rounded_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
if(owner)
to_chat(owner, "<span class='warning'>You feel your breasts shrinking away from your body as your chest flattens out.</span>")
QDEL_IN(src, 1)
return
switch(rounded_cached)
if(0) //flatchested
size = "flat"
if(1 to 8) //modest
size = breast_values[rounded_cached]
if(9 to 15) //massive
size = breast_values[rounded_cached]
if(16 to 17) //ridiculous
size = breast_values[rounded_cached]
if(18 to 24) //AWOOOOGAAAAAAA
size = "massive"
if(25 to 29) //AWOOOOOOGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
size = "giga"
if(30 to INFINITY) //AWWWWWWWWWWWWWOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOGGGGGAAAAAAAAAAAAAAAAAAAAAA
size = "impossible"
if((rounded_cached < 18 || rounded_cached == 25 || rounded_cached == 30) && owner )//Because byond doesn't count from 0, I have to do this.
if((rounded_size < 18 || rounded_size == 25 || rounded_size == 30) && owner )//Because byond doesn't count from 0, I have to do this.
var/mob/living/carbon/human/H = owner
var/r_prev_size = round(prev_size)
if (rounded_cached > r_prev_size)
to_chat(H, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.</span>")
else if (rounded_cached < r_prev_size)
to_chat(H, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.</span>")
if (rounded_size > r_prev_size)
to_chat(H, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size_state)]-cup.</span>")
else if (rounded_size < r_prev_size)
to_chat(H, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size_state)]-cup.</span>")
/obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H)
var/datum/dna/D = H.dna
@@ -120,16 +117,13 @@
color = SKINTONE2HEX(H.skin_tone)
else
color = "#[D.features["breasts_color"]]"
size = D.features["breasts_size"]
size = GLOB.breast_values[D.features["breasts_size"]]
max_size = D.features["breasts_max_size"]
min_size = D.features["breasts_min_size"]
shape = D.features["breasts_shape"]
if(!D.features["breasts_producing"])
genital_flags &= ~ (GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
if(!isnum(size))
cached_size = breast_values[size]
else
cached_size = size
size = breast_values[size]
prev_size = cached_size
prev_size = size
toggle_visibility(D.features["breasts_visibility"], FALSE)
if(D.features["breasts_stuffing"])
toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE)
+5 -2
View File
@@ -7,6 +7,7 @@
slot = ORGAN_SLOT_BUTT
w_class = 3
size = 0
max_size = BUTT_SIZE_MAX
var/size_name = "nonexistent"
shape = "Pair" //turn this into a default constant if for some inexplicable reason we get more than one butt type but I doubt it.
genital_flags = UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN|CAN_CUM_INTO|HAS_EQUIPMENT
@@ -15,8 +16,8 @@
var/prev_size //former size value, to allow update_size() to early return should be there no significant changes.
layer_index = BUTT_LAYER_INDEX
/obj/item/organ/genital/butt/modify_size(modifier, min = -INFINITY, max = BUTT_SIZE_MAX)
var/new_value = clamp(size_cached + modifier, min, max)
/obj/item/organ/genital/butt/modify_size(modifier, min = -INFINITY, max = INFINITY)
var/new_value = clamp(size_cached + modifier, max(min, min_size ? min_size : -INFINITY), min(max_size ? max_size : INFINITY, max))
if(new_value == size_cached)
return
prev_size = size_cached
@@ -88,6 +89,8 @@
else
color = "#[D.features["butt_color"]]"
size = D.features["butt_size"]
max_size = D.features["butt_max_size"]
min_size = D.features["butt_min_size"]
prev_size = size
size_cached = size
toggle_visibility(D.features["butt_visibility"], FALSE)
+7 -3
View File
@@ -14,18 +14,20 @@
shape = DEF_COCK_SHAPE
size = 2 //arbitrary value derived from length and diameter for sprites.
layer_index = PENIS_LAYER_INDEX
var/length = 6 //inches
var/length = 6 //inches
var/max_length = 9
var/min_length = 2
var/prev_length = 6 //really should be renamed to prev_length
var/diameter = 4.38
var/diameter_ratio = COCK_DIAMETER_RATIO_DEF //0.25; check citadel_defines.dm
/obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY)
var/new_value = clamp(length + modifier, min, max)
var/new_value = clamp(length + modifier, max(min, min_size ? min_size : -INFINITY), min(max_length ? max_length : INFINITY, max))
if(new_value == length)
return
prev_length = length
length = clamp(length + modifier, min, max)
length = new_value
update()
..()
@@ -95,6 +97,8 @@
else
color = "#[D.features["cock_color"]]"
length = D.features["cock_length"]
max_length = D.features["cock_max_length"]
min_length = D.features["cock_min_length"]
diameter_ratio = D.features["cock_diameter_ratio"]
shape = D.features["cock_shape"]
prev_length = length
+115 -28
View File
@@ -844,6 +844,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
tauric_shape = TRUE
dat += "<b>Penis Shape:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_shape;task=input'>[features["cock_shape"]][tauric_shape ? " (Taur)" : ""]</a>"
dat += "<b>Penis Length:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_length;task=input'>[features["cock_length"]] inch(es)</a>"
dat += "<b>Max Length:</b><a style='display:block;width:120px' href='?_src_=prefs;preference=cock_max_length;task=input'>[features["cock_max_length"] ? features["cock_max_length"] : "Disabled"]</a>"
dat += "<b>Min Length:</b><a style='display:block;width:120px' href='?_src_=prefs;preference=cock_min_length;task=input'>[features["cock_min_length"] ? features["cock_min_length"] : "Disabled"]</a>"
dat += "<b>Diameter Ratio:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_diameter_ratio;task=input'>[features["cock_diameter_ratio"]]</a>" //SPLURT Edit
dat += "<b>Penis Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=cock_visibility;task=input'>[features["cock_visibility"]]</a>"
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=cock_stuffing'>[features["cock_stuffing"] == TRUE ? "Yes" : "No"]</a>" //SPLURT Edit
@@ -859,6 +861,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Testicles Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=balls_visibility;task=input'>[features["balls_visibility"]]</a>"
//SPLURT Edit
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_stuffing'>[features["balls_stuffing"] == TRUE ? "Yes" : "No"]</a>"
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_max_size;task=input'>[features["balls_max_size"] ? features["balls_max_size"] : "Disabled"]</a>"
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_min_size;task=input'>[features["balls_min_size"] ? features["balls_min_size"] : "Disabled"]</a>"
dat += "<b>Produces:</b>"
var/datum/reagent/balls_fluid = find_reagent_object_from_type(features["balls_fluid"])
if(balls_fluid && (balls_fluid in GLOB.genital_fluids_list))
@@ -907,6 +911,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Lactates:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_producing'>[features["breasts_producing"] == TRUE ? "Yes" : "No"]</a>"
//SPLURT Edit
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_stuffing'>[features["breasts_stuffing"] == TRUE ? "Yes" : "No"]</a>"
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_max_size;task=input'>[features["breasts_max_size"] ? features["breasts_max_size"] : "Disabled"]</a>"
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_min_size;task=input'>[features["breasts_min_size"] ? features["breasts_min_size"] : "Disabled"]</a>"
if(features["breasts_producing"] == TRUE)
dat += "<b>Produces:</b>"
var/datum/reagent/breasts_fluid = find_reagent_object_from_type(features["breasts_fluid"])
@@ -930,6 +936,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Butt Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=butt_visibility;task=input'>[features["butt_visibility"]]</a>"
//SPLURT Edit
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=butt_stuffing'>[features["butt_stuffing"] == TRUE ? "Yes" : "No"]</a>"
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=butt_max_size;task=input'>[features["butt_max_size"] ? features["butt_max_size"] : "Disabled"]</a>"
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=butt_min_size;task=input'>[features["butt_min_size"] ? features["butt_min_size"] : "Disabled"]</a>"
dat += "<b>Butthole Sprite:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=has_anus'>[features["has_anus"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_anus"])
dat += "<b>Butthole Color:</b></a><BR>"
@@ -953,6 +961,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["belly_color"]];'><font color='[color_hex2num(features["belly_color"]) < 200 ? "FFFFFF" : "000000"]'>#[features["belly_color"]]</font></span> <a href='?_src_=prefs;preference=belly_color;task=input'>Change</a><br>"
dat += "<b>Belly Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_size;task=input'>[features["belly_size"]]</a>"
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_max_size;task=input'>[features["belly_max_size"] ? features["belly_max_size"] : "Disabled" ]</a>"
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_min_size;task=input'>[features["belly_min_size"] ? features["belly_min_size"] : "Disabled" ]</a>"
dat += "<b>Belly Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=belly_visibility;task=input'>[features["belly_visibility"]]</a>"
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_stuffing'>[features["belly_stuffing"] == TRUE ? "Yes" : "No"]</a>"
dat += "</td>"
@@ -2383,9 +2393,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_mutantcolor = input(user, "Choose your character's alien/mutant color:", "Character Preference","#"+features["mcolor"]) as color|null
if(new_mutantcolor)
var/temp_hsv = RGBtoHSV(new_mutantcolor)
if(new_mutantcolor == "#000000")
if(new_mutantcolor == "#000000" && features["mcolor"] != pref_species.default_color) //SPLURT EDIT
features["mcolor"] = pref_species.default_color
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) // mutantcolors must be bright, but only if they affect the skin //SPLURT EDIT
features["mcolor"] = sanitize_hexcolor(new_mutantcolor, 6)
else
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2394,9 +2404,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_mutantcolor = input(user, "Choose your character's secondary alien/mutant color:", "Character Preference","#"+features["mcolor2"]) as color|null
if(new_mutantcolor)
var/temp_hsv = RGBtoHSV(new_mutantcolor)
if(new_mutantcolor == "#000000")
if(new_mutantcolor == "#000000" && features["mcolor2"] != pref_species.default_color) //SPLURT EDIT
features["mcolor2"] = pref_species.default_color
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) // mutantcolors must be bright, but only if they affect the skin //SPLURT EDIT
features["mcolor2"] = sanitize_hexcolor(new_mutantcolor, 6)
else
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2405,9 +2415,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_mutantcolor = input(user, "Choose your character's tertiary alien/mutant color:", "Character Preference","#"+features["mcolor3"]) as color|null
if(new_mutantcolor)
var/temp_hsv = RGBtoHSV(new_mutantcolor)
if(new_mutantcolor == "#000000")
if(new_mutantcolor == "#000000" && features["mcolor3"] != pref_species.default_color) //SPLURT EDIT
features["mcolor3"] = pref_species.default_color
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) // mutantcolors must be bright, but only if they affect the skin //SPLURT EDIT
features["mcolor3"] = sanitize_hexcolor(new_mutantcolor, 6)
else
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2421,9 +2431,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_neckfire_color = input(user, "Choose your fire's color:", "Character Preference", "#"+features["neckfire_color"]) as color|null
if(new_neckfire_color)
var/temp_hsv = RGBtoHSV(new_neckfire_color)
if(new_neckfire_color == "#000000")
if(new_neckfire_color == "#000000" && features["neckfire_color"] != pref_species.default_color) //SPLURT EDIT
features["neckfire_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["neckfire_color"] = sanitize_hexcolor(new_neckfire_color, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2564,7 +2574,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("horns_color")
var/new_horn_color = input(user, "Choose your character's horn colour:", "Character Preference","#"+features["horns_color"]) as color|null
if(new_horn_color)
if (new_horn_color == "#000000")
if (new_horn_color == "#000000" && features["horns_color"] != "85615A") //SPLURT EDIT
features["horns_color"] = "85615A"
else
features["horns_color"] = sanitize_hexcolor(new_horn_color, 6)
@@ -2578,7 +2588,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("wings_color")
var/new_wing_color = input(user, "Choose your character's wing colour:", "Character Preference","#"+features["wings_color"]) as color|null
if(new_wing_color)
if (new_wing_color == "#000000")
if (new_wing_color == "#000000" && features["wings_color"] != "#FFFFFF") //SPLURT EDIT
features["wings_color"] = "#FFFFFF"
else
features["wings_color"] = sanitize_hexcolor(new_wing_color, 6)
@@ -2654,7 +2664,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/custom_tone = input(user, "Choose your custom skin tone:", "Character Preference", default) as color|null
if(custom_tone)
var/temp_hsv = RGBtoHSV(custom_tone)
if(ReadHSV(temp_hsv)[3] < ReadHSV("#333333")[3]) // rgb(50,50,50)
if(ReadHSV(temp_hsv)[3] < ReadHSV("#333333")[3] && CONFIG_GET(flag/character_color_limits)) // rgb(50,50,50) //SPLURT EDIT
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
else
use_custom_skin_tone = TRUE
@@ -2749,9 +2759,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_feature_color = input(user, "Choose your character's mutant part colour:", "Character Preference","#"+features[href_list["preference"]]) as color|null
if(new_feature_color)
var/temp_hsv = RGBtoHSV(new_feature_color)
if(new_feature_color == "#000000")
if(new_feature_color == "#000000" && features[href_list["preference"]] != pref_species.default_color) //SPLURT EDIT
features[href_list["preference"]] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features[href_list["preference"]] = sanitize_hexcolor(new_feature_color, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2778,9 +2788,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_cockcolor = input(user, "Penis color:", "Character Preference","#"+features["cock_color"]) as color|null
if(new_cockcolor)
var/temp_hsv = RGBtoHSV(new_cockcolor)
if(new_cockcolor == "#000000")
if(new_cockcolor == "#000000" && features["cock_color"] != pref_species.default_color) //SPLURT EDIT
features["cock_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["cock_color"] = sanitize_hexcolor(new_cockcolor, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2825,9 +2835,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_ballscolor = input(user, "Testicles Color:", "Character Preference","#"+features["balls_color"]) as color|null
if(new_ballscolor)
var/temp_hsv = RGBtoHSV(new_ballscolor)
if(new_ballscolor == "#000000")
if(new_ballscolor == "#000000" && features["balls_color"] != pref_species.default_color) //SPLURT EDIT
features["balls_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["balls_color"] = sanitize_hexcolor(new_ballscolor, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2868,9 +2878,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_breasts_color = input(user, "Breast Color:", "Character Preference","#"+features["breasts_color"]) as color|null
if(new_breasts_color)
var/temp_hsv = RGBtoHSV(new_breasts_color)
if(new_breasts_color == "#000000")
if(new_breasts_color == "#000000" && features["breasts_color"] != pref_species.default_color) //SPLURT EDIT
features["breasts_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["breasts_color"] = sanitize_hexcolor(new_breasts_color, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2900,9 +2910,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_vagcolor = input(user, "Vagina color:", "Character Preference","#"+features["vag_color"]) as color|null
if(new_vagcolor)
var/temp_hsv = RGBtoHSV(new_vagcolor)
if(new_vagcolor == "#000000")
if(new_vagcolor == "#000000" && features["vag_color"] != pref_species.default_color) //SPLURT EDIT
features["vag_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["vag_color"] = sanitize_hexcolor(new_vagcolor, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2926,9 +2936,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_bellycolor = input(user, "Belly Color:", "Character Preference", "#"+features["belly_color"]) as color|null
if(new_bellycolor)
var/temp_hsv = RGBtoHSV(new_bellycolor)
if(new_bellycolor == "#000000")
if(new_bellycolor == "#000000" && features["belly_color"] != pref_species.default_color) //SPLURT EDIT
features["belly_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["belly_color"] = sanitize_hexcolor(new_bellycolor, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2937,9 +2947,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_buttcolor = input(user, "Butt color:", "Character Preference","#"+features["butt_color"]) as color|null
if(new_buttcolor)
var/temp_hsv = RGBtoHSV(new_buttcolor)
if(new_buttcolor == "#000000")
if(new_buttcolor == "#000000" && features["butt_color"] != pref_species.default_color) //SPLURT EDIT
features["butt_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["butt_color"] = sanitize_hexcolor(new_buttcolor, 6)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2948,9 +2958,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_anuscolor = input(user, "Butthole color:", "Character Preference", "#"+features["anus_color"]) as color|null
if(new_anuscolor)
var/temp_hsv = RGBtoHSV(new_anuscolor)
if(new_anuscolor == "#000000")
if(new_anuscolor == "#000000" && features["anus_color"] != pref_species.default_color) //SPLURT EDIT
features["anus_color"] = pref_species.default_color
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) //SPLURT EDIT
features["anus_color"] = sanitize_hexcolor(new_anuscolor, 6)
else
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -2990,6 +3000,82 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(n_vis)
features["belly_visibility"] = n_vis
if("cock_max_length")
var/max_B = CONFIG_GET(number/penis_max_inches_prefs)
var/new_size = input(user, "Max size:\n([features["cock_length"]]-[max_B])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["cock_max_length"] = clamp(round(new_size), features["cock_length"], max_B)
else
features -= "cock_max_length"
if("balls_max_size")
var/new_size = input(user, "Max size:\n([BALLS_SIZE_MIN]-[BALLS_SIZE_MAX])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["balls_max_size"] = clamp(round(new_size), BALLS_SIZE_MIN, BALLS_SIZE_MAX)
else
features -= "balls_max_size"
if("breasts_max_size")
var/new_size = input(user, "Breast Max Size (cancel to disable)", "Character Preference") as null|anything in GLOB.breast_values
if(new_size)
features["breasts_max_size"] = new_size
else
features -= "breasts_max_size"
if("belly_max_size")
var/max_B = CONFIG_GET(number/belly_max_size_prefs)
var/new_size = input(user, "Max size:\n([features["belly_size"]]-[max_B])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["belly_max_size"] = clamp(round(new_size), features["belly_size"], max_B)
else
features -= "belly_max_size"
if("butt_max_size")
var/max_B = CONFIG_GET(number/butt_max_size_prefs)
var/new_size = input(user, "Max size:\n([features["butt_size"]]-[max_B])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["butt_max_size"] = clamp(round(new_size), features["butt_size"], max_B)
else
features -= "butt_max_size"
if("cock_min_length")
var/min_B = CONFIG_GET(number/penis_min_inches_prefs)
var/new_size = input(user, "Min size:\n([min_B]-[features["cock_length"]])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["cock_min_length"] = clamp(round(new_size), min_B, features["cock_length"])
else
features -= "cock_min_length"
if("balls_min_size")
var/new_size = input(user, "Min size:\n([BALLS_SIZE_MIN]-[BALLS_SIZE_MAX])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["balls_min_size"] = clamp(round(new_size), BALLS_SIZE_MIN, BALLS_SIZE_MAX)
else
features -= "balls_min_size"
if("breasts_min_size")
var/new_size = input(user, "Breast Min Size (cancel to disable)", "Character Preference") as null|anything in GLOB.breast_values
if(new_size)
features["breasts_min_size"] = new_size
else
features -= "breasts_min_size"
if("belly_min_size")
var/min_B = CONFIG_GET(number/belly_min_size_prefs)
var/new_size = input(user, "Min size:\n([min_B]-[features["belly_size"]])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["belly_min_size"] = clamp(round(new_size), min_B, features["belly_size"])
else
features -= "belly_min_size"
if("butt_min_size")
var/min_B = CONFIG_GET(number/butt_min_size_prefs)
var/new_size = input(user, "Min size:\n([min_B]-[features["butt_size"]])(0 = disabled)", "Character Preference") as num|null
if(new_size)
features["butt_min_size"] = clamp(round(new_size), min_B, features["butt_size"])
else
features -= "butt_min_size"
if("ooccolor")
var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference",ooccolor) as color|null
if(new_ooccolor)
@@ -3252,7 +3338,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/new_marking_color = input(user, "Choose your character's marking color:", "Character Preference","#"+color_list[color_number]) as color|null
if(new_marking_color)
var/temp_hsv = RGBtoHSV(new_marking_color)
if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin
if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) // mutantcolors must be bright, but only if they affect the skin //SPLURT EDIT
color_list[color_number] = "#[sanitize_hexcolor(new_marking_color, 6)]"
else
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
@@ -4173,3 +4259,4 @@ GLOBAL_LIST_EMPTY(preferences_datums)
#undef DEFAULT_SLOT_AMT
#undef HANDS_SLOT_AMT
#undef BACKPACK_SLOT_AMT
@@ -1054,6 +1054,28 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_inert_eggs"] >> features["inert_eggs"]
if(S["features_cock_max_length"])
S["features_cock_max_length"] >> features["cock_max_length"]
if(S["features_balls_max_size"])
S["features_balls_max_size"] >> features["balls_max_size"]
if(S["features_breasts_max_size"])
S["features_breasts_max_size"] >> features["breasts_max_size"]
if(S["features_belly_max_size"])
S["features_belly_max_size"] >> features["belly_max_size"]
if(S["features_butt_max_size"])
S["features_butt_max_size"] >> features["butt_max_size"]
if(S["features_cock_min_length"])
S["features_cock_min_length"] >> features["cock_min_length"]
if(S["features_balls_min_size"])
S["features_balls_min_size"] >> features["balls_min_size"]
if(S["features_breasts_min_size"])
S["features_breasts_min_size"] >> features["breasts_min_size"]
if(S["features_belly_min_size"])
S["features_belly_min_size"] >> features["belly_min_size"]
if(S["features_butt_min_size"])
S["features_butt_min_size"] >> features["butt_min_size"]
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
if(fexists(char_vr_path))
var/list/json_from_file = json_decode(file2text(char_vr_path))
@@ -1413,6 +1435,19 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["feature_inert_eggs"], features["inert_eggs"])
WRITE_FILE(S["features_cock_max_length"], features["cock_max_length"])
WRITE_FILE(S["features_balls_max_size"], features["balls_max_size"])
WRITE_FILE(S["features_breasts_max_size"], features["breasts_max_size"])
WRITE_FILE(S["features_belly_max_size"], features["belly_max_size"])
WRITE_FILE(S["features_butt_max_size"], features["butt_max_size"])
WRITE_FILE(S["features_cock_min_length"], features["cock_min_length"])
WRITE_FILE(S["features_balls_min_size"], features["balls_min_size"])
WRITE_FILE(S["features_breasts_min_size"], features["breasts_min_size"])
WRITE_FILE(S["features_belly_min_size"], features["belly_min_size"])
WRITE_FILE(S["features_butt_min_size"], features["butt_min_size"])
WRITE_FILE(S["feature_neckfire"], features["neckfire"])
WRITE_FILE(S["feature_neckfire_color"], features["neckfire_color"])
@@ -29,7 +29,7 @@
var/new_color = input(owner, "Choose your skin color:", "Race change","#"+H.dna.features["mcolor"]) as color|null
if(new_color)
var/temp_hsv = RGBtoHSV(new_color)
if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright
if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3] || !CONFIG_GET(flag/character_color_limits)) // mutantcolors must be bright //SPLURT EDIT
H.dna.features["mcolor"] = sanitize_hexcolor(new_color, 6)
H.update_body()
H.update_hair()
@@ -117,7 +117,7 @@
if(new_snout)
H.dna.features["mam_snouts"] = new_snout
H.update_body()
else if (select_alteration == "Wings")
var/new_color = input(owner, "Choose your wing color:", "Race change","#"+H.dna.features["wings_color"]) as color|null
if(new_color)
+20 -2
View File
@@ -404,7 +404,7 @@
*
* overridden here and in /mob/dead/observer for different point span classes and sanity checks
*/
/mob/verb/pointed(atom/A as mob|obj|turf in fov_view())
/mob/verb/pointed(atom/A as mob|obj|turf in fov_view(), params = "" as text)
set name = "Point To"
set category = "Object"
@@ -419,7 +419,25 @@
var/turf/our_tile = get_turf(src)
var/obj/visual = new /obj/effect/temp_visual/point(our_tile, invisibility)
animate(visual, pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, time = 1.7, easing = EASE_OUT)
/// Set position
var/final_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x
var/final_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y
var/list/click_params = params2list(params)
if(length(click_params) && click_params["screen-loc"])
var/list/actual_view = getviewsize(client ? client.view : world.view)
var/list/split_coords = splittext(click_params["screen-loc"], ",")
final_x = (text2num(splittext(split_coords[1], ":")[1]) - actual_view[1] / 2) * world.icon_size + (text2num(splittext(split_coords[1], ":")[2]) - world.icon_size)
final_y = (text2num(splittext(split_coords[2], ":")[1]) - actual_view[2] / 2) * world.icon_size + (text2num(splittext(split_coords[2], ":")[2]) - world.icon_size)
//
/// Set rotation
var/matrix/rotated_matrix = new()
rotated_matrix.TurnTo(0, Get_Pixel_Angle(-final_y, -final_x))
visual.transform = rotated_matrix
//
animate(visual, pixel_x = final_x, pixel_y = final_y, time = 1.7, easing = EASE_OUT)
SEND_SIGNAL(src, COMSIG_MOB_POINTED, A)
return TRUE
+3
View File
@@ -13,6 +13,9 @@
#include "v5\_defines.dm"
#include "v5\api.dm"
#include "v5\bridge.dm"
#include "v5\chunking.dm"
#include "v5\commands.dm"
#include "v5\serializers.dm"
#include "v5\topic.dm"
#include "v5\undefs.dm"
+3
View File
@@ -5,6 +5,9 @@ This DMAPI implements bridge requests using HTTP GET requests to TGS. It has no
- [__interop_version.dm](./__interop_version.dm) contains the version of the API used between the DMAPI and TGS.
- [_defines.dm](./_defines.dm) contains constant definitions.
- [api.dm](./api.dm) contains the bulk of the API code.
- [bridge.dm](./bridge.dm) contains functions related to making bridge requests.
- [chunking.dm](./chunking.dm) contains common function for splitting large raw data sets into chunks BYOND can natively process.
- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s.
- [serializers.dm](./serializers.dm) contains function to help convert interop `/datum`s into a JSON encodable `list()` format.
- [topic.dm](./topic.dm) contains functions related to processing topic requests.
- [undefs.dm](./undefs.dm) Undoes the work of `_defines.dm`.
+1 -1
View File
@@ -1 +1 @@
"5.5.0"
"5.6.0"
+15
View File
@@ -4,16 +4,29 @@
#define DMAPI5_BRIDGE_DATA "data"
#define DMAPI5_TOPIC_DATA "tgs_data"
#define DMAPI5_BRIDGE_REQUEST_LIMIT 8198
#define DMAPI5_TOPIC_REQUEST_LIMIT 65529
#define DMAPI5_TOPIC_RESPONSE_LIMIT 65528
#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0
#define DMAPI5_BRIDGE_COMMAND_STARTUP 1
#define DMAPI5_BRIDGE_COMMAND_PRIME 2
#define DMAPI5_BRIDGE_COMMAND_REBOOT 3
#define DMAPI5_BRIDGE_COMMAND_KILL 4
#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5
#define DMAPI5_BRIDGE_COMMAND_CHUNK 6
#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier"
#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands"
#define DMAPI5_CHUNK "chunk"
#define DMAPI5_CHUNK_PAYLOAD "payload"
#define DMAPI5_CHUNK_TOTAL "totalChunks"
#define DMAPI5_CHUNK_SEQUENCE_ID "sequenceId"
#define DMAPI5_CHUNK_PAYLOAD_ID "payloadId"
#define DMAPI5_MISSING_CHUNKS "missingChunks"
#define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage"
#define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType"
@@ -64,6 +77,8 @@
#define DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE 6
#define DMAPI5_TOPIC_COMMAND_HEARTBEAT 7
#define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8
#define DMAPI5_TOPIC_COMMAND_SEND_CHUNK 9
#define DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK 10
#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType"
#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand"
+7 -161
View File
@@ -17,6 +17,11 @@
var/initialized = FALSE
var/chunked_requests = 0
var/list/chunked_topics = list()
var/detached = FALSE
/datum/tgs_api/v5/ApiVersion()
return new /datum/tgs_version(
#include "__interop_version.dm"
@@ -97,13 +102,6 @@
/datum/tgs_api/v5/OnInitializationComplete()
Bridge(DMAPI5_BRIDGE_COMMAND_PRIME)
/datum/tgs_api/v5/proc/TopicResponse(error_message = null)
var/list/response = list()
if(error_message)
response[DMAPI5_RESPONSE_ERROR_MESSAGE] = error_message
return json_encode(response)
return "{}"
/datum/tgs_api/v5/OnTopic(T)
RequireInitialBridgeResponse()
var/list/params = params2list(T)
@@ -111,163 +109,11 @@
if(!json)
return FALSE // continue to /world/Topic
var/list/topic_parameters = json_decode(json)
if(!topic_parameters)
return TopicResponse("Invalid topic parameters json!");
if(!initialized)
TGS_WARNING_LOG("Missed topic due to not being initialized: [T]")
TGS_WARNING_LOG("Missed topic due to not being initialized: [json]")
return TRUE // too early to handle, but it's still our responsibility
var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER]
if(their_sCK != access_identifier)
return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] from: [json]!");
var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]
if(!isnum(command))
return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] from: [json]!")
switch(command)
if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND)
intercepted_message_queue = list()
var/result = HandleCustomCommand(topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND])
if(!result)
result = TopicResponse("Error running chat command!")
result[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
intercepted_message_queue = null
return result
if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION)
intercepted_message_queue = list()
var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]
if(!istype(event_notification))
return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!")
var/event_type = event_notification[DMAPI5_EVENT_NOTIFICATION_TYPE]
if(!isnum(event_type))
return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_TYPE]!")
var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS]
if(event_parameters && !istype(event_parameters))
return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!")
var/list/event_call = list(event_type)
if(event_parameters)
event_call += event_parameters
if(event_handler != null)
event_handler.HandleEvent(arglist(event_call))
var/list/response = list()
response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
intercepted_message_queue = null
return json_encode(response)
if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
if (!isnum(new_port) || !(new_port > 0))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port)
//the topic still completes, miraculously
//I honestly didn't believe byond could do it without exploding
if(!world.OpenPort(new_port))
return TopicResponse("Port change failed!")
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE)
var/new_reboot_mode = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]
if(!isnum(new_reboot_mode))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]!")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode)
reboot_mode = new_reboot_mode
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED)
var/new_instance_name = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]
if(!istext(new_instance_name))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]!")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_INSTANCE_RENAMED, new_instance_name)
instance_name = new_instance_name
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE)
var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]
if(!istype(chat_update_json))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!")
DecodeChannels(chat_update_json)
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
if (!isnum(new_port) || !(new_port > 0))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
server_port = new_port
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_HEARTBEAT)
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
var/error_message = null
if (new_port != null)
if (!isnum(new_port) || !(new_port > 0))
error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]"
else
server_port = new_port
var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]
if (!istext(new_version_string))
if(error_message != null)
error_message += ", "
error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]"
else
var/datum/tgs_version/new_version = new(new_version_string)
if (event_handler)
event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version)
version = new_version
return json_encode(list(DMAPI5_RESPONSE_ERROR_MESSAGE = error_message, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()))
return TopicResponse("Unknown command: [command]")
/datum/tgs_api/v5/proc/Bridge(command, list/data)
if(!data)
data = list()
data[DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE] = command
data[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] = access_identifier
var/json = json_encode(data)
var/encoded_json = url_encode(json)
// This is an infinite sleep until we get a response
var/export_response = world.Export("http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]")
if(!export_response)
TGS_ERROR_LOG("Failed export request: [json]")
return
var/response_json = file2text(export_response["CONTENT"])
if(!response_json)
TGS_ERROR_LOG("Failed export request, missing content!")
return
var/list/bridge_response = json_decode(response_json)
if(!bridge_response)
TGS_ERROR_LOG("Failed export request, bad json: [response_json]")
return
var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE]
if(error)
TGS_ERROR_LOG("Failed export request, bad request: [error]")
return
return bridge_response
return ProcessTopicJson(json, TRUE)
/datum/tgs_api/v5/OnReboot()
var/list/result = Bridge(DMAPI5_BRIDGE_COMMAND_REBOOT)
+95
View File
@@ -0,0 +1,95 @@
/datum/tgs_api/v5/proc/Bridge(command, list/data)
if(!data)
data = list()
var/single_bridge_request = CreateBridgeRequest(command, data)
if(length(single_bridge_request) <= DMAPI5_BRIDGE_REQUEST_LIMIT)
return PerformBridgeRequest(single_bridge_request)
// chunking required
var/payload_id = ++chunked_requests
var/raw_data = CreateBridgeData(command, data, FALSE)
var/list/chunk_requests = GenerateChunks(raw_data, TRUE)
var/list/response
for(var/bridge_request in chunk_requests)
response = PerformBridgeRequest(bridge_request)
if(!response)
// Abort
return
var/list/missing_sequence_ids = response[DMAPI5_MISSING_CHUNKS]
if(length(missing_sequence_ids))
do
TGS_WARNING_LOG("Server is still missing some chunks of bridge P[payload_id]! Sending missing chunks...")
if(!istype(missing_sequence_ids))
TGS_ERROR_LOG("Did not receive a list() for [DMAPI5_MISSING_CHUNKS]!")
return
for(var/missing_sequence_id in missing_sequence_ids)
if(!isnum(missing_sequence_id))
TGS_ERROR_LOG("Did not receive a num in [DMAPI5_MISSING_CHUNKS]!")
return
var/missing_chunk_request = chunk_requests[missing_sequence_id + 1]
response = PerformBridgeRequest(missing_chunk_request)
if(!response)
// Abort
return
missing_sequence_ids = response[DMAPI5_MISSING_CHUNKS]
while(length(missing_sequence_ids))
return response
/datum/tgs_api/v5/proc/CreateBridgeRequest(command, list/data)
var/json = CreateBridgeData(command, data, TRUE)
var/encoded_json = url_encode(json)
var/url = "http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]"
return url
/datum/tgs_api/v5/proc/CreateBridgeData(command, list/data, needs_auth)
data[DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE] = command
if(needs_auth)
data[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] = access_identifier
var/json = json_encode(data)
return json
/datum/tgs_api/v5/proc/PerformBridgeRequest(bridge_request)
if(detached)
// Wait up to one minute
for(var/i in 1 to 600)
sleep(1)
if(!detached)
break
// dad went out for milk cigarettes 20 years ago...
if(i == 600)
detached = FALSE
// This is an infinite sleep until we get a response
var/export_response = world.Export(bridge_request)
if(!export_response)
TGS_ERROR_LOG("Failed bridge request: [bridge_request]")
return
var/response_json = file2text(export_response["CONTENT"])
if(!response_json)
TGS_ERROR_LOG("Failed bridge request, missing content!")
return
var/list/bridge_response = json_decode(response_json)
if(!bridge_response)
TGS_ERROR_LOG("Failed bridge request, bad json: [response_json]")
return
var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE]
if(error)
TGS_ERROR_LOG("Failed bridge request, bad request: [error]")
return
return bridge_response
+43
View File
@@ -0,0 +1,43 @@
/datum/tgs_api/v5/proc/GenerateChunks(payload, bridge)
var/limit = bridge ? DMAPI5_BRIDGE_REQUEST_LIMIT : DMAPI5_TOPIC_RESPONSE_LIMIT
var/payload_id = ++chunked_requests
var/data_length = length(payload)
var/chunk_count
var/list/chunk_requests
for(chunk_count = 2; !chunk_requests; ++chunk_count)
var/max_chunk_size = -round(-(data_length / chunk_count))
if(max_chunk_size > limit)
continue
chunk_requests = list()
for(var/i in 1 to chunk_count)
var/start_index = 1 + ((i - 1) * max_chunk_size)
if (start_index > data_length)
break
var/end_index = min(1 + (i * max_chunk_size), data_length + 1)
var/chunk_payload = copytext(payload, start_index, end_index)
// sequence IDs in interop chunking are always zero indexed
var/list/chunk = list(DMAPI5_CHUNK_PAYLOAD_ID = payload_id, DMAPI5_CHUNK_SEQUENCE_ID = (i - 1), DMAPI5_CHUNK_TOTAL = chunk_count, DMAPI5_CHUNK_PAYLOAD = chunk_payload)
var/chunk_request = list(DMAPI5_CHUNK = chunk)
var/chunk_length
if(bridge)
chunk_request = CreateBridgeRequest(DMAPI5_BRIDGE_COMMAND_CHUNK, chunk_request)
chunk_length = length(chunk_request)
else
chunk_request = list(chunk_request) // wrap for adding to list
chunk_length = length(json_encode(chunk_request))
if(chunk_length > limit)
// Screwed by encoding, no way to preempt it though
chunk_requests = null
break
chunk_requests += chunk_request
return chunk_requests
+2 -2
View File
@@ -36,10 +36,10 @@
var/datum/tgs_message_content/response = sc.Run(u, params)
response = UpgradeDeprecatedCommandResponse(response, command)
var/list/topic_response = list()
var/list/topic_response = TopicResponse()
topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response?.text
topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response?._interop_serialize()
return json_encode(topic_response)
return topic_response
return TopicResponse("Unknown custom chat command: [command]!")
// Common proc b/c it's used by the V3/V4 APIs
+258
View File
@@ -0,0 +1,258 @@
/datum/tgs_api/v5/proc/TopicResponse(error_message = null)
var/list/response = list()
if(error_message)
response[DMAPI5_RESPONSE_ERROR_MESSAGE] = error_message
return response
/datum/tgs_api/v5/proc/ProcessTopicJson(json, check_access_identifier)
var/list/result = ProcessRawTopic(json, check_access_identifier)
if(!result)
result = TopicResponse("Runtime error!")
else if(!length(result))
return "{}" // quirk of json_encode is an empty list returns "[]"
var/response_json = json_encode(result)
if(length(response_json) > DMAPI5_TOPIC_RESPONSE_LIMIT)
// cache response chunks and send the first
var/list/chunks = GenerateChunks(response_json, FALSE)
var/payload_id = chunks[1][DMAPI5_CHUNK][DMAPI5_CHUNK_PAYLOAD_ID]
var/cache_key = ResponseTopicChunkCacheKey(payload_id)
chunked_topics[cache_key] = chunks
response_json = json_encode(chunks[1])
return response_json
/datum/tgs_api/v5/proc/ProcessRawTopic(json, check_access_identifier)
var/list/topic_parameters = json_decode(json)
if(!topic_parameters)
return TopicResponse("Invalid topic parameters json: [json]!");
var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER]
if(check_access_identifier && their_sCK != access_identifier)
return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER]!")
var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]
if(!isnum(command))
return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]!")
return ProcessTopicCommand(command, topic_parameters)
/datum/tgs_api/v5/proc/ResponseTopicChunkCacheKey(payload_id)
return "response[payload_id]"
/datum/tgs_api/v5/proc/ProcessTopicCommand(command, list/topic_parameters)
switch(command)
if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND)
intercepted_message_queue = list()
var/list/result = HandleCustomCommand(topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND])
if(!result)
result = TopicResponse("Error running chat command!")
result[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
intercepted_message_queue = null
return result
if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION)
intercepted_message_queue = list()
var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]
if(!istype(event_notification))
return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!")
var/event_type = event_notification[DMAPI5_EVENT_NOTIFICATION_TYPE]
if(!isnum(event_type))
return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_TYPE]!")
var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS]
if(event_parameters && !istype(event_parameters))
return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!")
var/list/event_call = list(event_type)
if (event_type == TGS_EVENT_WATCHDOG_DETACH)
detached = TRUE
if(event_parameters)
event_call += event_parameters
if(event_handler != null)
event_handler.HandleEvent(arglist(event_call))
var/list/response = TopicResponse()
response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
intercepted_message_queue = null
return response
if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
if (!isnum(new_port) || !(new_port > 0))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port)
//the topic still completes, miraculously
//I honestly didn't believe byond could do it without exploding
if(!world.OpenPort(new_port))
return TopicResponse("Port change failed!")
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE)
var/new_reboot_mode = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]
if(!isnum(new_reboot_mode))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]!")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode)
reboot_mode = new_reboot_mode
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED)
var/new_instance_name = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]
if(!istext(new_instance_name))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]!")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_INSTANCE_RENAMED, new_instance_name)
instance_name = new_instance_name
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE)
var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]
if(!istype(chat_update_json))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!")
DecodeChannels(chat_update_json)
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
if (!isnum(new_port) || !(new_port > 0))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
server_port = new_port
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_HEARTBEAT)
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH)
detached = FALSE
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
var/error_message = null
if (new_port != null)
if (!isnum(new_port) || !(new_port > 0))
error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]"
else
server_port = new_port
var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]
if (!istext(new_version_string))
if(error_message != null)
error_message += ", "
error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]"
else
var/datum/tgs_version/new_version = new(new_version_string)
if (event_handler)
event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version)
version = new_version
var/list/reattach_response = TopicResponse(error_message)
reattach_response[DMAPI5_PARAMETER_CUSTOM_COMMANDS] = ListCustomCommands()
return reattach_response
if(DMAPI5_TOPIC_COMMAND_SEND_CHUNK)
var/list/chunk = topic_parameters[DMAPI5_CHUNK]
if(!istype(chunk))
return TopicResponse("Invalid [DMAPI5_CHUNK]!")
var/payload_id = chunk[DMAPI5_CHUNK_PAYLOAD_ID]
if(!isnum(payload_id))
return TopicResponse("[DMAPI5_CHUNK_PAYLOAD_ID] is not a number!")
// Always updated the highest known payload ID
chunked_requests = max(chunked_requests, payload_id)
var/sequence_id = chunk[DMAPI5_CHUNK_SEQUENCE_ID]
if(!isnum(sequence_id))
return TopicResponse("[DMAPI5_CHUNK_SEQUENCE_ID] is not a number!")
var/total_chunks = chunk[DMAPI5_CHUNK_TOTAL]
if(!isnum(total_chunks))
return TopicResponse("[DMAPI5_CHUNK_TOTAL] is not a number!")
if(total_chunks == 0)
return TopicResponse("[DMAPI5_CHUNK_TOTAL] is zero!")
var/payload = chunk[DMAPI5_CHUNK_PAYLOAD]
if(!istext(payload))
return TopicResponse("[DMAPI5_CHUNK_PAYLOAD] is not text!")
var/cache_key = "request[payload_id]"
var/payloads = chunked_topics[cache_key]
if(!payloads)
payloads = new /list(total_chunks)
chunked_topics[cache_key] = payloads
if(total_chunks != length(payloads))
chunked_topics -= cache_key
return TopicResponse("Received differing total chunks for same [DMAPI5_CHUNK_PAYLOAD_ID]! Invalidating [DMAPI5_CHUNK_PAYLOAD_ID]!")
var/pre_existing_chunk = payloads[sequence_id + 1]
if(pre_existing_chunk && pre_existing_chunk != payload)
chunked_topics -= cache_key
return TopicResponse("Received differing payload for same [DMAPI5_CHUNK_SEQUENCE_ID]! Invalidating [DMAPI5_CHUNK_PAYLOAD_ID]!")
payloads[sequence_id + 1] = payload
var/list/missing_sequence_ids = list()
for(var/i in 1 to total_chunks)
if(!payloads[i])
missing_sequence_ids += i - 1
if(length(missing_sequence_ids))
return list(DMAPI5_MISSING_CHUNKS = missing_sequence_ids)
chunked_topics -= cache_key
var/full_json = jointext(payloads, "")
return ProcessRawTopic(full_json, FALSE)
if(DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK)
var/payload_id = topic_parameters[DMAPI5_CHUNK_PAYLOAD_ID]
if(!isnum(payload_id))
return TopicResponse("[DMAPI5_CHUNK_PAYLOAD_ID] is not a number!")
// Always updated the highest known payload ID
chunked_requests = max(chunked_requests, payload_id)
var/list/missing_chunks = topic_parameters[DMAPI5_MISSING_CHUNKS]
if(!istype(missing_chunks) || !length(missing_chunks))
return TopicResponse("Missing or empty [DMAPI5_MISSING_CHUNKS]!")
var/sequence_id_to_send = missing_chunks[1]
if(!isnum(sequence_id_to_send))
return TopicResponse("[DMAPI5_MISSING_CHUNKS] contained a non-number!")
var/cache_key = ResponseTopicChunkCacheKey(payload_id)
var/list/chunks = chunked_topics[cache_key]
if(!chunks)
return TopicResponse("Unknown response chunk set: P[payload_id]!")
// sequence IDs in interop chunking are always zero indexed
var/chunk_to_send = chunks[sequence_id_to_send + 1]
if(!chunk_to_send)
return TopicResponse("Sequence ID [sequence_id_to_send] is not present in response chunk P[payload_id]!")
if(length(missing_chunks) == 1)
// sending last chunk, purge the cache
chunked_topics -= cache_key
return chunk_to_send
return TopicResponse("Unknown command: [command]")
+13
View File
@@ -4,16 +4,29 @@
#undef DMAPI5_BRIDGE_DATA
#undef DMAPI5_TOPIC_DATA
#undef DMAPI5_BRIDGE_REQUEST_LIMIT
#undef DMAPI5_TOPIC_REQUEST_LIMIT
#undef DMAPI5_TOPIC_RESPONSE_LIMIT
#undef DMAPI5_BRIDGE_COMMAND_PORT_UPDATE
#undef DMAPI5_BRIDGE_COMMAND_STARTUP
#undef DMAPI5_BRIDGE_COMMAND_PRIME
#undef DMAPI5_BRIDGE_COMMAND_REBOOT
#undef DMAPI5_BRIDGE_COMMAND_KILL
#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND
#undef DMAPI5_BRIDGE_COMMAND_CHUNK
#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER
#undef DMAPI5_PARAMETER_CUSTOM_COMMANDS
#undef DMAPI5_CHUNK
#undef DMAPI5_CHUNK_PAYLOAD
#undef DMAPI5_CHUNK_TOTAL
#undef DMAPI5_CHUNK_SEQUENCE_ID
#undef DMAPI5_CHUNK_PAYLOAD_ID
#undef DMAPI5_MISSING_CHUNKS
#undef DMAPI5_RESPONSE_ERROR_MESSAGE
#undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE