Skip to content

Commit

Permalink
[PORT] Giving Books More Potential (Monkestation#1363)
Browse files Browse the repository at this point in the history
* Books now render Markdown, fixing paper importing (#74902)

## About The Pull Request

Books didn't render markdown and instead just dumped the raw contents,
(after a html encode), into the window.
Changes them to use tgui and support markdown rendering.
## Why It's Good For The Game

Books should should look the same as the paper used to make them.
## Changelog
:cl:
fix: Book's no longer take your formatting and throw it out the window.
refactor: Book display and rendering
/:cl:

---------

Co-authored-by: GoldenAlpharex <[email protected]>
Co-authored-by: Mothblocks <[email protected]>

* Adjust objects to tabletop when wrenched (#75671)

![dreamseeker_2f6HEd87Kb](https://github.com/tgstation/tgstation/assets/3625094/c272df94-cdb6-427e-a3dc-c0e7d9cca4ea)

## About The Pull Request

Added a variable to `/obj/` that can be set to adjust the object sprite
when it mapspawns or being wrenched on top of a table.

Set this variable for some popular tabletop machines, removing the
default `pixel_y` offsets for some of them.

Also moved the wrenching logic to /obj/. It was under machinery for some
reason.

## Why It's Good For The Game

Did you ever unwrench something from the table by accident and then was
annoyed that you can't revet it back?

## Changelog

:cl:
qol: Objects have a variable to adjust them visually when they're
wrenched or spawned on a table
refactor: Removed redundant code that had similar purpose, moved `obj`
wrenching logic into the `objs.dm`
qol: food/slime processor can be moved on table and adjusts to it when
wrenched
/:cl:

* Admin Library Moderation (in-game edition) (#75645)

For the longest time, the only way admins could moderate the library was
by using statbus's external tool.
But a few months back statbus went down, and ever since then they've
been sitting lost. Shit sucks.

The whole external thing has been bugging me for a while, so let's fix
all that yeah?

This pr adds a new verb to the admin tab that allows admins to
ban/restore books from the library.
It includes expanded (ckey) search, faster response times, in tool book
viewing with and without markdown rendering, and viewing of deleted
books.

This is accomplished with a special subtype of library consoles, stored
on the admin datum.
It shouldn't let you do anything without +BAN, rip my live debugging or
whatever.

I've also hooked into (and fixed) Ned's existing library actions log,
and added viewing support to the ban/restore pages.
This logs banning admin, ban time, ban reason, etc.

As a part of this, I've fixed/expanded on the existing UIs.
I've added ID search to all existing consoles, and fixed an existing bug
with the visitor console not supporting category search (shows how many
people actually use the thing)

Changes to the library_action table were pretty minor. The ckey column
was too small, so longer keys just caused it to fail on ban. Bad.
That and the ip address column was signed, which wasted space and was
non standard with other tables.

* Removes line about adding a new index to the library_action table (#75808)

## About The Pull Request

I ended up walking back the index since it ended up being useless in
testing, just forgot to nuke the comment about it

* Improves some confusing aspects of the Library (#75781)

The barcode scanner now uses balloon alerts and only has 2 modes: check
in and add to inventory. It used to have 4, 2 of which were useless.

Added a title and author to chuuni granter so it's not broken to the
Curator's console. Moves inventory ui data stuff to ui static data so we
can reference it in checkout, which now uses a dropdown list of all
books in checkout, instead of having you fill out the name of the book
yourself.

Removes sending things to a computer by scanning a book then connecting
it to a computer. Just connect it to a computer first, there's no need
for this copy and paste stuff.

Finally, lets the book bag hold posters, since the Curator prints them
and it would be nice if they can also carry them without filling a bag.

Video was taken before the balloon alert stuff so just ignore that part

https://github.com/tgstation/tgstation/assets/53777086/e78011af-fb23-4553-a92d-f3dcc8bb5601

The library is currently very confusing for new people to figure out, I
thought this might be able to help with that.
The dropdown in the UI now means it's easier to give out books in
inventory, and you can no longer just type whatever the hell you wanted.

:cl:
qol: The Curator's barcode scanner has been simplified into 2 modes:
check-in and add to inventory.
qol: The Book bag can now hold posters.
ui: The library console can now lend books out easier with a dropdown
menu to all inventory books.
/:cl:

---------

Co-authored-by: MrMelbert <[email protected]>

* changed a var name to be more descriptive and match TGs current name

* Allows the book binder to remember font typing (#75007)

use that for book binding
## About The Pull Request

Closes tgstation/tgstation#74996
## Why It's Good For The Game
## Changelog
:cl:
fix: Bookbinder no longer takes your pen's font and throws it out the
nearest window
/:cl:

---------

Co-authored-by: Zephyr <[email protected]>
Co-authored-by: GoldenAlpharex <[email protected]>
Co-authored-by: Mothblocks <[email protected]>
Co-authored-by: Andrew <[email protected]>
Co-authored-by: LemonInTheDark <[email protected]>
Co-authored-by: John Willard <[email protected]>
Co-authored-by: MrMelbert <[email protected]>
  • Loading branch information
8 people authored Mar 16, 2024
1 parent 7d5a438 commit 110a42e
Show file tree
Hide file tree
Showing 33 changed files with 1,268 additions and 237 deletions.
14 changes: 11 additions & 3 deletions SQL/database_changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ Any time you make a change to the schema files, remember to increment the databa

Make sure to also update `DB_MAJOR_VERSION` and `DB_MINOR_VERSION`, which can be found in `code/__DEFINES/subsystem.dm`.

The latest database version is 5.23; The query to update the schema revision table is:
The latest database version is 5.24; The query to update the schema revision table is:

```sql
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 23);
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 24);
```
or

```sql
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 23);
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 24);
```

In any query remember to add a prefix to the table names if you use one.

-----------------------------------------------------
Version 5.24, 17 May 2023, by LemonInTheDark
Modified the library action table to fit ckeys properly, and to properly store ips.
```sql
ALTER TABLE `library_action` MODIFY COLUMN `ckey` varchar(32) NOT NULL;
ALTER TABLE `library_action` MODIFY COLUMN `ip_addr` int(10) unsigned NOT NULL;
```

-----------------------------------------------------
Version 5.23, 28 December 2022, by Mothblocks
Added `tutorial_completions` to mark what ckeys have completed contextual tutorials.
Expand Down
4 changes: 2 additions & 2 deletions SQL/tgstation_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ CREATE TABLE `library_action` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`book` int(10) unsigned NOT NULL,
`reason` longtext DEFAULT NULL,
`ckey` varchar(11) NOT NULL DEFAULT '',
`ckey` varchar(32) NOT NULL DEFAULT '',
`datetime` datetime NOT NULL DEFAULT current_timestamp(),
`action` varchar(11) NOT NULL DEFAULT '',
`ip_addr` int(11) NOT NULL,
`ip_addr` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
Expand Down
4 changes: 2 additions & 2 deletions SQL/tgstation_schema_prefixed.sql
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ CREATE TABLE `SS13_library_action` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`book` int(10) unsigned NOT NULL,
`reason` longtext DEFAULT NULL,
`ckey` varchar(11) NOT NULL DEFAULT '',
`ckey` varchar(32) NOT NULL DEFAULT '',
`datetime` datetime NOT NULL DEFAULT current_timestamp(),
`action` varchar(11) NOT NULL DEFAULT '',
`ip_addr` int(11) NOT NULL,
`ip_addr` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
Expand Down
9 changes: 9 additions & 0 deletions code/__DEFINES/library.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#define DEFAULT_UPLOAD_CATAGORY "Fiction"
#define DEFAULT_SEARCH_CATAGORY "Any"

///How many books should we load per page?
#define BOOKS_PER_PAGE 18
///How many checkout records should we load per page?
#define CHECKOUTS_PER_PAGE 17
///How many inventory items should we load per page?
#define INVENTORY_PER_PAGE 19
3 changes: 3 additions & 0 deletions code/__DEFINES/paper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
#define MODE_WRITING 1
/// Should be able to stamp paper.
#define MODE_STAMPING 2

#define BARCODE_SCANNER_CHECKIN "check_in"
#define BARCODE_SCANNER_INVENTORY "inventory"
2 changes: 1 addition & 1 deletion code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* make sure you add an update to the schema_version stable in the db changelog
*/
#define DB_MINOR_VERSION 23
#define DB_MINOR_VERSION 24


//! ## Timing subsystem
Expand Down
41 changes: 0 additions & 41 deletions code/game/machinery/_machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@
/obj/machinery/proc/process_atmos()//If you dont use process why are you here
return PROCESS_KILL


///Called when we want to change the value of the machine_stat variable. Holds bitflags.
/obj/machinery/proc/set_machine_stat(new_value)
if(new_value == machine_stat)
Expand Down Expand Up @@ -910,46 +909,6 @@
to_chat(user, span_notice("You rotate [src]."))
return TRUE

/obj/proc/can_be_unfasten_wrench(mob/user, silent) //if we can unwrench this object; returns SUCCESSFUL_UNFASTEN and FAILED_UNFASTEN, which are both TRUE, or CANT_UNFASTEN, which isn't.
if(!(isfloorturf(loc) || isindestructiblefloor(loc)) && !anchored)
to_chat(user, span_warning("[src] needs to be on the floor to be secured!"))
return FAILED_UNFASTEN
return SUCCESSFUL_UNFASTEN

/obj/proc/default_unfasten_wrench(mob/user, obj/item/wrench, time = 20) //try to unwrench an object in a WONDERFUL DYNAMIC WAY
if((flags_1 & NODECONSTRUCT_1) || wrench.tool_behaviour != TOOL_WRENCH)
return CANT_UNFASTEN

var/turf/ground = get_turf(src)
if(!anchored && ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
to_chat(user, span_notice("You fail to secure [src]."))
return CANT_UNFASTEN
var/can_be_unfasten = can_be_unfasten_wrench(user)
if(!can_be_unfasten || can_be_unfasten == FAILED_UNFASTEN)
return can_be_unfasten
if(time)
to_chat(user, span_notice("You begin [anchored ? "un" : ""]securing [src]..."))
wrench.play_tool_sound(src, 50)
var/prev_anchored = anchored
//as long as we're the same anchored state and we're either on a floor or are anchored, toggle our anchored state
if(!wrench.use_tool(src, user, time, extra_checks = CALLBACK(src, PROC_REF(unfasten_wrench_check), prev_anchored, user)))
return FAILED_UNFASTEN
if(!anchored && ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
to_chat(user, span_notice("You fail to secure [src]."))
return CANT_UNFASTEN
to_chat(user, span_notice("You [anchored ? "un" : ""]secure [src]."))
set_anchored(!anchored)
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored)
return SUCCESSFUL_UNFASTEN

/obj/proc/unfasten_wrench_check(prev_anchored, mob/user) //for the do_after, this checks if unfastening conditions are still valid
if(anchored != prev_anchored)
return FALSE
if(can_be_unfasten_wrench(user, TRUE) != SUCCESSFUL_UNFASTEN) //if we aren't explicitly successful, cancel the fuck out
return FALSE
return TRUE

/obj/machinery/proc/exchange_parts(mob/user, obj/item/storage/part_replacer/replacer_tool)
if(!istype(replacer_tool))
return FALSE
Expand Down
2 changes: 2 additions & 0 deletions code/game/objects/items/granters/chuuni_granter.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/// Turns the user into a chuunibyou.
/obj/item/book/granter/chuunibyou
starting_title = "I Found a Mysterious Book in the Library That Teaches Me How to Become a Chuunibyou, But It Turns Out It's Actually a Grimoire That Unlocks My Hidden Powers!"
starting_author = "Anonymous"
name = "I Found a Mysterious Book in the Library That Teaches Me How to Become a Chuunibyou, But It Turns Out It's Actually a Grimoire That Unlocks My Hidden Powers!"
desc = "I'd rather get caught holding a syndicate revolver, honestly."
icon_state ="chuuni_manga"
Expand Down
5 changes: 3 additions & 2 deletions code/game/objects/items/storage/bags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,9 @@
atom_storage.set_holdable(list(
/obj/item/book,
/obj/item/spellbook,
/obj/item/storage/book,
))
/obj/item/storage/book, //TG#75350 Refactors these to be just /obj/item/book, but it also add burning bibles. May look back at it another time
/obj/item/poster,
))

/*
* Trays - Agouri
Expand Down
58 changes: 56 additions & 2 deletions code/game/objects/objs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
/// Icon to use as a 32x32 preview in crafting menus and such
var/icon_preview
var/icon_state_preview
/// The vertical pixel offset applied when the object is anchored on a tile with table
/// Ignored when set to 0 - to avoid shifting directional wall-mounted objects above tables
var/anchored_tabletop_offset = 0

var/damtype = BRUTE
var/force = 0
Expand Down Expand Up @@ -62,6 +65,8 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
/obj/Initialize(mapload)
. = ..()

check_on_table()

if (id_tag)
GLOB.objects_by_id_tag[id_tag] = src
add_debris_element() //monkestation edit
Expand Down Expand Up @@ -352,7 +357,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
var/datum/reagent/R = reagent
. |= R.expose_obj(src, reagents[R])

///attempt to freeze this obj if possible. returns TRUE if it succeeded, FALSE otherwise.
/// Attempt to freeze this obj if possible. returns TRUE if it succeeded, FALSE otherwise.
/obj/proc/freeze()
if(HAS_TRAIT(src, TRAIT_FROZEN))
return FALSE
Expand All @@ -362,6 +367,55 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
AddElement(/datum/element/frozen)
return TRUE

///unfreezes this obj if its frozen
/// Unfreezes this obj if its frozen
/obj/proc/unfreeze()
SEND_SIGNAL(src, COMSIG_OBJ_UNFREEZE)

/// If we can unwrench this object; returns SUCCESSFUL_UNFASTEN and FAILED_UNFASTEN, which are both TRUE, or CANT_UNFASTEN, which isn't.
/obj/proc/can_be_unfasten_wrench(mob/user, silent)
if(!(isfloorturf(loc) || isindestructiblefloor(loc)) && !anchored)
to_chat(user, span_warning("[src] needs to be on the floor to be secured!"))
return FAILED_UNFASTEN
return SUCCESSFUL_UNFASTEN

/// Try to unwrench an object in a WONDERFUL DYNAMIC WAY
/obj/proc/default_unfasten_wrench(mob/user, obj/item/wrench, time = 20)
if((flags_1 & NODECONSTRUCT_1) || wrench.tool_behaviour != TOOL_WRENCH)
return CANT_UNFASTEN

var/turf/ground = get_turf(src)
if(!anchored && ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
to_chat(user, span_notice("You fail to secure [src]."))
return CANT_UNFASTEN
var/can_be_unfasten = can_be_unfasten_wrench(user)
if(!can_be_unfasten || can_be_unfasten == FAILED_UNFASTEN)
return can_be_unfasten
if(time)
to_chat(user, span_notice("You begin [anchored ? "un" : ""]securing [src]..."))
wrench.play_tool_sound(src, 50)
var/prev_anchored = anchored
//as long as we're the same anchored state and we're either on a floor or are anchored, toggle our anchored state
if(!wrench.use_tool(src, user, time, extra_checks = CALLBACK(src, PROC_REF(unfasten_wrench_check), prev_anchored, user)))
return FAILED_UNFASTEN
if(!anchored && ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
to_chat(user, span_notice("You fail to secure [src]."))
return CANT_UNFASTEN
to_chat(user, span_notice("You [anchored ? "un" : ""]secure [src]."))
set_anchored(!anchored)
check_on_table()
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored)
return SUCCESSFUL_UNFASTEN

/// For the do_after, this checks if unfastening conditions are still valid
/obj/proc/unfasten_wrench_check(prev_anchored, mob/user)
if(anchored != prev_anchored)
return FALSE
if(can_be_unfasten_wrench(user, TRUE) != SUCCESSFUL_UNFASTEN) //if we aren't explicitly successful, cancel the fuck out
return FALSE
return TRUE

/// Adjusts the vertical pixel offset when the object is anchored on a tile with table
/obj/proc/check_on_table()
if(anchored_tabletop_offset != 0 && !istype(src, /obj/structure/table) && locate(/obj/structure/table) in loc)
pixel_y = anchored ? anchored_tabletop_offset : initial(pixel_y)
13 changes: 12 additions & 1 deletion code/modules/admin/admin_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ GLOBAL_PROTECT(admin_verbs_admin)
/client/proc/view_player_camera,
/client/proc/log_viewer_new,
)
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel))
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel, /client/proc/library_control))
GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_direct_mob_sound, /client/proc/play_sound, /client/proc/set_round_end_sound))
GLOBAL_PROTECT(admin_verbs_sounds)
Expand Down Expand Up @@ -1085,3 +1085,14 @@ GLOBAL_PROTECT(admin_verbs_poll)
QDEL_NULL(segment.ai_controller)
segment.AddComponent(/datum/component/mob_chain, front = previous)
previous = segment

/client/proc/library_control()
set name = "Library Management"
set category = "Admin"
if(!check_rights(R_BAN))
return

if(!holder.library_manager)
holder.library_manager = new()
holder.library_manager.ui_interact(usr)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Library Management") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
1 change: 1 addition & 0 deletions code/modules/admin/holder2.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ GLOBAL_PROTECT(href_token)
var/datum/particle_editor/particle_test
var/datum/colorblind_tester/color_test = new
var/datum/plane_master_debug/plane_debug
var/obj/machinery/computer/libraryconsole/admin_only_do_not_map_in_you_fucker/library_manager

/// Whether or not the user tried to connect, but was blocked by 2FA
var/blocked_by_2fa = FALSE
Expand Down
3 changes: 0 additions & 3 deletions code/modules/fishing/fish_catalog.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
icon_state = "fishbook"
starting_content = "Lot of fish stuff" //book wrappers could use cleaning so this is not necessary

/obj/item/book/fish_catalog/on_read(mob/user)
ui_interact(user)

/obj/item/book/fish_catalog/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/food_and_drinks/machinery/coffeemaker.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
base_icon_state = "coffeemaker"
resistance_flags = FIRE_PROOF | ACID_PROOF
circuit = /obj/item/circuitboard/machine/coffeemaker
pixel_y = 4 //needed to make it sit nicely on tables
anchored_tabletop_offset = 4
var/obj/item/reagent_containers/cup/coffeepot/coffeepot = null
var/brewing = FALSE
var/brew_time = 20 SECONDS
Expand Down
15 changes: 1 addition & 14 deletions code/modules/food_and_drinks/machinery/microwave.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
pass_flags = PASSTABLE
light_color = LIGHT_COLOR_DIM_YELLOW
light_power = 3
anchored_tabletop_offset = 6
var/wire_disabled = FALSE // is its internal wire cut?
var/operating = FALSE
/// How dirty is it?
Expand Down Expand Up @@ -53,8 +54,6 @@
set_wires(new /datum/wires/microwave(src))
create_reagents(100)
soundloop = new(src, FALSE)
set_on_table()

update_appearance(UPDATE_ICON)

/obj/machinery/microwave/Exited(atom/movable/gone, direction)
Expand All @@ -78,10 +77,6 @@
QDEL_NULL(soundloop)
return ..()

/obj/machinery/microwave/set_anchored(anchorvalue)
. = ..()
set_on_table()

/obj/machinery/microwave/RefreshParts()
. = ..()
efficiency = 0
Expand Down Expand Up @@ -518,14 +513,6 @@
open = FALSE
update_appearance()

/// Go on top of a table if we're anchored & not varedited
/obj/machinery/microwave/proc/set_on_table()
var/obj/structure/table/counter = locate(/obj/structure/table) in get_turf(src)
if(anchored && counter && !pixel_y)
pixel_y = 6
else if(!anchored)
pixel_y = initial(pixel_y)

/// Type of microwave that automatically turns it self on erratically. Probably don't use this outside of the holodeck program "Microwave Paradise".
/// You could also live your life with a microwave that will continously run in the background of everything while also not having any power draw. I think the former makes more sense.
/obj/machinery/microwave/hell
Expand Down
2 changes: 2 additions & 0 deletions code/modules/food_and_drinks/machinery/processor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
icon_state = "processor1"
layer = BELOW_OBJ_LAYER
density = TRUE
pass_flags = PASSTABLE
circuit = /obj/item/circuitboard/machine/processor
anchored_tabletop_offset = 8
///Is the processor blending items at the moment
var/processing = FALSE
///The speed at which the processor processes items
Expand Down
Loading

0 comments on commit 110a42e

Please sign in to comment.