Merge pull request #12105 from MrPerson/ntsl_is_kill

Removes NTSL
This commit is contained in:
Aranclanos
2015-10-03 09:08:22 -03:00
30 changed files with 45 additions and 3754 deletions
@@ -4017,7 +4017,7 @@
"bzm" = (/obj/machinery/atmospherics/pipe/manifold/supply/hidden{dir = 8},/turf/simulated/wall/r_wall,/area/atmos)
"bzn" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/wall/r_wall,/area/atmos)
"bzo" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 10},/turf/simulated/wall/r_wall,/area/atmos)
"bzp" = (/obj/machinery/computer/telecomms/traffic{network = "tcommsat"},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/tcommsat/computer{name = "\improper Telecoms Control Room"})
"bzp" = (/obj/structure/table/wood/poker,/obj/effect/spawner/lootdrop{loot = list(/obj/item/weapon/gun/projectile/revolver/russian = 5, /obj/item/weapon/storage/box/throwing_stars, /obj/item/toy/cards/deck/syndicate = 2); name = "gambling valuables spawner"},/turf/simulated/floor/wood,/area/crew_quarters/bar)
"bzq" = (/obj/machinery/atmospherics/components/unary/vent_pump{dir = 4; on = 1},/obj/structure/stool/bed/chair/office/dark{dir = 1},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/tcommsat/computer{name = "\improper Telecoms Control Room"})
"bzr" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/tcommsat/computer{name = "\improper Telecoms Control Room"})
"bzs" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/manifold/supply/hidden{dir = 4},/turf/simulated/floor/plasteel{icon_state = "grimy"},/area/tcommsat/computer{name = "\improper Telecoms Control Room"})
@@ -8094,9 +8094,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaaaaYobabaYoaYoaYoaYoaYoaYobabaYoaaaaSJbrZbsabsbbcdbscbsdbsebsdbsfbcdbsgbshbsibsjbskbslbsmbsjbsjbsnbsobspbsqbsjbsjbsrbsjbsjbsjbssbstbsubsubsvbswbsxbsybmnbszbsAbsBbmnbsCbsDbsEbsFbsGbqvbsHbqqbsIbsJbsKbsLbsMbsLbsNbsObsPbsQbsRbsSbsTbdNbsUbsVbsWbsXbsYbdNbdNbdNbsZbtabtbboFbtcbtdbteboFbtfbtgbthbtibtjbtkbtlbtmbtnbtobtpbtqbtrbtsbttbtubtvbtwalwboMbtxbtybjFbtzbtAbtBbtCbtDbtEbtFbtGbtHbnebtIbtJbtKbtLbtMaOxaaaaaabtNbpiaafaaaaaaaafaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaafaaaaaabtObtPbpfaafbtQbtRbtSbtTbtUbtVbtWbtXbtYbtZbuabubbucbudbuebufbugbubbuhbuibujbukaSHbhYbulaPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaYoaafaaaaafaaaaYobumaYobunbuobbzbupaYobumaYoaYoaSJbdmbuqburbcdbusbsdbutbsdbuubcdbuvbuwbuxbuybuzbuAbuBbuCbuDbuEbuFbuGbuzbuzbuzbuHbuzbuIbuJbuBbuKbuzbuzbuLbuMbuNbsybmnbuObuPbuQbuRbuSbuTbuSbuSbsGbuUbuVbuWbuWbuWbuXbuYbuZbvabvbbuWbuWbuWbvcbvdbhebdNbvebvfbvgbvhbvibdNbvjbvkbvlbvmbtbboDbvnbvobvpboFbvqbvrbvsbvtboGboGalwalwbvualwalwalwbvvbvwalwalwbvxbvyalwbvzbtxbvAbjFbfVbfVbfVbfVbvBbfVbfVbvCbvDbvEbjFbjFbvFbvGbvHbvIaaabpgbvJaaaaafaaaaaaaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafbvKbvLbnkbvMbvNbnnaPZbnpaPWaPXaSHaSHaSHbvObvObvObvPbvQbvObvObvObvOaSHaSHaSHaSHaaaaOraPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaYoaYobaaaYoaSJaYobabaYobvRaWObvSbvTaYobabaYobvUbvVbvWbpIbpJbcdbvXbvYbpMbvYbvZbcdbwabwbbwcbcdbwdbwebwfbcdalQbwgalQbwhbwhbwibwjbwkbwibwhbwhbwhbwhbwhbwhbwlbwmbwnbwobwpbwqbwrbwsbwtbwsbwubwvbwwbwxbwybwzbwAbwBbwAbwAbwCbwDbwEbuWbuWbwFbuWbwGbwHbdNbwIbwJbwKbhjbwLbwMbdNbwNbdKbwOaXBbwPboFboFboFboFboFbwQbwRboGboGboGbwSbwTboGbwUbwVbwWalwavEbwXalwbwYbwZbxabxbbxcbxdbxebxfbxgbxhbxibxjbxkbxlbfVbxmbxnbxobxpbxqbxrbxsbxtbxubpdbvMbxvaafaafaafaafaafaaaaafaaaaafaaaaafaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaobaOrbnpaQaaaaaaabxwaSHbvObxxbxybxzbxAbxBbxCbxDbvOaSHbxwaaaaaaaaaaOraPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaYobxEaWOaWQbxFbxGaWOaWObxHbxIaYtbxJbxKbxKbxKbxLbxMbxNbxObxPbxQbxRbxSbxTbxUbxVbxQbxWbxXbxYbxZbxZbyabxZbxZaombybbycbwhbydbyebyfbygbyhbwhbyibyjbwhbyibyjbwhbykbcfbgRbmnbylbymbynbyobypbyqbyrbysbsGbytbyubuWbyvbywbyxbkObkObwHbyybyzbyAbuWbyBbyCbdNbyDbyEbyFbyGbyHbyIbyJbyKbdKbfubyLbyMboGbyNbyObyPbyQbyRbySbyTboGbyUbyVbyWbyXbyYbyZbzaalwalwalwalwalwalwbzbalwbzcbzdbzebzfbzgbzgbzgbzgbzgbzfbzfbzgbzhbzibzjbzkbzlbzmbznbzobzfbzfbzfaafaaaaaaaaaaafaaaaafaaaaafaaaaaiaaaaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaobaOrbnpbeuaNiaaaaaaaSHbvObzpbzqbzrbzsbztbzubzvbvOaSHaaaaaaaNiaNibnoaPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaYobxEaWOaWQbxFbxGaWOaWObxHbxIaYtbxJbxKbxKbxKbxLbxMbxNbxObxPbxQbxRbxSbxTbxUbxVbxQbxWbxXbxYbxZbxZbyabxZbxZaombybbycbwhbydbyebyfbygbyhbwhbyibyjbwhbyibyjbwhbykbcfbgRbmnbylbymbynbyobypbyqbyrbysbsGbytbyubuWbyvbywbyxbkObkObwHbyybyzbyAbuWbyBbyCbdNbyDbyEbyFbyGbyHbyIbyJbyKbdKbfubyLbyMboGbyNbyObyPbyQbyRbySbyTboGbyUbyVbyWbyXbyYbyZbzaalwalwalwalwalwalwbzbalwbzcbzdbzebzfbzgbzgbzgbzgbzgbzfbzfbzgbzhbzibzjbzkbzlbzmbznbzobzfbzfbzfaafaaaaaaaaaaafaaaaafaaaaafaaaaaiaaaaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaobaOrbnpbeuaNiaaaaaaaSHbvObztbzqbzrbzsbztbzubzvbvOaSHaaaaaaaNiaNibnoaPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaYoaYpaYqaYqbzwaYqbzxbzybzzbzzbzAbzzbzBbzCbzDbzEbzFbzGbzHbzIblMbzJbzKbzLbzMbzNbzObzPbzQbzRbzSbzTbzUbzVbxZbzWbzXaoibwhbzYbzZbyfbygbyhbwhbAabAbbwhbAabAbbwhbAcbfvbmmbmnbmnbAdbmnbmnbmnbAebAfbmnbmnbAgbAhbAibkObsLbsLbAjbAkbAlbAmbAnbAobApbAqbArbAsbhjbAtbAubAvbAwbAxbdNbAybdKbAzaXBbAAboGbABbACbyRbADbyRbAEbyRbAFbAGbzabAHbAIbAJbAKbALbAMbANbAObAPbAQbARbASalwbATbtxbAUbzfbAVbAWbAXbAYbAZbzfbBabBbbBcbBdbBebBfbBgbBhbBibBjbBkbBlbzfaafaafaafaafaafaafaafaaaaaiaaabBmaaabBnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaobaVfbBobBpbBqaViaVjaSHbvObBrbBsbBtbBubBvbBwbBxbvOaSHaVjaVobBybggbggbBzaOxaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaYoaYoaSJaYobaaaYoaSJaYoaYoaYoaSJaYoaSJaSJaSJbkgbkhalQbBAalQalQbBBbBCbBBbBDbBBbBBbBBbBBbxZbxZbBEbBFbxZbxZbxZbBGalIbwhbBHbBIbyfbBJbwhbwhbBKbwhbwhbBLbwhbwhbBMbcfbgRbBNbBObBPbBQbBRbBSbBPbBTbBUbBVbwHbBWbwAbBXbsLbBYbBZbCabCbbCcbsLbCdbuWbCebCfbdNbCgbChbhjbCibCjbCkbdNbClbdKbdPaXBbAAboGbCmbCnbCobCnbCpbCqbCrbCsbAGbzabCtbCubzabAGbCvbCwbCxbCybCzbCAbARbvyalwbCBbCCbCDbCEbCFbCGbCHbCIbCJbzfbCKbCLbCMbCNbBebCObCPbCQbCRbCSbCTbCUbzfaafbCVbCVbCVbCVbCVaafaaabBnaaabBmaaabBnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaobaaabCWbCXaPVaQaaaaaSHbvObCYbCZbDabDbbDcbDdbDebvOaSHaaaaOraPVaWEbhYbDfaaaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaYoaYoaSJaYobaaaYoaSJaYoaYoaYoaSJaYoaSJaSJaSJbkgbkhalQbBAalQalQbBBbBCbBBbBDbBBbBBbBBbBBbxZbxZbBEbBFbxZbxZbxZbBGalIbwhbBHbBIbyfbBJbwhbwhbBKbwhbwhbBLbwhbwhbBMbcfbgRbBNbBObBPbBQbBRbBSbBPbBTbBUbBVbwHbBWbwAbBXbsLbBYbBZbCabCbbCcbsLbCdbuWbCebCfbdNbCgbChbhjbCibCjbCkbdNbClbdKbdPaXBbAAboGbCmbCnbCobCnbCpbCqbCrbCsbAGbzabCtbzpbzabAGbCvbCwbCxbCybCzbCAbARbvyalwbCBbCCbCDbCEbCFbCGbCHbCIbCJbzfbCKbCLbCMbCNbBebCObCPbCQbCRbCSbCTbCUbzfaafbCVbCVbCVbCVbCVaafaaabBnaaabBmaaabBnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaobaaabCWbCXaPVaQaaaaaSHbvObCYbCZbDabDbbDcbDdbDebvOaSHaaaaOraPVaWEbhYbDfaaaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaYobDgbdmbDhalQbybauRbDibBBbDjbDkbDlbDmbDnbDobBBbDpbDpbDqbDrbDsbDtbxZbBGbDubwhbDvbDwbyfbygbDxbDybBIbDzbDAbDBbDCbwibwmbcfbgRbDDbDEbDFbDGbDGbDGbDGbDHbBVbDIbDJbDKbhebhebDLbDMbDNbDObDPbDQbDLbhebhebDRbDJbDSbdNbAsbdNbdNbdNbdObdNbDTbDUbDVbDWbAAbDXbDYbDYbDYbDZbDYbEabDYbEbbAGbAGbEcbAGbAGbzabEdbEebEfbEgbEhbEibARbzbalwbEjbCCbEkbElbEmbEnbEobEpbEqbErbEsbEtbEubEvbBebEwbExbEybEzbEAbEBbECbEDbEEbEFbEGbEHbEHbCVaafaaabBnaaabBmaaaaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaobaobaobaOraPVaQaaaaaSHbEIbEIbEIbEJbEKbEJbEIbEIbEIaSHaaaaOraPVaQaaobaobaobaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabELaYoaYobdmbEMalQbENbEObEPbBBbEQbDkbDlbERbESbETbBBbEUbEVbEWbEXbxZbxZbxZbBGapHbwhbEYbEZbyfbygbyfbyfbyfbyfbyfbFabyfbwjbFbbFcbFdbFebFfbFgbFfbFhbFfbFgbFibFfbFjbFkbFlbFmbFnbFobFpbFpbFqbFrbFpbFsbFtbFubFvbFwbFxbFobFybFzbFobFAbFBbFobFCbFDbFEbFFbFGbFHbyRbFIbyRbFJbyRbFKbyRbFLbAGbAGbFMbAGbAGbFNbFObEebFPbANbEhbFQbARbzbalwbFRbFSbvAbCEbFTbEnbFUbEnbFVbFWbFXbFYbFZbGabBebGbbGcbGdbGebGfbGgbGhbBeaafbBebGibEHbGjbCVaafaaabBnaaabBmaaabBnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaobaOraPVaQaaaaaSHbGkbGlbGmbEJbGnbEJbGobGlbGpaSHaaaaOraPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGqbGrbGsbGrbdmbGtalQbGubGvakubBBbGwbDkbDlbGxbDkbGybBBbxZbGzbxZbDrbGAbGBbxZbBGapFbwhbGCbDwbGDbGEbGFbGFbGFbGFbGFbGGbGFbGHbuMbGIbGJbGKbGLbGMbGLbGNbGObGPbGQbGLbGRbGSbGTbGUbGVbGUbGWbGWbGXbGYbGWbGZbHabHbbHcbHdbHebHfbHgbHhbHibHjbHkbHdbHlbHmbHnbHobHpbHqbHrbHsbHtbHtbHubHvbHrbHwbHxbHybHzbzabHAbzabHBbHCbHDbHEbHFbHGbHHbHIalwbHJbHKbHLbHMbHNbHObHPbHQbHRbBebHSbHTbHUbHVbHWbHXbHYbHZbIabIbbIcbIdbIebIfbIgbIhbEHbIibCVaafaaabBnaaabBmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaobaOraPVaQaaaaaSHbIjbIkbIlbEJbEKbEJbIlbIkbImaSHaaaaOraPVaQaaobaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+1 -2
View File
@@ -1565,7 +1565,6 @@
"EI" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/wall/r_wall,/area/tcommsat/computer)
"EJ" = (/turf/simulated/wall/r_wall,/area/engine/gravity_generator)
"EL" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 9},/turf/simulated/wall/r_wall,/area/tcommsat/computer)
"EM" = (/obj/machinery/computer/telecomms/traffic{network = "tcommsat"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "yellow"},/area/tcommsat/computer)
"EO" = (/obj/machinery/atmospherics/components/unary/vent_pump{dir = 2; on = 1},/turf/simulated/floor/plasteel,/area/tcommsat/computer)
"EP" = (/obj/structure/table,/obj/item/weapon/paper_bin,/obj/item/weapon/paper/monitorkey,/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor/plasteel,/area/tcommsat/computer)
"EQ" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/gravity_generator)
@@ -1851,7 +1850,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaEeEfamamamamamamamamamamamamamamamamamamamambLbLEgEhEgEhEhEhEhEhEiEjEkElEmuhEoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaEpEqCqErCqCqCqCqCqCqErCqCqCqCqErEsEtEfamEaEaEaEaEaEaEaEuEvEwEwEwExEyEzEAAkEaamamaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamCoEBEfuREhEhEDEhEhEhEhEEEFEGEGEHEIEhEJEJEJEJEJEJEJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamCoCAuREhEhEvEwEwEwEwELEMDkEOEPEIEhEJEQERESETEQEJamaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamCoCAuREhEhEvEwEwEwEwELGtDkEOEPEIEhEJEQERESETEQEJamaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamEauwEaEhEhEEsFrUGPEWEaEYEZFaFbFcFdEJFeFfEQFfFgEJamamaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamuRFhFiEhDlELFkEVEVEVEauRvnFnuREIFpEJFqFrFsFtFuEJamamamamamaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamuRFwEhEhEhFxFyFzFAEVFBFCFDFEFFEIFpEJFGFHEQFIDmEJamaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -5231,7 +5231,7 @@
"bWE" = (/obj/machinery/telecomms/processor/preset_three,/turf/simulated/floor/bluegrid{icon_state = "dark"; name = "Mainframe Floor"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/server)
"bWF" = (/obj/machinery/light{dir = 1},/obj/machinery/power/apc{cell_type = 5000; dir = 1; name = "Telecoms Server APC"; pixel_x = 0; pixel_y = 25},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/server)
"bWG" = (/obj/machinery/telecomms/server/presets/security,/turf/simulated/floor/bluegrid{icon_state = "dark"; name = "Mainframe Floor"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/server)
"bWH" = (/obj/machinery/computer/message_monitor,/turf/simulated/floor/plasteel{dir = 9; icon_state = "yellow"},/area/tcommsat/computer)
"bWH" = (/obj/structure/table,/turf/simulated/floor/plasteel{dir = 9; icon_state = "yellow"},/area/tcommsat/computer)
"bWI" = (/obj/structure/window/reinforced/fulltile,/obj/structure/grille,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating,/area/tcommsat/computer)
"bWJ" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{tag = "icon-manifold-r-f (NORTH)"; dir = 1},/turf/simulated/floor/plasteel,/area/hallway/primary/aft)
"bWK" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/turf/simulated/floor/plasteel{dir = 8; icon_state = "yellow"},/area/hallway/primary/aft)
@@ -5280,7 +5280,7 @@
"bXB" = (/obj/machinery/telecomms/bus/preset_three,/turf/simulated/floor/bluegrid{icon_state = "dark"; name = "Mainframe Floor"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/server)
"bXC" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/server)
"bXD" = (/obj/machinery/telecomms/server/presets/command,/turf/simulated/floor/bluegrid{icon_state = "dark"; name = "Mainframe Floor"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/server)
"bXE" = (/obj/machinery/computer/telecomms/traffic{network = "tcommsat"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "yellow"},/area/tcommsat/computer)
"bXE" = (/obj/machinery/computer/message_monitor,/turf/simulated/floor/plasteel{dir = 8; icon_state = "yellow"},/area/tcommsat/computer)
"bXF" = (/obj/structure/window/reinforced/fulltile,/obj/structure/grille,/obj/structure/cable{icon_state = "0-2"; d2 = 2},/obj/structure/cable,/turf/simulated/floor/plating,/area/tcommsat/computer)
"bXG" = (/turf/simulated/floor/plasteel,/area/tcommsat/computer)
"bXH" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/manifold4w/scrubbers,/turf/simulated/floor/plasteel,/area/engine/break_room)
@@ -193,16 +193,6 @@
name = "circuit board (Telecommunications Server Monitor)"
build_path = /obj/machinery/computer/telecomms/server
origin_tech = "programming=3"
/obj/item/weapon/circuitboard/comm_traffic
name = "circuitboard (Telecommunications Traffic Control)"
build_path = /obj/machinery/computer/telecomms/traffic
origin_tech = "programming=3"
/*/obj/item/weapon/circuitboard/curefab
name = "circuit board (Cure fab)"
build_path = /obj/machinery/computer/curer
/obj/item/weapon/circuitboard/splicer
name = "circuit board (Disease Splicer)"
build_path = /obj/machinery/computer/diseasesplicer*/
/obj/item/weapon/circuitboard/shuttle
name = "circuit board (Shuttle)"
build_path = /obj/machinery/computer/shuttle
@@ -1,286 +0,0 @@
/obj/machinery/computer/telecomms/traffic
name = "telecommunications traffic control console"
var/screen = 0 // the screen number:
var/list/servers = list() // the servers located by the computer
var/mob/editingcode
var/mob/lasteditor
var/list/viewingcode = list()
var/obj/machinery/telecomms/server/SelectedServer
var/network = "NULL" // the network to probe
var/temp = "" // temporary feedback messages
var/storedcode = "" // code stored
var/obj/item/weapon/card/id/auth = null
var/list/access_log = list()
var/process = 0
circuit = "/obj/item/weapon/circuitboard/comm_traffic"
req_access = list(access_tcomsat)
/obj/machinery/computer/telecomms/traffic/proc/stop_editing()
if(editingcode)
if(editingcode.client)
winshow(editingcode, "Telecomms IDE", 0) // hide the window!
editingcode.unset_machine()
editingcode = null
/obj/machinery/computer/telecomms/traffic/process()
if(stat & (NOPOWER|BROKEN))
stop_editing()
return
if(editingcode && editingcode.machine != src)
stop_editing()
return
if(!editingcode)
if(length(viewingcode) > 0)
editingcode = pick(viewingcode)
viewingcode.Remove(editingcode)
return
process = !process
if(!process)
return
// loop if there's someone manning the keyboard
if(!editingcode.client)
stop_editing()
return
// For the typer, the input is enabled. Buffer the typed text
storedcode = "[winget(editingcode, "tcscode", "text")]"
winset(editingcode, "tcscode", "is-disabled=false")
// If the player's not manning the keyboard anymore, adjust everything
if(!in_range(editingcode, src) && !issilicon(editingcode) || editingcode.machine != src)
winshow(editingcode, "Telecomms IDE", 0) // hide the window!
editingcode = null
return
// For other people viewing the typer type code, the input is disabled and they can only view the code
// (this is put in place so that there's not any magical shenanigans with 50 people inputting different code all at once)
if(length(viewingcode))
// This piece of code is very important - it escapes quotation marks so string aren't cut off by the input element
var/showcode = replacetext(storedcode, "\\\"", "\\\\\"")
showcode = replacetext(storedcode, "\"", "\\\"")
for(var/mob/M in viewingcode)
if( (M.machine == src && in_range(M, src) ) || issilicon(M))
winset(M, "tcscode", "is-disabled=true")
winset(M, "tcscode", "text=\"[showcode]\"")
else
viewingcode.Remove(M)
winshow(M, "Telecomms IDE", 0) // hide the windows
/obj/machinery/computer/telecomms/traffic/attack_hand(mob/user)
if(..())
return
user.set_machine(src)
var/dat = "<TITLE>Telecommunication Traffic Control</TITLE><center><b>Telecommunications Traffic Control</b></center>"
dat += "<br><b><font color='[(auth ? "green" : "red")]'>[(auth ? "AUTHED" : "NOT AUTHED")]:</font></b> <A href='?src=\ref[src];auth=1'>[(!auth ? "Insert ID" : auth)]</A><BR>"
dat += "<A href='?src=\ref[src];print=1'>View System Log</A><HR>"
if(issilicon(user) || auth)
switch(screen)
// --- Main Menu ---
if(0)
dat += "<br>[temp]<br>"
dat += "<br>Current Network: <a href='?src=\ref[src];network=1'>[network]</a><br>"
if(servers.len)
dat += "<br>Detected Telecommunication Servers:<ul>"
for(var/obj/machinery/telecomms/T in servers)
dat += "<li><a href='?src=\ref[src];viewserver=[T.id]'>\ref[T] [T.name]</a> ([T.id])</li>"
dat += "</ul>"
dat += "<br><a href='?src=\ref[src];operation=release'>\[Flush Buffer\]</a>"
else
dat += "<br>No servers detected. Scan for servers: <a href='?src=\ref[src];operation=scan'>\[Scan\]</a>"
// --- Viewing Server ---
if(1)
if(SelectedServer)
dat += "<br>[temp]<br>"
dat += "<center><a href='?src=\ref[src];operation=mainmenu'>\[Main Menu\]</a> <a href='?src=\ref[src];operation=refresh'>\[Refresh\]</a></center>"
dat += "<br>Current Network: [network]"
dat += "<br>Selected Server: [SelectedServer.id]<br><br>"
dat += "<br><a href='?src=\ref[src];operation=editcode'>\[Edit Code\]</a>"
dat += "<br>Signal Execution: "
if(SelectedServer.autoruncode)
dat += "<a href='?src=\ref[src];operation=togglerun'>ALWAYS</a>"
else
dat += "<a href='?src=\ref[src];operation=togglerun'>NEVER</a>"
else
screen = 0
return
user << browse(dat, "window=traffic_control;size=575x400")
onclose(user, "server_control")
temp = ""
return
/obj/machinery/computer/telecomms/traffic/proc/create_log(entry, mob/user)
var/id = null
if(issilicon(user))
id = "System Administrator"
else
if(auth)
id = "[auth.registered_name] ([auth.assignment])"
else
throw EXCEPTION("null auth while the user isn't a silicon")
return
access_log += "\[[get_timestamp()]\] [id] [entry]"
/obj/machinery/computer/telecomms/traffic/proc/print_logs()
. = "<center><h2>Traffic Control Telecomms System Log</h2></center><HR>"
for(var/entry in access_log)
. += entry + "<BR>"
return .
/obj/machinery/computer/telecomms/traffic/Topic(href, href_list)
if(..())
return
add_fingerprint(usr)
usr.set_machine(src)
if(href_list["auth"])
if(iscarbon(usr))
var/mob/living/carbon/C = usr
if(!auth)
var/obj/item/weapon/card/id/I = C.get_active_hand()
if(istype(I))
if(check_access(I))
if(!C.drop_item())
return
I.loc = src
auth = I
create_log("has logged in.", usr)
else
create_log("has logged out.", usr)
auth.loc = src.loc
C.put_in_hands(auth)
auth = null
updateUsrDialog()
return
if(href_list["print"])
usr << browse(print_logs(), "window=traffic_logs")
return
if(!auth && !issilicon(usr) && !emagged)
usr << "<span class='danger'>ACCESS DENIED.</span>"
return
if(href_list["viewserver"])
screen = 1
for(var/obj/machinery/telecomms/T in servers)
if(T.id == href_list["viewserver"])
SelectedServer = T
create_log("selected server [T.name]", usr)
break
if(href_list["operation"])
create_log("has performed action: [href_list["operation"]].", usr)
switch(href_list["operation"])
if("release")
servers = list()
screen = 0
if("mainmenu")
screen = 0
if("scan")
if(servers.len > 0)
temp = "<font color = #D70B00>- FAILED: CANNOT PROBE WHEN BUFFER FULL -</font color>"
else
for(var/obj/machinery/telecomms/server/T in range(25, src))
if(T.network == network)
servers.Add(T)
if(!servers.len)
temp = "<font color = #D70B00>- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -</font color>"
else
temp = "<font color = #336699>- [servers.len] SERVERS PROBED & BUFFERED -</font color>"
screen = 0
if("editcode")
if(editingcode == usr) return
if(usr in viewingcode) return
if(!editingcode)
lasteditor = usr
editingcode = usr
winshow(editingcode, "Telecomms IDE", 1) // show the IDE
winset(editingcode, "tcscode", "is-disabled=false")
winset(editingcode, "tcscode", "text=\"\"")
var/showcode = replacetext(storedcode, "\\\"", "\\\\\"")
showcode = replacetext(storedcode, "\"", "\\\"")
winset(editingcode, "tcscode", "text=\"[showcode]\"")
else
viewingcode.Add(usr)
winshow(usr, "Telecomms IDE", 1) // show the IDE
winset(usr, "tcscode", "is-disabled=true")
winset(editingcode, "tcscode", "text=\"\"")
var/showcode = replacetext(storedcode, "\"", "\\\"")
winset(usr, "tcscode", "text=\"[showcode]\"")
if("togglerun")
SelectedServer.autoruncode = !(SelectedServer.autoruncode)
if(href_list["network"])
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
if(newnet && canAccess(usr))
if(length(newnet) > 15)
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
else
network = newnet
screen = 0
servers = list()
temp = "<font color = #336699>- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -</font color>"
create_log("has set the network to [network].", usr)
updateUsrDialog()
return
/obj/machinery/computer/telecomms/traffic/attackby()
..()
src.updateUsrDialog()
return
/obj/machinery/computer/telecomms/traffic/emag_act(mob/user)
if(!emagged)
playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
user << "<span class='notice'>You you disable the security protocols.</span>"
/obj/machinery/computer/telecomms/traffic/proc/canAccess(mob/user)
if(issilicon(user) || in_range(user, src))
return 1
return 0
@@ -25,10 +25,6 @@
var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes)
var/list/memory = list() // stored memory
var/rawcode = "" // the code to compile (raw text)
var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code
var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up
var/encryption = "null" // encryption key: ie "password"
var/salt = "null" // encryption salt: ie "123comsat"
@@ -46,17 +42,8 @@
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
RefreshParts()
Compiler = new()
Compiler.Holder = src
server_radio = new()
/obj/machinery/telecomms/server/Destroy()
// Garbage collects all the NTSL datums.
if(Compiler)
Compiler.GC()
Compiler = null
return ..()
/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
if(signal.data["message"])
@@ -103,34 +90,10 @@
var/identifier = num2text( rand(-1000,1000) + world.time )
log.name = "data packet ([md5(identifier)])"
if(Compiler && autoruncode)
Compiler.Run(signal) // execute the code
var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub")
if(!can_send)
relay_information(signal, "/obj/machinery/telecomms/broadcaster")
/obj/machinery/telecomms/server/proc/setcode(t)
if(t)
if(istext(t))
rawcode = t
/obj/machinery/telecomms/server/proc/admin_log(mob/mob)
var/msg="[key_name(mob)] has compiled a script to server [src]:"
diary << msg
diary << rawcode
src.investigate_log("[msg]<br>[rawcode]", "ntsl")
if(length(rawcode)) // Let's not bother the admins for empty code.
message_admins("[key_name_admin(mob)] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) has compiled and uploaded a NTSL script to [src.id]",0,1)
/obj/machinery/telecomms/server/proc/compile(mob/user)
if(Compiler)
admin_log(user)
return Compiler.Compile(rawcode)
/obj/machinery/telecomms/server/proc/update_logs()
// start deleting the very first log entry
if(logs >= 400)
-2
View File
@@ -60,7 +60,6 @@ var/list/admin_verbs_admin = list(
/client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/
/client/proc/cmd_admin_local_narrate, //sends text to all mobs within view of atmo
/client/proc/cmd_admin_create_centcom_report,
/client/proc/reset_all_tcs /*resets all telecomms scripts*/
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -206,7 +205,6 @@ var/list/admin_verbs_hideable = list(
/proc/possess,
/proc/release,
/client/proc/reload_admins,
/client/proc/reset_all_tcs,
/client/proc/panicbunker,
/client/proc/admin_change_sec_level,
/client/proc/toggle_nuke,
-21
View File
@@ -685,27 +685,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/reset_all_tcs()
set category = "Admin"
set name = "Reset Telecomms Scripts"
set desc = "Blanks all telecomms scripts from all telecomms servers"
if(!holder)
usr << "Admin only."
return
var/confirm = alert(src, "You sure you want to blank all NTSL scripts?", "Confirm", "Yes", "No")
if(confirm !="Yes") return
for(var/obj/machinery/telecomms/server/S in telecomms_list)
var/datum/TCS_Compiler/C = S.Compiler
S.rawcode = ""
C.Compile("")
for(var/obj/machinery/computer/telecomms/traffic/T in machines)
T.storedcode = ""
log_admin("[key_name(usr)] blanked all telecomms scripts.")
message_admins("[key_name_admin(usr)] blanked all telecomms scripts.")
feedback_add_details("admin_verb","RAT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_change_sec_level()
set category = "Special Verbs"
set name = "Set Security Level"
@@ -301,16 +301,6 @@
build_path = /obj/item/weapon/circuitboard/message_monitor
category = list("Computer Boards")
/datum/design/comm_traffic
name = "Computer Design (Telecommunications Traffic Control Console)"
desc = "Allows for the construction of circuit boards used to build a telecommunications traffic control console."
id = "comm_traffic"
req_tech = list("programming" = 3)
build_type = IMPRINTER
materials = list(MAT_GLASS = 1000, "sacid" = 20)
build_path = /obj/item/weapon/circuitboard/comm_traffic
category = list("Computer Boards")
/datum/design/aifixer
name = "Computer Design (AI Integrity Restorer)"
desc = "Allows for the construction of circuit boards used to build an AI Integrity Restorer."
-139
View File
@@ -1,139 +0,0 @@
/*
File: AST Nodes
An abstract syntax tree (AST) is a representation of source code in a computer-friendly format. It is composed of nodes,
each of which represents a certain part of the source code. For example, an <IfStatement> node represents an if statement in the
script's source code. Because it is a representation of the source code in memory, it is independent of any specific scripting language.
This allows a script in any language for which a parser exists to be run by the interpreter.
The AST is produced by an <n_Parser> object. It consists of a <GlobalBlock> with an arbitrary amount of statements. These statements are
run in order by an <n_Interpreter> object. A statement may in turn run another block (such as an if statement might if its condition is
met).
Articles:
- <http://en.wikipedia.org/wiki/Abstract_syntax_tree>
*/
var
const
/*
Constants: Operator Precedence
OOP_OR - Logical or
OOP_AND - Logical and
OOP_BIT - Bitwise operations
OOP_EQUAL - Equality checks
OOP_COMPARE - Greater than, less then, etc
OOP_ADD - Addition and subtraction
OOP_MULTIPLY - Multiplication and division
OOP_POW - Exponents
OOP_UNARY - Unary Operators
OOP_GROUP - Parentheses
*/
OOP_OR = 1 //||
OOP_AND = OOP_OR + 1 //&&
OOP_BIT = OOP_AND + 1 //&, |
OOP_EQUAL = OOP_BIT + 1 //==, !=
OOP_COMPARE = OOP_EQUAL + 1 //>, <, >=, <=
OOP_ADD = OOP_COMPARE + 1 //+, -
OOP_MULTIPLY= OOP_ADD + 1 //*, /, %
OOP_POW = OOP_MULTIPLY+ 1 //^
OOP_UNARY = OOP_POW + 1 //!
OOP_GROUP = OOP_UNARY + 1 //()
/*
Class: node
*/
/node
proc
ToString()
return "[src.type]"
/*
Class: identifier
*/
/node/identifier
var
id_name
New(id)
.=..()
src.id_name=id
ToString()
return id_name
/*
Class: expression
*/
/node/expression
/*
Class: operator
See <Binary Operators> and <Unary Operators> for subtypes.
*/
/node/expression/operator
var
node/expression/exp
tmp
name
precedence
New()
.=..()
if(!src.name) src.name="[src.type]"
ToString()
return "operator: [name]"
/*
Class: FunctionCall
*/
/node/expression/FunctionCall
//Function calls can also be expressions or statements.
var
func_name
node/identifier/object
list/parameters=new
/*
Class: literal
*/
/node/expression/value/literal
var
value
New(value)
.=..()
src.value=value
ToString()
return src.value
/*
Class: variable
*/
/node/expression/value/variable
var
node
object //Either a node/identifier or another node/expression/value/variable which points to the object
node/identifier
id
New(ident)
.=..()
id=ident
if(istext(id))id=new(id)
ToString()
return src.id.ToString()
/*
Class: reference
*/
/node/expression/value/reference
var
datum/value
New(value)
.=..()
src.value=value
ToString()
return "ref: [src.value] ([src.value.type])"
-48
View File
@@ -1,48 +0,0 @@
/*
File: Block Types
*/
/*
Class: BlockDefinition
An object representing a set of actions to perform independently from the rest of the script. Blocks are basically just
lists of statements to execute which also contain some local variables and methods. Note that since functions are local to a block,
it is possible to have a function definition inside of any type of block (such as in an if statement or another function),
and not just in the global scope as in many languages.
*/
/node/BlockDefinition
var/list
statements = new
functions = new
initial_variables = new
proc
/*
Proc: SetVar
Defines a permanent variable. The variable will not be deleted when it goes out of scope.
Notes:
Since all pre-existing temporary variables are deleted, it is not generally desirable to use this proc after the interpreter has been instantiated.
Instead, use <n_Interpreter.SetVar()>.
See Also:
- <n_Interpreter.SetVar()>
*/
SetVar(name, value)
initial_variables[name]=value
/*
Class: GlobalBlock
A block object representing the global scope.
*/
//
GlobalBlock
New()
initial_variables["null"]=null
return ..()
/*
Class: FunctionBlock
A block representing a function body.
*/
//
FunctionBlock
@@ -1,174 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/*
File: Binary Operators
*/
/*
Class: binary
Represents a binary operator in the AST. A binary operator takes two operands (ie x and y) and returns a value.
*/
/node/expression/operator/binary
var/node/expression/exp2
////////// Comparison Operators //////////
/*
Class: Equal
Returns true if x = y.
*/
//
Equal
precedence=OOP_EQUAL
/*
Class: NotEqual
Returns true if x and y aren't equal.
*/
//
NotEqual
precedence=OOP_EQUAL
/*
Class: Greater
Returns true if x > y.
*/
//
Greater
precedence=OOP_COMPARE
/*
Class: Less
Returns true if x < y.
*/
//
Less
precedence=OOP_COMPARE
/*
Class: GreaterOrEqual
Returns true if x >= y.
*/
//
GreaterOrEqual
precedence=OOP_COMPARE
/*
Class: LessOrEqual
Returns true if x <= y.
*/
//
LessOrEqual
precedence=OOP_COMPARE
////////// Logical Operators //////////
/*
Class: LogicalAnd
Returns true if x and y are true.
*/
//
LogicalAnd
precedence=OOP_AND
/*
Class: LogicalOr
Returns true if x, y, or both are true.
*/
//
LogicalOr
precedence=OOP_OR
/*
Class: LogicalXor
Returns true if either x or y but not both are true.
*/
//
LogicalXor //Not implemented in nS
precedence=OOP_OR
////////// Bitwise Operators //////////
/*
Class: BitwiseAnd
Performs a bitwise and operation.
Example:
011 & 110 = 010
*/
//
BitwiseAnd
precedence=OOP_BIT
/*
Class: BitwiseOr
Performs a bitwise or operation.
Example:
011 | 110 = 111
*/
//
BitwiseOr
precedence=OOP_BIT
/*
Class: BitwiseXor
Performs a bitwise exclusive or operation.
Example:
011 xor 110 = 101
*/
//
BitwiseXor
precedence=OOP_BIT
////////// Arithmetic Operators //////////
/*
Class: Add
Returns the sum of x and y.
*/
//
Add
precedence=OOP_ADD
/*
Class: Subtract
Returns the difference of x and y.
*/
//
Subtract
precedence=OOP_ADD
/*
Class: Multiply
Returns the product of x and y.
*/
//
Multiply
precedence=OOP_MULTIPLY
/*
Class: Divide
Returns the quotient of x and y.
*/
//
Divide
precedence=OOP_MULTIPLY
/*
Class: Power
Returns x raised to the power of y.
*/
//
Power
precedence=OOP_POW
/*
Class: Modulo
Returns the remainder of x / y.
*/
//
Modulo
precedence=OOP_MULTIPLY
@@ -1,51 +0,0 @@
/*
File: Unary Operators
*/
/*
Class: unary
Represents a unary operator in the AST. Unary operators take a single operand (referred to as x below) and return a value.
*/
/node/expression/operator/unary
precedence=OOP_UNARY
/*
Class: LogicalNot
Returns !x.
Example:
!true = false and !false = true
*/
//
LogicalNot
name="logical not"
/*
Class: BitwiseNot
Returns the value of a bitwise not operation performed on x.
Example:
~10 (decimal 2) = 01 (decimal 1).
*/
//
BitwiseNot
name="bitwise not"
/*
Class: Minus
Returns -x.
*/
//
Minus
name="minus"
/*
Class: group
A special unary operator representing a value in parentheses.
*/
//
group
precedence=OOP_GROUP
New(node/expression/exp)
src.exp=exp
return ..()
-126
View File
@@ -1,126 +0,0 @@
/*
File: Statement Types
*/
/*
Class: statement
An object representing a single instruction run by an interpreter.
*/
/node/statement
/*
Class: FunctionCall
Represents a call to a function.
*/
//
FunctionCall
var
func_name
node/identifier/object
list/parameters=new
/*
Class: FunctionDefinition
Defines a function.
*/
//
FunctionDefinition
var
func_name
list/parameters=new
node/BlockDefinition/FunctionBlock/block
/*
Class: VariableAssignment
Sets a variable in an accessible scope to the given value if one exists, otherwise initializes a new local variable to the given value.
Notes:
If a variable with the same name exists in a higher block, the value will be assigned to it. If not,
a new variable is created in the current block. To force creation of a new variable, use <VariableDeclaration>.
See Also:
- <VariableDeclaration>
*/
//
VariableAssignment
var
node
identifier
object
var_name
expression/value
/*
Class: VariableDeclaration
Intializes a local variable to a null value.
See Also:
- <VariableAssignment>
*/
//
VariableDeclaration
var
node
identifier
object
var_name
/*
Class: IfStatement
*/
//
IfStatement
var
skip = 0
node
BlockDefinition
block
else_block //may be null
expression/cond
statement/else_if
ElseIf
/*
Class: WhileLoop
Loops while a given condition is true.
*/
//
WhileLoop
var
node
BlockDefinition/block
expression/cond
/*
Class: ForLoop
Loops while test is true, initializing a variable, increasing the variable
*/
ForLoop
var
node
BlockDefinition/block
expression/test
expression/init
expression/increment
/*
Class: BreakStatement
Ends a loop.
*/
//
BreakStatement
/*
Class: ContinueStatement
Skips to the next iteration of a loop.
*/
//
ContinueStatement
/*
Class: ReturnStatement
Ends the function and returns a value.
*/
//
ReturnStatement
var
node/expression/value
-141
View File
@@ -1,141 +0,0 @@
/*
File: Errors
*/
/*
Class: scriptError
An error scanning or parsing the source code.
*/
/scriptError
var
/*
Var: message
A message describing the problem.
*/
message
New(msg=null)
if(msg)message=msg
BadToken
message="Unexpected token: "
var/token/token
New(token/t)
token=t
if(t&&t.line) message="[t.line]: [message]"
if(istype(t))message+="[t.value]"
else message+="[t]"
InvalidID
parent_type=/scriptError/BadToken
message="Invalid identifier name: "
ReservedWord
parent_type=/scriptError/BadToken
message="Identifer using reserved word: "
BadNumber
parent_type=/scriptError/BadToken
message = "Bad number: "
BadReturn
var/token/token
message = "Unexpected return statement outside of a function."
New(token/t)
src.token=t
EndOfFile
message = "Unexpected end of file."
ExpectedToken
message="Expected: '"
New(id, token/T)
if(T && T.line) message="[T.line]: [message]"
message+="[id]'. "
if(T)message+="Found '[T.value]'."
UnterminatedComment
message="Unterminated multi-line comment statement: expected */"
DuplicateFunction
New(name, token/t)
message="Function '[name]' defined twice."
ParameterFunction
message = "You cannot use a function inside a parameter."
New(token/t)
var/line = "?"
if(t)
line = t.line
message = "[line]: [message]"
/*
Class: runtimeError
An error thrown by the interpreter in running the script.
*/
/runtimeError
var
name
/*
Var: message
A basic description as to what went wrong.
*/
message
datum/stack/stack
proc
/*
Proc: ToString
Returns a description of the error suitable for showing to the user.
*/
ToString()
. = "[name]: [message]"
if(!stack.Top()) return
.+="\nStack:"
while(stack.Top())
var/node/statement/FunctionCall/stmt=stack.Pop()
. += "\n\t [stmt.func_name]()"
TypeMismatch
name="TypeMismatchError"
New(op, a, b)
message="Type mismatch: '[a]' [op] '[b]'"
UnexpectedReturn
name="UnexpectedReturnError"
message="Unexpected return statement."
UnknownInstruction
name="UnknownInstructionError"
message="Unknown instruction type. This may be due to incompatible compiler and interpreter versions or a lack of implementation."
UndefinedVariable
name="UndefinedVariableError"
New(variable)
message="Variable '[variable]' has not been declared."
UndefinedFunction
name="UndefinedFunctionError"
New(function)
message="Function '[function]()' has not been defined."
DuplicateVariableDeclaration
name="DuplicateVariableError"
New(variable)
message="Variable '[variable]' was already declared."
IterationLimitReached
name="MaxIterationError"
message="A loop has reached its maximum number of iterations."
RecursionLimitReached
name="MaxRecursionError"
message="The maximum amount of recursion has been reached."
DivisionByZero
name="DivideByZeroError"
message="Division by zero attempted."
MaxCPU
name="MaxComputationalUse"
message="Maximum amount of computational cycles reached (>= 1000)."
-188
View File
@@ -1,188 +0,0 @@
/client/verb/tcssave()
set hidden = 1
if(mob.machine || issilicon(mob))
if(telecomms_check(mob))
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
if(Machine.editingcode != mob)
return
if(Machine.SelectedServer)
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
var/tcscode=winget(src, "tcscode", "text")
Server.setcode( tcscode ) // this actually saves the code from input to the server
src << output(null, "tcserror") // clear the errors
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to save: Unable to locate server machine. (Back up your code before exiting the window!)</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to save: Unable to locate machine. (Back up your code before exiting the window!)</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to save: Unable to locate machine. (Back up your code before exiting the window!)</font color>", "tcserror")
/client/verb/tcscompile()
set hidden = 1
if(mob.machine || issilicon(mob))
if(telecomms_check(mob))
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
if(Machine.editingcode != mob)
return
if(Machine.SelectedServer)
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
Server.setcode( winget(src, "tcscode", "text") ) // save code first
spawn(0)
// Output all the compile-time errors
src << output(null, "tcserror")
src << output("<font color = black>Please wait, compiling...</font>", "tcserror")
var/list/compileerrors = Server.compile(mob) // then compile the code!
if(!telecomms_check(mob))
return
if(compileerrors.len)
src << output("<b>Compile Errors</b>", "tcserror")
for(var/scriptError/e in compileerrors)
src << output("<font color = red>\t>[e.message]</font color>", "tcserror")
src << output("([compileerrors.len] errors)", "tcserror")
// Output compile errors to all other people viewing the code too
for(var/mob/M in Machine.viewingcode)
if(M.client)
M << output(null, "tcserror")
M << output("<b>Compile Errors</b>", "tcserror")
for(var/scriptError/e in compileerrors)
M << output("<font color = red>\t>[e.message]</font color>", "tcserror")
M << output("([compileerrors.len] errors)", "tcserror")
else
src << output("<font color = blue>TCS compilation successful!</font color>", "tcserror")
src << output("(0 errors)", "tcserror")
for(var/mob/M in Machine.viewingcode)
if(M.client)
M << output("<font color = blue>TCS compilation successful!</font color>", "tcserror")
M << output("(0 errors)", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to compile: Unable to locate server machine. (Back up your code before exiting the window!)</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)</font color>", "tcserror")
/client/verb/tcsrun()
set hidden = 1
if(mob.machine || issilicon(mob))
if(telecomms_check(mob))
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
if(Machine.editingcode != mob)
return
if(Machine.SelectedServer)
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
var/datum/signal/signal = new()
signal.data["message"] = ""
if(Server.freq_listening.len > 0)
signal.frequency = Server.freq_listening[1]
else
signal.frequency = 1459
signal.data["name"] = ""
signal.data["job"] = ""
signal.data["reject"] = 0
signal.data["server"] = Server
Server.Compiler.Run(signal)
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to run: Unable to locate server machine. (Back up your code before exiting the window!)</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to run: Unable to locate machine. (Back up your code before exiting the window!)</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to run: Unable to locate machine. (Back up your code before exiting the window!)</font color>", "tcserror")
/client/verb/exittcs()
set hidden = 1
if(mob.machine || issilicon(mob))
if(telecomms_check(mob))
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
if(Machine.editingcode == mob)
Machine.storedcode = "[winget(mob, "tcscode", "text")]"
Machine.editingcode = null
else
if(mob in Machine.viewingcode)
Machine.viewingcode.Remove(mob)
/client/verb/tcsrevert()
set hidden = 1
if(mob.machine || issilicon(mob))
if(telecomms_check(mob))
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
if(Machine.editingcode != mob)
return
if(Machine.SelectedServer)
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
// Replace quotation marks with quotation macros for proper winset() compatibility
var/showcode = replacetext(Server.rawcode, "\\\"", "\\\\\"")
showcode = replacetext(showcode, "\"", "\\\"")
winset(mob, "tcscode", "text=\"[showcode]\"")
src << output(null, "tcserror") // clear the errors
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to revert: Unable to locate server machine.</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to revert: Unable to locate machine.</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to revert: Unable to locate machine.</font color>", "tcserror")
/client/verb/tcsclearmem()
set hidden = 1
if(mob.machine || issilicon(mob))
if(telecomms_check(mob))
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
if(Machine.editingcode != mob)
return
if(Machine.SelectedServer)
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
Server.memory = list() // clear the memory
// Show results
src << output(null, "tcserror")
src << output("<font color = blue>Server memory cleared!</font color>", "tcserror")
for(var/mob/M in Machine.viewingcode)
if(M.client)
M << output("<font color = blue>Server memory cleared!</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to clear memory: Unable to locate server machine.</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to clear memory: Unable to locate machine.</font color>", "tcserror")
else
src << output(null, "tcserror")
src << output("<font color = red>Failed to clear memory: Unable to locate machine.</font color>", "tcserror")
/proc/telecomms_check(var/mob/mob)
if(mob && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && in_range(mob.machine, mob) || issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic))
return 1
return 0
@@ -1,367 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/* --- Traffic Control Scripting Language --- */
// Nanotrasen TCS Language - Made by Doohl
//Span classes that players are allowed to set in a radio transmission.
var/list/allowed_custom_spans = list(SPAN_ROBOT,SPAN_YELL,SPAN_ITALICS,SPAN_SANS)
/n_Interpreter/TCS_Interpreter
var/datum/TCS_Compiler/Compiler
HandleError(runtimeError/e)
Compiler.Holder.add_entry(e.ToString(), "Execution Error")
GC()
..()
Compiler = null
/datum/TCS_Compiler
var/n_Interpreter/TCS_Interpreter/interpreter
var/obj/machinery/telecomms/server/Holder // the server that is running the code
var/ready = 1 // 1 if ready to run code
/* -- Set ourselves to Garbage Collect -- */
proc/GC()
Holder = null
if(interpreter)
interpreter.GC()
/* -- Compile a raw block of text -- */
proc/Compile(code as message)
var/n_scriptOptions/nS_Options/options = new()
var/n_Scanner/nS_Scanner/scanner = new(code, options)
var/list/tokens = scanner.Scan()
var/n_Parser/nS_Parser/parser = new(tokens, options)
var/node/BlockDefinition/GlobalBlock/program = parser.Parse()
var/list/returnerrors = list()
returnerrors += scanner.errors
returnerrors += parser.errors
if(returnerrors.len)
return returnerrors
interpreter = new(program)
interpreter.persist = 1
interpreter.Compiler= src
return returnerrors
/* -- Execute the compiled code -- */
proc/Run(datum/signal/signal)
if(!ready)
return
if(!interpreter)
return
interpreter.container = src
interpreter.SetVar("PI" , 3.141592653) // value of pi
interpreter.SetVar("E" , 2.718281828) // value of e
interpreter.SetVar("SQURT2" , 1.414213562) // value of the square root of 2
interpreter.SetVar("FALSE" , 0) // boolean shortcut to 0
interpreter.SetVar("false" , 0) // boolean shortcut to 0
interpreter.SetVar("TRUE" , 1) // boolean shortcut to 1
interpreter.SetVar("true" , 1) // boolean shortcut to 1
interpreter.SetVar("NORTH" , NORTH) // NORTH (1)
interpreter.SetVar("SOUTH" , SOUTH) // SOUTH (2)
interpreter.SetVar("EAST" , EAST) // EAST (4)
interpreter.SetVar("WEST" , WEST) // WEST (8)
// Channel macros
interpreter.SetVar("$common", 1459)
interpreter.SetVar("$science", 1351)
interpreter.SetVar("$command", 1353)
interpreter.SetVar("$medical", 1355)
interpreter.SetVar("$engineering",1357)
interpreter.SetVar("$security", 1359)
interpreter.SetVar("$supply", 1347)
interpreter.SetVar("$service", 1349)
// Signal data
interpreter.SetVar("$content", html_decode(signal.data["message"]))
interpreter.SetVar("$freq" , signal.frequency)
interpreter.SetVar("$source" , signal.data["name"])
interpreter.SetVar("$job" , signal.data["job"])
interpreter.SetVar("$sign" , signal)
interpreter.SetVar("$pass" , !(signal.data["reject"])) // if the signal isn't rejected, pass = 1; if the signal IS rejected, pass = 0
interpreter.SetVar("$filters" , signal.data["spans"]) //Important, this is given as a vector! (a list)
interpreter.SetVar("$say" , signal.data["verb_say"])
interpreter.SetVar("$ask" , signal.data["verb_ask"])
interpreter.SetVar("$yell" , signal.data["verb_yell"])
interpreter.SetVar("$exclaim" , signal.data["verb_exclaim"])
//Current allowed span classes
interpreter.SetVar("$robot", SPAN_ROBOT) //The font used by silicons!
interpreter.SetVar("$loud", SPAN_YELL) //Bolding, applied when ending a message with several exclamation marks.
interpreter.SetVar("$emphasis", SPAN_ITALICS) //Italics
interpreter.SetVar("$wacky", SPAN_SANS) //Comic sans font, normally seen from the genetics power.
//Language bitflags
interpreter.SetVar("HUMAN" , HUMAN)
interpreter.SetVar("MONKEY" , MONKEY)
interpreter.SetVar("ALIEN" , ALIEN)
interpreter.SetVar("ROBOT" , ROBOT)
interpreter.SetVar("SLIME" , SLIME)
interpreter.SetVar("DRONE" , DRONE)
var/curlang = HUMAN
if(istype(signal.data["mob"], /atom/movable))
var/atom/movable/M = signal.data["mob"]
curlang = M.languages
interpreter.SetVar("$language", curlang)
/*
Telecomms procs
*/
/*
-> Send another signal to a server
@format: broadcast(content, frequency, source, job, lang)
@param content: Message to broadcast
@param frequency: Frequency to broadcast to
@param source: The name of the source you wish to imitate. Must be stored in stored_names list.
@param job: The name of the job.
@param spans What span classes you want to apply to your message. Must be in the "allowed_custom_spans" list.
@param say Say verb used in messages ending in ".".
@param ask Say verb used in messages ending in "?".
@param yell Say verb used in messages ending in "!!" (or more).
@param exclaim Say verb used in messages ending in "!".
*/
interpreter.SetProc("broadcast", "tcombroadcast", signal, list("message", "freq", "source", "job","spans","say","ask","yell","exclaim"))
/*
-> Send a code signal.
@format: signal(frequency, code)
@param frequency: Frequency to send the signal to
@param code: Encryption code to send the signal with
*/
interpreter.SetProc("signal", "signaler", signal, list("freq", "code"))
/*
-> Store a value permanently to the server machine (not the actual game hosting machine, the ingame machine)
@format: mem(address, value)
@param address: The memory address (string index) to store a value to
@param value: The value to store to the memory address
*/
interpreter.SetProc("mem", "mem", signal, list("address", "value"))
/*
General NTSL procs
Should probably be moved to its own place
*/
// Vector
interpreter.SetProc("vector", /proc/n_list)
interpreter.SetProc("at", /proc/n_listpos)
interpreter.SetProc("copy", /proc/n_listcopy)
interpreter.SetProc("push_back", /proc/n_listadd)
interpreter.SetProc("remove", /proc/n_listremove)
interpreter.SetProc("cut", /proc/n_listcut)
interpreter.SetProc("swap", /proc/n_listswap)
interpreter.SetProc("insert", /proc/n_listinsert)
interpreter.SetProc("pick", /proc/n_pick)
interpreter.SetProc("prob", /proc/n_prob)
interpreter.SetProc("substr", /proc/n_substr)
interpreter.SetProc("find", /proc/n_smartfind)
interpreter.SetProc("length", /proc/n_smartlength)
// Strings
interpreter.SetProc("lower", /proc/n_lower)
interpreter.SetProc("upper", /proc/n_upper)
interpreter.SetProc("explode", /proc/n_explode)
interpreter.SetProc("implode", /proc/n_implode)
interpreter.SetProc("repeat", /proc/n_repeat)
interpreter.SetProc("reverse", /proc/n_reverse)
interpreter.SetProc("tonum", /proc/n_str2num)
interpreter.SetProc("replace", /proc/n_replace)
interpreter.SetProc("proper", /proc/n_proper)
// Numbers
interpreter.SetProc("tostring", /proc/n_num2str)
interpreter.SetProc("sqrt", /proc/n_sqrt)
interpreter.SetProc("abs", /proc/n_abs)
interpreter.SetProc("floor", /proc/n_floor)
interpreter.SetProc("ceil", /proc/n_ceil)
interpreter.SetProc("round", /proc/n_round)
interpreter.SetProc("clamp", /proc/n_clamp)
interpreter.SetProc("inrange", /proc/n_inrange)
interpreter.SetProc("rand", /proc/n_rand)
interpreter.SetProc("randseed", /proc/n_randseed)
interpreter.SetProc("min", /proc/n_min)
interpreter.SetProc("max", /proc/n_max)
interpreter.SetProc("sin", /proc/n_sin)
interpreter.SetProc("cos", /proc/n_cos)
interpreter.SetProc("asin", /proc/n_asin)
interpreter.SetProc("acos", /proc/n_acos)
interpreter.SetProc("log", /proc/n_log)
// Time
interpreter.SetProc("time", /proc/n_time)
interpreter.SetProc("sleep", /proc/n_delay)
interpreter.SetProc("timestamp", /proc/gameTimestamp)
// Run the compiled code
interpreter.Run()
// Backwards-apply variables onto signal data
/* sanitize EVERYTHING. fucking players can't be trusted with SHIT */
signal.data["message"] = interpreter.GetCleanVar("$content", signal.data["message"])
signal.frequency = interpreter.GetCleanVar("$freq", signal.frequency)
var/setname = interpreter.GetCleanVar("$source", signal.data["name"])
if(signal.data["name"] != setname)
signal.data["realname"] = setname
signal.data["name"] = setname
signal.data["job"] = interpreter.GetCleanVar("$job", signal.data["job"])
signal.data["reject"] = !(interpreter.GetCleanVar("$pass")) // set reject to the opposite of $pass
signal.data["verb_say"] = interpreter.GetCleanVar("$say")
signal.data["verb_ask"] = interpreter.GetCleanVar("$ask")
signal.data["verb_yell"] = interpreter.GetCleanVar("$yell")
signal.data["verb_exclaim"] = interpreter.GetCleanVar("$exclaim")
var/list/setspans = interpreter.GetCleanVar("$filters") //Save the span vector/list to a holder list
setspans &= allowed_custom_spans //Prune out any illegal ones. Go ahead, comment this line out. See the horror you can unleash!
if(islist(setspans)) //Previous comment block was right. Players cannot be trusted with ANYTHING. At all. Ever.
signal.data["spans"] = setspans //Apply new span to the signal only if it is a valid list, made using vector() in the script.
// If the message is invalid, just don't broadcast it!
if(signal.data["message"] == "" || !signal.data["message"])
signal.data["reject"] = 1
/* -- Actual language proc code -- */
var/const/SIGNAL_COOLDOWN = 20 // 2 seconds
/datum/signal
proc/mem(address, value)
if(istext(address))
var/obj/machinery/telecomms/server/S = data["server"]
if(!value && value != 0)
return S.memory[address]
else
S.memory[address] = value
proc/signaler(freq = 1459, code = 30)
if(isnum(freq) && isnum(code))
var/obj/machinery/telecomms/server/S = data["server"]
if(S.last_signal + SIGNAL_COOLDOWN > world.timeofday && S.last_signal < MIDNIGHT_ROLLOVER)
return
S.last_signal = world.timeofday
var/datum/radio_frequency/connection = radio_controller.return_frequency(freq)
if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal
freq *= 10 // shift the decimal one place
freq = sanitize_frequency(freq)
code = round(code)
code = Clamp(code, 0, 100)
var/datum/signal/signal = new
signal.source = S
signal.encryption = code
signal.data["message"] = "ACTIVATE"
connection.post_signal(S, signal)
var/time = time2text(world.realtime,"hh:mm:ss")
lastsignalers.Add("[time] <B>:</B> [S.id] sent a signal command, which was triggered by NTSL.<B>:</B> [format_frequency(freq)]/[code]")
proc/tcombroadcast(message, freq, source, job, spans, say = "says", ask = "asks", yell = "yells", exclaim = "exclaims")
var/datum/signal/newsign = new
var/obj/machinery/telecomms/server/S = data["server"]
var/obj/item/device/radio/hradio = S.server_radio
if(!hradio)
throw EXCEPTION("tcombroadcast(): signal has no radio")
return
if((!message) && message != 0)
message = "*beep*"
if(!source)
source = "[html_encode(uppertext(S.id))]"
hradio = new // sets the hradio as a radio intercom
if(!freq || (!isnum(freq) && text2num(freq) == null))
freq = 1459
if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal
freq *= 10 // shift the decimal one place
if(!job)
job = "Unknown"
if(!islist(spans))
spans = list()
else
spans &= allowed_custom_spans //Removes any spans not on the allowed list. Comment this out if want to let players use ANY span in stylesheet.dm!
//SAY REWRITE RELATED CODE.
//This code is a little hacky, but it *should* work. Even though it'll result in a virtual speaker referencing another virtual speaker. vOv
var/atom/movable/virtualspeaker/virt = PoolOrNew(/atom/movable/virtualspeaker,null)
virt.name = source
virt.job = job
virt.languages = HUMAN
//END SAY REWRITE RELATED CODE.
newsign.data["mob"] = virt
newsign.data["mobtype"] = /mob/living/carbon/human
newsign.data["name"] = source
newsign.data["realname"] = newsign.data["name"]
newsign.data["job"] = "[job]"
newsign.data["compression"] = 0
newsign.data["message"] = message
newsign.data["type"] = 2 // artificial broadcast
newsign.data["spans"] = spans
newsign.data["verb_say"] = say
newsign.data["verb_ask"] = ask
newsign.data["verb_yell"]= yell
newsign.data["verb_exclaim"] = exclaim
if(!isnum(freq))
freq = text2num(freq)
newsign.frequency = freq
newsign.data["radio"] = hradio
newsign.data["vmessage"] = message
newsign.data["vname"] = source
newsign.data["vmask"] = 0
newsign.data["level"] = data["level"]
newsign.sanitize_data()
var/pass = S.relay_information(newsign, "/obj/machinery/telecomms/hub")
if(!pass)
S.relay_information(newsign, "/obj/machinery/telecomms/broadcaster") // send this simple message to broadcasters
@@ -1,319 +0,0 @@
// Script -> BYOND code procs
#define SCRIPT_MAX_REPLACEMENTS_ALLOWED 200
// --- List operations (lists known as vectors in n_script) ---
// Creates a list out of all the arguments
/proc/n_list()
var/list/returnlist = list()
for(var/e in args)
returnlist.Add(e)
return returnlist
// Picks one random item from the list
/proc/n_pick()
var/list/finalpick = list()
for(var/e in args)
if(isobject(e))
if(istype(e, /list))
var/list/sublist = e
for(var/sube in sublist)
finalpick.Add(sube)
continue
finalpick.Add(e)
return pick(finalpick)
// Gets/Sets a value at a key in the list
/proc/n_listpos(list/L, pos, value)
if(!istype(L, /list)) return
if(isnum(pos))
if(!value)
if(L.len >= pos)
return L[pos]
else
if(L.len >= pos)
L[pos] = value
else if(istext(pos))
if(!value)
return L[pos]
else
L[pos] = value
// Copies the list into a new one
/proc/n_listcopy(list/L, start, end)
if(!istype(L, /list)) return
return L.Copy(start, end)
// Adds arg 2,3,4,5... to the end of list at arg 1
/proc/n_listadd()
var/list/chosenlist
var/i = 1
for(var/e in args)
if(i == 1)
if(isobject(e))
if(istype(e, /list))
chosenlist = e
i = 2
else
if(chosenlist)
chosenlist.Add(e)
// Removes arg 2,3,4,5... from list at arg 1
/proc/n_listremove()
var/list/chosenlist
var/i = 1
for(var/e in args)
if(i == 1)
if(isobject(e))
if(istype(e, /list))
chosenlist = e
i = 2
else
if(chosenlist)
chosenlist.Remove(e)
// Cuts out a copy of a list
/proc/n_listcut(list/L, start, end)
if(!istype(L, /list)) return
return L.Cut(start, end)
// Swaps two values in the list
/proc/n_listswap(list/L, firstindex, secondindex)
if(!istype(L, /list)) return
if(L.len >= secondindex && L.len >= firstindex)
return L.Swap(firstindex, secondindex)
// Inserts a value into the list
/proc/n_listinsert(list/L, index, element)
if(!istype(L, /list)) return
return L.Insert(index, element)
// --- String methods ---
//If list, finds a value in it, if text, finds a substring in it
/proc/n_smartfind(haystack, needle, start = 1, end = 0)
if(haystack && needle)
if(isobject(haystack))
if(istype(haystack, /list))
if(length(haystack) >= end && start > 0)
var/list/listhaystack = haystack
return listhaystack.Find(needle, start, end)
else
if(istext(haystack))
if(length(haystack) >= end && start > 0)
return findtext(haystack, needle, start, end)
//Returns a substring of the string
/proc/n_substr(string, start = 1, end = 0)
if(istext(string) && isnum(start) && isnum(end))
if(start > 0)
return copytext(string, start, end)
//Returns the length of the string or list
/proc/n_smartlength(container)
if(container)
if(istype(container, /list) || istext(container))
return length(container)
return 0
//Lowercase all characters
/proc/n_lower(string)
if(istext(string))
return lowertext(string)
//Uppercase all characters
/proc/n_upper(string)
if(istext(string))
return uppertext(string)
//Converts a string to a list
/proc/n_explode(string, separator = "")
if(istext(string) && (istext(separator) || isnull(separator)))
return text2list(string, separator)
//Converts a list to a string
/proc/n_implode(list/li, separator)
if(istype(li) && (istext(separator) || isnull(separator)))
return list2text(li, separator)
//Repeats the string x times
/proc/n_repeat(string, amount)
if(istext(string) && isnum(amount))
var/i
var/newstring = ""
if(length(newstring)*amount >=1000)
return
for(i=0, i<=amount, i++)
if(i>=1000)
break
newstring = newstring + string
return newstring
//Reverses the order of the string. "Clown" becomes "nwolC"
/proc/n_reverse(string)
if(istext(string))
var/newstring = ""
var/i
for(i=lentext(string), i>0, i--)
if(i>=1000)
break
newstring = newstring + copytext(string, i, i+1)
return newstring
// String -> Number
/proc/n_str2num(string)
if(istext(string))
return text2num(string)
/proc/n_proper(string)
if(!istext(string))
return ""
return text("[][]", uppertext(copytext(string, 1, 2)), lowertext(copytext(string, 2)))
// --- Number methods ---
//Returns the highest value of the arguments
//Need custom functions here cause byond's min and max runtimes if you give them a string or list.
/proc/n_max()
if(args.len == 0)
return 0
var/max = args[1]
for(var/e in args)
if(isnum(e) && e > max)
max = e
return max
//Returns the lowest value of the arguments
/proc/n_min()
if(args.len == 0)
return 0
var/min = args[1]
for(var/e in args)
if(isnum(e) && e < min)
min = e
return min
/proc/n_prob(chance)
return prob(chance)
/proc/n_randseed(seed)
rand_seed(seed)
return 0
/proc/n_rand(low, high)
if(isnull(low) && isnull(high))
return rand()
return rand(low, high)
// Number -> String
/proc/n_num2str(num)
if(isnum(num))
return num2text(num)
// Squareroot
/proc/n_sqrt(num)
if(isnum(num))
return sqrt(num)
// Magnitude of num
/proc/n_abs(num)
if(isnum(num))
return abs(num)
// Round down
/proc/n_floor(num)
if(isnum(num))
return round(num)
// Round up
/proc/n_ceil(num)
if(isnum(num))
return round(num)+1
// Round to nearest integer
/proc/n_round(num)
if(isnum(num))
if(num-round(num)<0.5)
return round(num)
return n_ceil(num)
// Clamps N between min and max
/proc/n_clamp(num, min=-1, max=1)
if(isnum(num)&&isnum(min)&&isnum(max))
if(num<=min)
return min
if(num>=max)
return max
return num
// Returns 1 if N is inbetween Min and Max
/proc/n_inrange(num, min=-1, max=1)
if(isnum(num)&&isnum(min)&&isnum(max))
return ((min <= num) && (num <= max))
// Returns the sine of num
/proc/n_sin(num)
if(isnum(num))
return sin(num)
// Returns the cosine of num
/proc/n_cos(num)
if(isnum(num))
return cos(num)
// Returns the arcsine of num
/proc/n_asin(num)
if(isnum(num)&&-1<=num&&num<=1)
return arcsin(num)
// Returns the arccosine of num
/proc/n_acos(num)
if(isnum(num)&&-1<=num&&num<=1)
return arccos(num)
// Returns the natural log of num
/proc/n_log(num)
if(isnum(num)&&0<num)
return log(num)
// Replace text
/proc/n_replace(text, find, replacement)
if(istext(text) && istext(find) && istext(replacement))
var/find_len = length(find)
if(find_len < 1) return text
. = ""
var/last_found = 1
var/count = 0
while(1)
count += 1
if(count > SCRIPT_MAX_REPLACEMENTS_ALLOWED)
break
var/found = findtext(text, find, last_found, 0)
. += copytext(text, last_found, found)
if(found)
. += replacement
last_found = found + find_len
continue
return
#undef SCRIPT_MAX_REPLACEMENTS_ALLOWED
// --- Miscellaneous functions ---
/proc/n_time()
return world.timeofday
// Clone of sleep()
/proc/n_delay(time)
sleep(time)
@@ -1,169 +0,0 @@
/proc/isobject(x)
return (istype(x, /datum) || istype(x, /list) || istype(x, /savefile) || istype(x, /client) || (x==world))
/n_Interpreter
proc
Eval(node/expression/exp)
if(istype(exp, /node/expression/FunctionCall))
return RunFunction(exp)
else if(istype(exp, /node/expression/operator))
return EvalOperator(exp)
else if(istype(exp, /node/expression/value/literal))
var/node/expression/value/literal/lit=exp
return lit.value
else if(istype(exp, /node/expression/value/reference))
var/node/expression/value/reference/ref=exp
return ref.value
else if(istype(exp, /node/expression/value/variable))
var/node/expression/value/variable/v=exp
if(!v.object)
return Eval(GetVariable(v.id.id_name))
else
var/datum/D
if(istype(v.object, /node/identifier))
D=GetVariable(v.object:id_name)
else
D=v.object
D=Eval(D)
if(!isobject(D))
return null
if(!D.vars.Find(v.id.id_name))
RaiseError(new/runtimeError/UndefinedVariable("[v.object.ToString()].[v.id.id_name]"))
return null
return Eval(D.vars[v.id.id_name])
else if(istype(exp, /node/expression))
RaiseError(new/runtimeError/UnknownInstruction())
else
return exp
EvalOperator(node/expression/operator/exp)
if(istype(exp, /node/expression/operator/binary))
var/node/expression/operator/binary/bin=exp
switch(bin.type)
if(/node/expression/operator/binary/Equal)
return Equal(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/NotEqual)
return NotEqual(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Greater)
return Greater(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Less)
return Less(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/GreaterOrEqual)
return GreaterOrEqual(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/LessOrEqual)
return LessOrEqual(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/LogicalAnd)
return LogicalAnd(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/LogicalOr)
return LogicalOr(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/LogicalXor)
return LogicalXor(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/BitwiseAnd)
return BitwiseAnd(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/BitwiseOr)
return BitwiseOr(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/BitwiseXor)
return BitwiseXor(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Add)
return Add(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Subtract)
return Subtract(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Multiply)
return Multiply(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Divide)
return Divide(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Power)
return Power(Eval(bin.exp), Eval(bin.exp2))
if(/node/expression/operator/binary/Modulo)
return Modulo(Eval(bin.exp), Eval(bin.exp2))
else
RaiseError(new/runtimeError/UnknownInstruction())
else
switch(exp.type)
if(/node/expression/operator/unary/Minus)
return Minus(Eval(exp.exp))
if(/node/expression/operator/unary/LogicalNot)
return LogicalNot(Eval(exp.exp))
if(/node/expression/operator/unary/BitwiseNot)
return BitwiseNot(Eval(exp.exp))
if(/node/expression/operator/unary/group)
return Eval(exp.exp)
else
RaiseError(new/runtimeError/UnknownInstruction())
//Binary//
//Comparison operators
Equal(a, b) return a==b
NotEqual(a, b) return a!=b //LogicalNot(Equal(a, b))
Greater(a, b) return a>b
Less(a, b) return a<b
GreaterOrEqual(a, b)return a>=b
LessOrEqual(a, b) return a<=b
//Logical Operators
LogicalAnd(a, b) return a&&b
LogicalOr(a, b) return a||b
LogicalXor(a, b) return (a||b) && !(a&&b)
//Bitwise Operators
BitwiseAnd(a, b) return a&b
BitwiseOr(a, b) return a|b
BitwiseXor(a, b) return a^b
//Arithmetic Operators
Add(a, b)
if(istext(a)&&!istext(b)) b="[b]"
else if(istext(b)&&!istext(a)) a="[a]"
if(isobject(a) && !isobject(b))
RaiseError(new/runtimeError/TypeMismatch("+", a, b))
return null
else if(isobject(b) && !isobject(a))
RaiseError(new/runtimeError/TypeMismatch("+", a, b))
return null
return a+b
Subtract(a, b)
if(isobject(a) && !isobject(b))
RaiseError(new/runtimeError/TypeMismatch("-", a, b))
return null
else if(isobject(b) && !isobject(a))
RaiseError(new/runtimeError/TypeMismatch("-", a, b))
return null
return a-b
Divide(a, b)
if(isobject(a) && !isobject(b))
RaiseError(new/runtimeError/TypeMismatch("/", a, b))
return null
else if(isobject(b) && !isobject(a))
RaiseError(new/runtimeError/TypeMismatch("/", a, b))
return null
if(b==0 || b==null)
RaiseError(new/runtimeError/DivisionByZero())
return null
return a/b
Multiply(a, b)
if(isobject(a) && !isobject(b))
RaiseError(new/runtimeError/TypeMismatch("*", a, b))
return null
else if(isobject(b) && !isobject(a))
RaiseError(new/runtimeError/TypeMismatch("*", a, b))
return null
return a*b
Modulo(a, b)
if(isobject(a) && !isobject(b))
RaiseError(new/runtimeError/TypeMismatch("%", a, b))
return null
else if(isobject(b) && !isobject(a))
RaiseError(new/runtimeError/TypeMismatch("%", a, b))
return null
return a%b
Power(a, b)
if(isobject(a) && !isobject(b))
RaiseError(new/runtimeError/TypeMismatch("**", a, b))
return null
else if(isobject(b) && !isobject(a))
RaiseError(new/runtimeError/TypeMismatch("**", a, b))
return null
return a**b
//Unary//
Minus(a) return -a
LogicalNot(a) return !a
BitwiseNot(a) return ~a
@@ -1,153 +0,0 @@
/*
File: Interpreter (Public)
Contains methods for interacting with the interpreter.
*/
/*
Class: n_Interpreter
Procedures allowing for interaction with the script that is being run by the interpreter object.
*/
/n_Interpreter
proc
/*
Proc: Load
Loads a 'compiled' script into memory.
Parameters:
program - A <GlobalBlock> object which represents the script's global scope.
*/
Load(node/BlockDefinition/GlobalBlock/program)
ASSERT(program)
src.program = program
CreateGlobalScope()
alertadmins = 0 // reset admin alerts
/*
Proc: Run
Runs the script.
*/
Run()
cur_recursion = 0 // reset recursion
cur_statements = 0 // reset CPU tracking
ASSERT(src.program)
RunBlock(src.program)
/*
Proc: SetVar
Defines a global variable for the duration of the next execution of a script.
Notes:
This differs from <Block.SetVar()> in that variables set using this procedure only last for the session,
while those defined from the block object persist if it is ran multiple times.
See Also:
- <Block.SetVar()>
*/
SetVar(name, value)
if(!istext(name))
//CRASH("Invalid variable name")
return
AssignVariable(name, value)
/*
Proc: SetProc
Defines a procedure to be available to the script.
Parameters:
name - The name of the procedure as exposed to the script.
path - The typepath of a proc to be called when the function call is read by the interpreter, or, if object is specified, a string representing the procedure's name.
object - (Optional) An object which will the be target of a function call.
params - Only required if object is not null, a list of the names of parameters the proc takes.
*/
SetProc(name, path, object=null, list/params=null)
if(!istext(name))
//CRASH("Invalid function name")
return
if(!object)
globalScope.functions[name] = path
else
var/node/statement/FunctionDefinition/S = new()
S.func_name = name
S.parameters = params
S.block = new()
S.block.SetVar("src", object)
var/node/expression/FunctionCall/C = new()
C.func_name = path
C.object = new("src")
for(var/p in params)
C.parameters += new/node/expression/value/variable(p)
var/node/statement/ReturnStatement/R=new()
R.value=C
S.block.statements += R
globalScope.functions[name] = S
/*
Proc: VarExists
Checks whether a global variable with the specified name exists.
*/
VarExists(name)
return globalScope.variables.Find(name) //convert to 1/0 first?
/*
Proc: ProcExists
Checks whether a global function with the specified name exists.
*/
ProcExists(name)
return globalScope.functions.Find(name)
/*
Proc: GetVar
Returns the value of a global variable in the script. Remember to ensure that the variable exists before calling this procedure.
See Also:
- <VarExists()>
*/
GetVar(name)
if(!VarExists(name))
//CRASH("No variable named '[name]'.")
return
var/x = globalScope.variables[name]
return Eval(x)
/*
Proc: GetCleanVar
Returns the value of a global variable in the script and cleans it (sanitizes).
*/
GetCleanVar(name, compare)
var/x = GetVar(name)
if(istext(x) && compare && x != compare) // Was changed
x = sanitize(x)
return x
/*
Proc: CallProc
Calls a global function defined in the script and, amazingly enough, returns its return value. Remember to ensure that the function
exists before calling this procedure.
See Also:
- <ProcExists()>
*/
CallProc(name, params[]=null)
if(!ProcExists(name))
//CRASH("No function named '[name]'.")
return
var/node/statement/FunctionDefinition/func = globalScope.functions[name]
if(istype(func))
var/node/statement/FunctionCall/stmt = new
stmt.func_name = func.func_name
stmt.parameters = params
return RunFunction(stmt)
else
return call(func)(arglist(params))
//CRASH("Unknown function type '[name]'.")
/*
Event: HandleError
Called when the interpreter throws a runtime error.
See Also:
- <runtimeError>
*/
HandleError(runtimeError/e)
@@ -1,340 +0,0 @@
/*
File: Interpreter (Internal)
*/
/*
Class: n_Interpreter
*/
/*
Macros: Status Macros
RETURNING - Indicates that the current function is returning a value.
BREAKING - Indicates that the current loop is being terminated.
CONTINUING - Indicates that the rest of the current iteration of a loop is being skipped.
*/
#define RETURNING 1
#define BREAKING 2
#define CONTINUING 4
/n_Interpreter
var
scope
curScope
globalScope
node
BlockDefinition/program
statement/FunctionDefinition/curFunction
datum/stack
scopes = new()
functions = new()
datum/container // associated container for interpeter
/*
Var: status
A variable indicating that the rest of the current block should be skipped. This may be set to any combination of <Status Macros>.
*/
status=0
returnVal
max_statements=900 // maximum amount of statements that can be called in one execution. this is to prevent massive crashes and exploitation
cur_statements=0 // current amount of statements called
alertadmins=0 // set to 1 if the admins shouldn't be notified of anymore issues
max_iterations=100 // max number of uninterrupted loops possible
max_recursion=10 // max recursions without returning anything (or completing the code block)
cur_recursion=0 // current amount of recursion
/*
Var: persist
If 0, global variables will be reset after Run() finishes.
*/
persist=1
paused=0
/*
Constructor: New
Calls <Load()> with the given parameters.
*/
New(node/BlockDefinition/GlobalBlock/program=null)
.=..()
if(program)Load(program)
proc
/*
Set ourselves to Garbage Collect
*/
GC()
..()
container = null
/*
Proc: RaiseError
Raises a runtime error.
*/
RaiseError(runtimeError/e)
e.stack=functions.Copy()
e.stack.Push(curFunction)
src.HandleError(e)
CreateScope(node/BlockDefinition/B)
var/scope/S = new(B, curScope)
scopes.Push(curScope)
curScope = S
return S
CreateGlobalScope()
scopes.Clear()
var/scope/S = new(program, null)
globalScope = S
return S
/*
Proc: AlertAdmins
Alerts the admins of a script that is bad.
*/
AlertAdmins()
if(container && !alertadmins)
if(istype(container, /datum/TCS_Compiler))
var/datum/TCS_Compiler/Compiler = container
var/obj/machinery/telecomms/server/Holder = Compiler.Holder
var/message = "Potential crash-inducing NTSL script detected at telecommunications server [Compiler.Holder] ([Holder.x], [Holder.y], [Holder.z])."
alertadmins = 1
message_admins(message, 1)
/*
Proc: RunBlock
Runs each statement in a block of code.
*/
RunBlock(node/BlockDefinition/Block, scope/scope = null)
var/is_global = istype(Block, /node/BlockDefinition/GlobalBlock)
if(!is_global)
if(scope)
curScope = scope
else
CreateScope(Block)
else
if(!persist)
CreateGlobalScope()
curScope = globalScope
if(cur_statements < max_statements)
for(var/node/statement/S in Block.statements)
while(paused) sleep(10)
cur_statements++
if(cur_statements >= max_statements)
RaiseError(new/runtimeError/MaxCPU())
AlertAdmins()
break
if(istype(S, /node/statement/VariableAssignment))
var/node/statement/VariableAssignment/stmt = S
var/name = stmt.var_name.id_name
if(!stmt.object)
// Below we assign the variable first to null if it doesn't already exist.
// This is necessary for assignments like +=, and when the variable is used in a function
// If the variable already exists in a different block, then AssignVariable will automatically use that one.
if(!IsVariableAccessible(name))
AssignVariable(name, null)
AssignVariable(name, Eval(stmt.value))
else
var/datum/D = Eval(GetVariable(stmt.object.id_name))
if(!D) return
D.vars[stmt.var_name.id_name] = Eval(stmt.value)
else if(istype(S, /node/statement/VariableDeclaration))
//VariableDeclaration nodes are used to forcibly declare a local variable so that one in a higher scope isn't used by default.
var/node/statement/VariableDeclaration/dec=S
if(!dec.object)
AssignVariable(dec.var_name.id_name, null, curScope)
else
var/datum/D = Eval(GetVariable(dec.object.id_name))
if(!D) return
D.vars[dec.var_name.id_name] = null
else if(istype(S, /node/statement/FunctionCall))
RunFunction(S)
else if(istype(S, /node/statement/FunctionDefinition))
//do nothing
else if(istype(S, /node/statement/WhileLoop))
RunWhile(S)
else if(istype(S, /node/statement/IfStatement))
RunIf(S)
else if(istype(S, /node/statement/ReturnStatement))
if(!curFunction)
RaiseError(new/runtimeError/UnexpectedReturn())
continue
status |= RETURNING
returnVal=Eval(S:value)
break
else if(istype(S, /node/statement/BreakStatement))
status |= BREAKING
break
else if(istype(S, /node/statement/ContinueStatement))
status |= CONTINUING
break
else
RaiseError(new/runtimeError/UnknownInstruction())
if(status)
break
curScope = scopes.Pop()
/*
Proc: RunFunction
Runs a function block or a proc with the arguments specified in the script.
*/
RunFunction(node/statement/FunctionCall/stmt)
//Note that anywhere /node/statement/FunctionCall/stmt is used so may /node/expression/FunctionCall
// If recursion gets too high (max 50 nested functions) throw an error
if(cur_recursion >= max_recursion)
AlertAdmins()
RaiseError(new/runtimeError/RecursionLimitReached())
return 0
var/node/statement/FunctionDefinition/def
if(!stmt.object) //A scope's function is being called, stmt.object is null
def = GetFunction(stmt.func_name)
else if(istype(stmt.object)) //A method of an object exposed as a variable is being called, stmt.object is a /node/identifier
var/O = GetVariable(stmt.object.id_name) //Gets a reference to the object which is the target of the function call.
if(!O) return //Error already thrown in GetVariable()
def = Eval(O)
if(!def) return
cur_recursion++ // add recursion
if(istype(def))
if(curFunction) functions.Push(curFunction)
var/scope/S = CreateScope(def.block)
for(var/i=1 to def.parameters.len)
var/val
if(stmt.parameters.len>=i)
val = stmt.parameters[i]
//else
// unspecified param
AssignVariable(def.parameters[i], new/node/expression/value/literal(Eval(val)), S)
curFunction=stmt
RunBlock(def.block, S)
//Handle return value
. = returnVal
status &= ~RETURNING
returnVal=null
curFunction=functions.Pop()
cur_recursion--
else
cur_recursion--
var/list/params=new
for(var/node/expression/P in stmt.parameters)
params+=list(Eval(P))
if(isobject(def)) //def is an object which is the target of a function call
if( !hascall(def, stmt.func_name) )
RaiseError(new/runtimeError/UndefinedFunction("[stmt.object.id_name].[stmt.func_name]"))
return
return call(def, stmt.func_name)(arglist(params))
else //def is a path to a global proc
return call(def)(arglist(params))
//else
// RaiseError(new/runtimeError/UnknownInstruction())
/*
Proc: RunIf
Checks a condition and runs either the if block or else block.
*/
RunIf(node/statement/IfStatement/stmt)
if(!stmt.skip)
if(Eval(stmt.cond))
RunBlock(stmt.block)
// Loop through the if else chain and tell them to be skipped.
var/node/statement/IfStatement/i = stmt.else_if
var/fail_safe = 800
while(i && fail_safe)
fail_safe -= 1
i.skip = 1
i = i.else_if
else if(stmt.else_block)
RunBlock(stmt.else_block)
// We don't need to skip you anymore.
stmt.skip = 0
/*
Proc: RunWhile
Runs a while loop.
*/
RunWhile(node/statement/WhileLoop/stmt)
var/i=1
while(Eval(stmt.cond) && Iterate(stmt.block, i++))
continue
status &= ~BREAKING
/*
Proc:Iterate
Runs a single iteration of a loop. Returns a value indicating whether or not to continue looping.
*/
Iterate(node/BlockDefinition/block, count)
RunBlock(block)
if(max_iterations > 0 && count >= max_iterations)
RaiseError(new/runtimeError/IterationLimitReached())
return 0
if(status & (BREAKING|RETURNING))
return 0
status &= ~CONTINUING
return 1
/*
Proc: GetFunction
Finds a function in an accessible scope with the given name. Returns a <FunctionDefinition>.
*/
GetFunction(name)
var/scope/S = curScope
while(S)
if(S.functions.Find(name))
return S.functions[name]
S = S.parent
RaiseError(new/runtimeError/UndefinedFunction(name))
/*
Proc: GetVariable
Finds a variable in an accessible scope and returns its value.
*/
GetVariable(name)
var/scope/S = curScope
while(S)
if(S.variables.Find(name))
return S.variables[name]
S = S.parent
RaiseError(new/runtimeError/UndefinedVariable(name))
GetVariableScope(name) //needed for when you reassign a variable in a higher scope
var/scope/S = curScope
while(S)
if(S.variables.Find(name))
return S
S = S.parent
IsVariableAccessible(name)
var/scope/S = curScope
while(S)
if(S.variables.Find(name))
return TRUE
S = S.parent
return FALSE
/*
Proc: AssignVariable
Assigns a value to a variable in a specific block.
Parameters:
name - The name of the variable to assign.
value - The value to assign to it.
S - The scope the variable resides in. If it is null, a scope with the variable already existing is found. If no scopes have a variable of the given name, the current scope is used.
*/
AssignVariable(name, node/expression/value, scope/S=null)
if(!S) S = GetVariableScope(name)
if(!S) S = curScope
if(!S) S = globalScope
ASSERT(istype(S))
if(istext(value) || isnum(value) || isnull(value)) value = new/node/expression/value/literal(value)
else if(!istype(value) && isobject(value)) value = new/node/expression/value/reference(value)
//TODO: check for invalid name
S.variables["[name]"] = value
@@ -1,18 +0,0 @@
/*
Class: scope
A runtime instance of a block. Used internally by the interpreter.
*/
/scope
var
scope/parent = null
node/BlockDefinition/block
list
functions
variables
New(node/BlockDefinition/B, scope/parent)
src.block = B
src.parent = parent
src.variables = B.initial_variables.Copy()
src.functions = B.functions.Copy()
.=..()
-82
View File
@@ -1,82 +0,0 @@
/*
File: Options
*/
var/const //Ascii values of characters
ascii_A =65
ascii_Z =90
ascii_a =97
ascii_z =122
ascii_DOLLAR = 36 // $
ascii_ZERO=48
ascii_NINE=57
ascii_UNDERSCORE=95 // _
/*
Class: n_scriptOptions
*/
n_scriptOptions
proc
CanStartID(char) //returns true if the character can start a variable, function, or keyword name (by default letters or an underscore)
if(!isnum(char))char=text2ascii(char)
return (char in ascii_A to ascii_Z) || (char in ascii_a to ascii_z) || char==ascii_UNDERSCORE || char==ascii_DOLLAR
IsValidIDChar(char) //returns true if the character can be in the body of a variable, function, or keyword name (by default letters, numbers, and underscore)
if(!isnum(char))char=text2ascii(char)
return CanStartID(char) || IsDigit(char)
IsDigit(char)
if(!isnum(char))char=text2ascii(char)
return char in ascii_ZERO to ascii_NINE
IsValidID(id) //returns true if all the characters in the string are okay to be in an identifier name
if(!CanStartID(id)) //don't need to grab first char in id, since text2ascii does it automatically
return 0
if(lentext(id)==1) return 1
for(var/i=2 to lentext(id))
if(!IsValidIDChar(copytext(id, i, i+1)))
return 0
return 1
/*
Class: nS_Options
An implementation of <n_scriptOptions> for the n_Script language.
*/
nS_Options
var
list
symbols = list("(", ")", "\[", "]", ";", ",", "{", "}") //scanner - Characters that can be in symbols
/*
Var: keywords
An associative list used by the parser to parse keywords. Indices are strings which will trigger the keyword when parsed and the
associated values are <nS_Keyword> types of which the <n_Keyword.Parse()> proc will be called.
*/
keywords = list("if" = /n_Keyword/nS_Keyword/kwIf, "else" = /n_Keyword/nS_Keyword/kwElse, "elseif" = /n_Keyword/nS_Keyword/kwElseIf, \
"while" = /n_Keyword/nS_Keyword/kwWhile, "break" = /n_Keyword/nS_Keyword/kwBreak, \
"continue" = /n_Keyword/nS_Keyword/kwContinue, \
"return" = /n_Keyword/nS_Keyword/kwReturn, "def" = /n_Keyword/nS_Keyword/kwDef)
list
assign_operators=list("=" = null, "&=" = "&",
"|=" = "|", "`=" = "`",
"+=" = "+", "-=" = "-",
"*=" = "*", "/=" = "/",
"^=" = "^",
"%=" = "%")
unary_operators =list("!" = /node/expression/operator/unary/LogicalNot, "~" = /node/expression/operator/unary/BitwiseNot,
"-" = /node/expression/operator/unary/Minus)
binary_operators=list("==" = /node/expression/operator/binary/Equal, "!=" = /node/expression/operator/binary/NotEqual,
">" = /node/expression/operator/binary/Greater, "<" = /node/expression/operator/binary/Less,
">=" = /node/expression/operator/binary/GreaterOrEqual,"<=" = /node/expression/operator/binary/LessOrEqual,
"&&" = /node/expression/operator/binary/LogicalAnd, "||" = /node/expression/operator/binary/LogicalOr,
"&" = /node/expression/operator/binary/BitwiseAnd, "|" = /node/expression/operator/binary/BitwiseOr,
"`" = /node/expression/operator/binary/BitwiseXor, "+" = /node/expression/operator/binary/Add,
"-" = /node/expression/operator/binary/Subtract, "*" = /node/expression/operator/binary/Multiply,
"/" = /node/expression/operator/binary/Divide, "^" = /node/expression/operator/binary/Power,
"%" = /node/expression/operator/binary/Modulo)
New()
.=..()
for(var/O in assign_operators+binary_operators+unary_operators)
if(!symbols.Find(O)) symbols+=O
@@ -1,336 +0,0 @@
/*
File: Expressions
Procedures for parsing expressions.
*/
/*
Macros: Expression Macros
OPERATOR - A value indicating the parser currently expects a binary operator.
VALUE - A value indicating the parser currently expects a value.
SHIFT - Tells the parser to push the current operator onto the stack.
REDUCE - Tells the parser to reduce the stack.
*/
#define OPERATOR 1
#define VALUE 2
#define SHIFT 0
#define REDUCE 1
/*
Class: nS_Parser
*/
/n_Parser/nS_Parser
var
/*
Var: expecting
A variable which keeps track of whether an operator or value is expected. It should be either <OPERATOR> or <VALUE>. See <ParseExpression()>
for more information.
*/
expecting=VALUE
proc
/*
Proc: Precedence
Compares two operators, decides which is higher in the order of operations, and returns <SHIFT> or <REDUCE>.
*/
Precedence(node/expression/operator/top, node/expression/operator/input)
if(istype(top))
top=top.precedence
if(istype(input))
input=input:precedence
if(top>=input)
return REDUCE
return SHIFT
/*
Proc: GetExpression
Takes a token expected to represent a value and returns an <expression> node.
*/
GetExpression(token/T)
if(!T) return
if(istype(T, /node/expression))
return T
switch(T.type)
if(/token/word)
return new/node/expression/value/variable(T.value)
if(/token/accessor)
var
token/accessor/A=T
node/expression/value/variable/E//=new(A.member)
datum/stack/S = new()
while(istype(A.object, /token/accessor))
S.Push(A)
A=A.object
ASSERT(istext(A.object))
while(A)
var/node/expression/value/variable/V=new()
V.id=new(A.member)
if(E)
V.object=E
else
V.object=new/node/identifier(A.object)
E=V
A=S.Pop()
return E
if(/token/number, /token/string)
return new/node/expression/value/literal(T.value)
/*
Proc: GetOperator
Gets a path related to a token or string and returns an instance of the given type. This is used to get an instance of either a binary or unary
operator from a token.
Parameters:
O - The input value. If this is a token, O is reset to the token's value.
When O is a string and is in L, its associated value is used as the path to instantiate.
type - The desired type of the returned object.
L - The list in which to search for O.
See Also:
- <GetBinaryOperator()>
- <GetUnaryOperator()>
*/
GetOperator(O, type=/node/expression/operator, L[])
if(istype(O, type)) return O //O is already the desired type
if(istype(O, /token)) O=O:value //sets O to text
if(istext(O)) //sets O to path
if(L.Find(O)) O=L[O]
else return null
if(ispath(O))O=new O //catches path from last check
else return null //Unknown type
return O
/*
Proc: GetBinaryOperator
Uses <GetOperator()> to search for an instance of a binary operator type with which the given string is associated. For example, if
O is set to "+", an <Add> node is returned.
See Also:
- <GetOperator()>
- <GetUnaryOperator()>
*/
GetBinaryOperator(O)
return GetOperator(O, /node/expression/operator/binary, options.binary_operators)
/*
Proc: GetUnaryOperator
Uses <GetOperator()> to search for an instance of a unary operator type with which the given string is associated. For example, if
O is set to "!", a <LogicalNot> node is returned.
See Also:
- <GetOperator()>
- <GetBinaryOperator()>
*/
GetUnaryOperator(O)
return GetOperator(O, /node/expression/operator/unary, options.unary_operators)
/*
Proc: Reduce
Takes the operator on top of the opr stack and assigns its operand(s). Then this proc pushes the value of that operation to the top
of the val stack.
*/
Reduce(datum/stack/opr, datum/stack/val)
var/node/expression/operator/O=opr.Pop()
if(!O) return
if(!istype(O))
errors+=new/scriptError("Error reducing expression - invalid operator.")
return
//Take O and assign its operands, popping one or two values from the val stack
//depending on whether O is a binary or unary operator.
if(istype(O, /node/expression/operator/binary))
var/node/expression/operator/binary/B=O
B.exp2=val.Pop()
B.exp =val.Pop()
val.Push(B)
else
O.exp=val.Pop()
val.Push(O)
/*
Proc: EndOfExpression
Returns true if the current token represents the end of an expression.
Parameters:
end - A list of values to compare the current token to.
*/
EndOfExpression(end[])
if(!curToken)
return 1
if(istype(curToken, /token/symbol) && end.Find(curToken.value))
return 1
if(istype(curToken, /token/end) && end.Find(/token/end))
return 1
return 0
/*
Proc: ParseExpression
Uses the Shunting-yard algorithm to parse expressions.
Notes:
- When an opening parenthesis is found, then <ParseParenExpression()> is called to handle it.
- The <expecting> variable helps distinguish unary operators from binary operators (for cases like the - operator, which can be either).
Articles:
- <http://epaperpress.com/oper/>
- <http://en.wikipedia.org/wiki/Shunting-yard_algorithm>
See Also:
- <ParseFunctionExpression()>
- <ParseParenExpression()>
- <ParseParamExpression()>
*/
ParseExpression(list/end=list(/token/end), list/ErrChars=list("{", "}"), check_functions = 0)
var/datum/stack
opr=new
val=new
src.expecting=VALUE
var/loop = 0
for()
loop++
if(loop > 800)
errors+=new/scriptError("Too many nested tokens.")
return
if(EndOfExpression(end))
break
if(istype(curToken, /token/symbol) && ErrChars.Find(curToken.value))
errors+=new/scriptError/BadToken(curToken)
break
if(index>tokens.len) //End of File
errors+=new/scriptError/EndOfFile()
break
var/token/ntok
if(index+1<=tokens.len)
ntok=tokens[index+1]
if(istype(curToken, /token/symbol) && curToken.value=="(") //Parse parentheses expression
if(expecting!=VALUE)
errors+=new/scriptError/ExpectedToken("operator", curToken)
NextToken()
continue
val.Push(ParseParenExpression())
else if(istype(curToken, /token/symbol)) //Operator found.
var/node/expression/operator/curOperator //Figure out whether it is unary or binary and get a new instance.
if(src.expecting==OPERATOR)
curOperator=GetBinaryOperator(curToken)
if(!curOperator)
errors+=new/scriptError/ExpectedToken("operator", curToken)
NextToken()
continue
else
curOperator=GetUnaryOperator(curToken)
if(!curOperator) //given symbol isn't a unary operator
errors+=new/scriptError/ExpectedToken("expression", curToken)
NextToken()
continue
if(opr.Top() && Precedence(opr.Top(), curOperator)==REDUCE) //Check order of operations and reduce if necessary
Reduce(opr, val)
continue
opr.Push(curOperator)
src.expecting=VALUE
else if(ntok && ntok.value=="(" && istype(ntok, /token/symbol)\
&& istype(curToken, /token/word)) //Parse function call
if(!check_functions)
var/token/preToken=curToken
var/old_expect=src.expecting
var/fex=ParseFunctionExpression()
if(old_expect!=VALUE)
errors+=new/scriptError/ExpectedToken("operator", preToken)
NextToken()
continue
val.Push(fex)
else
errors+=new/scriptError/ParameterFunction(curToken)
break
else if(istype(curToken, /token/keyword)) //inline keywords
var/n_Keyword/kw=options.keywords[curToken.value]
kw=new kw(inline=1)
if(kw)
if(!kw.Parse(src))
return
else
errors+=new/scriptError/BadToken(curToken)
else if(istype(curToken, /token/end)) //semicolon found where it wasn't expected
errors+=new/scriptError/BadToken(curToken)
NextToken()
continue
else
if(expecting!=VALUE)
errors+=new/scriptError/ExpectedToken("operator", curToken)
NextToken()
continue
val.Push(GetExpression(curToken))
src.expecting=OPERATOR
NextToken()
while(opr.Top()) Reduce(opr, val) //Reduce the value stack completely
.=val.Pop() //Return what should be the last value on the stack
if(val.Top()) //
var/node/N=val.Pop()
errors+=new/scriptError("Error parsing expression. Unexpected value left on stack: [N.ToString()].")
return null
/*
Proc: ParseFunctionExpression
Parses a function call inside of an expression.
See Also:
- <ParseExpression()>
*/
ParseFunctionExpression()
var/node/expression/FunctionCall/exp=new
exp.func_name=curToken.value
NextToken() //skip function name
NextToken() //skip open parenthesis, already found
var/loops = 0
for()
loops++
if(loops>=800)
errors += new/scriptError("Too many nested expressions.")
break
//CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;")
if(istype(curToken, /token/symbol) && curToken.value==")")
return exp
exp.parameters+=ParseParamExpression()
if(errors.len)
return exp
if(curToken.value==","&&istype(curToken, /token/symbol))NextToken() //skip comma
if(istype(curToken, /token/end)) //Prevents infinite loop...
errors+=new/scriptError/ExpectedToken(")")
return exp
/*
Proc: ParseParenExpression
Parses an expression that ends with a close parenthesis. This is used for parsing expressions inside of parentheses.
See Also:
- <ParseExpression()>
*/
ParseParenExpression()
if(!CheckToken("(", /token/symbol))
return
return new/node/expression/operator/unary/group(ParseExpression(list(")")))
/*
Proc: ParseParamExpression
Parses an expression that ends with either a comma or close parenthesis. This is used for parsing the parameters passed to a function call.
See Also:
- <ParseExpression()>
*/
ParseParamExpression(check_functions = 0)
var/cf = check_functions
return ParseExpression(list(",", ")"), check_functions = cf)
-191
View File
@@ -1,191 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/*
File: Keywords
*/
var/const/KW_FAIL = 0 //Fatal error; stop parsing entire script.
var/const/KW_PASS = 1 //OK
var/const/KW_ERR = 2 //Non-fatal error, keyword couldn't be handled properly. Ignore keyword but continue on.
var/const/KW_WARN = 3 //Warning
/*
var/const/Class: n_Keyword
var/const/Represents a special statement in the code triggered by a keyword.
*/
/n_Keyword
New(inline=0)
src.inline=inline
return ..()
/*
Var: inline
1 if the keyword is in an expression (e.g. the new keyword in many languages), 0 otherwise (such as the if and else keywords).
*/
var/inline
/*
Proc: Parse
Called when the parser finds a keyword in the code.
Parameters:
parser - The parser that created this object. You can use the parameter to manipulate the parser in order to add statements and blocks
to its AST.
*/
proc/Parse(n_Parser/parser)
/*
Class: nS_Keyword
A keyword in n_Script. By default these include return, if, else, while, and def. To enable or disable a keyword, change the
<nS_Options.keywords> list.
Behavior:
When a parser is expecting a new statement, and a keyword listed in <nS_Options.keywords> is found, it will call the keyword's
<n_Keyword.Parse()> proc.
*/
//
nS_Keyword
New(inline=0)
if(inline)
del src
kwReturn
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock)) // Exit out of the program by setting the tokens list size to the same as index.
parser.tokens.len = parser.index
return
var/node/statement/ReturnStatement/stmt=new
parser.NextToken() //skip 'return' token
stmt.value=parser.ParseExpression()
parser.curBlock.statements+=stmt
kwIf
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/node/statement/IfStatement/stmt=new
parser.NextToken() //skip 'if' token
stmt.cond=parser.ParseParenExpression()
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0
return KW_ERR
parser.curBlock.statements+=stmt
stmt.block=new
parser.AddBlock(stmt.block)
kwElseIf
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/list/L=parser.curBlock.statements
var/node/statement/IfStatement/ifstmt
if(L && L.len)
ifstmt = L[L.len] //Get the last statement in the current block
if(!ifstmt || !istype(ifstmt) || ifstmt.else_if)
parser.errors += new/scriptError/ExpectedToken("if statement", parser.curToken)
return KW_FAIL
var/node/statement/IfStatement/ElseIf/stmt = new
parser.NextToken() //skip 'if' token
stmt.cond = parser.ParseParenExpression()
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0
return KW_ERR
parser.curBlock.statements+=stmt
stmt.block=new
ifstmt.else_if = stmt
parser.AddBlock(stmt.block)
kwElse
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/list/L=parser.curBlock.statements
var/node/statement/IfStatement/stmt
if(L&&L.len) stmt=L[L.len] //Get the last statement in the current block
if(!stmt || !istype(stmt) || stmt.else_block) //Ensure that it is an if statement
parser.errors+=new/scriptError/ExpectedToken("if statement",parser.curToken)
return KW_FAIL
parser.NextToken() //skip 'else' token
if(!parser.CheckToken("{", /token/symbol, skip=0))
return KW_ERR
stmt.else_block=new()
parser.AddBlock(stmt.else_block)
kwWhile
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/node/statement/WhileLoop/stmt=new
parser.NextToken() //skip 'while' token
stmt.cond=parser.ParseParenExpression()
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /token/symbol, skip=0))
return KW_ERR
parser.curBlock.statements+=stmt
stmt.block=new
parser.AddBlock(stmt.block)
kwBreak
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
parser.errors+=new/scriptError/BadToken(parser.curToken)
. = KW_WARN
var/node/statement/BreakStatement/stmt=new
parser.NextToken() //skip 'break' token
parser.curBlock.statements+=stmt
kwContinue
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
parser.errors+=new/scriptError/BadToken(parser.curToken)
. = KW_WARN
var/node/statement/ContinueStatement/stmt=new
parser.NextToken() //skip 'break' token
parser.curBlock.statements+=stmt
kwDef
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/node/statement/FunctionDefinition/def=new
parser.NextToken() //skip 'def' token
if(!parser.options.IsValidID(parser.curToken.value))
parser.errors+=new/scriptError/InvalidID(parser.curToken)
return KW_FAIL
def.func_name=parser.curToken.value
parser.NextToken()
if(!parser.CheckToken("(", /token/symbol))
return KW_FAIL
for() //for now parameters can be separated by whitespace - they don't need a comma in between
if(istype(parser.curToken, /token/symbol))
switch(parser.curToken.value)
if(",")
parser.NextToken()
if(")")
break
else
parser.errors+=new/scriptError/BadToken(parser.curToken)
return KW_ERR
else if(istype(parser.curToken, /token/word))
def.parameters+=parser.curToken.value
parser.NextToken()
else
parser.errors+=new/scriptError/InvalidID(parser.curToken)
return KW_ERR
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(istype(parser.curToken, /token/end)) //Function prototype
parser.curBlock.statements+=def
else if(parser.curToken.value=="{" && istype(parser.curToken, /token/symbol))
def.block = new
parser.curBlock.statements+=def
parser.curBlock.functions[def.func_name]=def
parser.AddBlock(def.block)
else
parser.errors+=new/scriptError/BadToken(parser.curToken)
return KW_FAIL
-190
View File
@@ -1,190 +0,0 @@
/*
File: Parser
*/
/*
Class: n_Parser
An object that reads tokens and produces an AST (abstract syntax tree).
*/
/n_Parser
var
/*
Var: index
The parser's current position in the token's list.
*/
index = 1
list
/*
Var: tokens
A list of tokens in the source code generated by a scanner.
*/
tokens = new
/*
Var: errors
A list of fatal errors found by the parser. If there are any items in this list, then it is not safe to run the returned AST.
See Also:
- <scriptError>
*/
errors = new
/*
Var: warnings
A list of non-fatal problems in the script.
*/
warnings = new
token
/*
Var: curToken
The token at <index> in <tokens>.
*/
curToken
datum/stack
blocks=new
node/BlockDefinition
GlobalBlock/global_block=new
curBlock
proc
/*
Proc: Parse
Reads the tokens and returns the AST's <GlobalBlock> node. Be sure to populate the tokens list before calling this procedure.
*/
Parse()
/*
Proc: NextToken
Sets <curToken> to the next token in the <tokens> list, or null if there are no more tokens.
*/
NextToken()
if(index>=tokens.len)
curToken=null
else
curToken=tokens[++index]
return curToken
/*
Class: nS_Parser
An implmentation of a parser for n_Script.
*/
/n_Parser/nS_Parser
var/n_scriptOptions/nS_Options/options
/*
Constructor: New
Parameters:
tokens - A list of tokens to parse.
options - An object used for configuration.
*/
New(tokens[], n_scriptOptions/options)
src.tokens=tokens
src.options=options
curBlock=global_block
return ..()
Parse()
ASSERT(tokens)
for(,src.index<=src.tokens.len, src.index++)
curToken=tokens[index]
switch(curToken.type)
if(/token/keyword)
var/n_Keyword/kw=options.keywords[curToken.value]
kw=new kw()
if(kw)
if(!kw.Parse(src))
return
if(/token/word)
var/token/ntok
if(index+1>tokens.len)
errors+=new/scriptError/BadToken(curToken)
continue
ntok=tokens[index+1]
if(!istype(ntok, /token/symbol))
errors+=new/scriptError/BadToken(ntok)
continue
if(ntok.value=="(")
ParseFunctionStatement()
else if(options.assign_operators.Find(ntok.value))
ParseAssignment()
else
errors+=new/scriptError/BadToken(ntok)
continue
if(!istype(curToken, /token/end))
errors+=new/scriptError/ExpectedToken(";", curToken)
continue
if(/token/symbol)
if(curToken.value=="}")
if(!EndBlock())
errors+=new/scriptError/BadToken(curToken)
continue
else
errors+=new/scriptError/BadToken(curToken)
continue
if(/token/end)
warnings+=new/scriptError/BadToken(curToken)
continue
else
errors+=new/scriptError/BadToken(curToken)
return
return global_block
proc
CheckToken(val, type, err=1, skip=1)
if(curToken.value!=val || !istype(curToken,type))
if(err)
errors+=new/scriptError/ExpectedToken(val, curToken)
return 0
if(skip)NextToken()
return 1
AddBlock(node/BlockDefinition/B)
blocks.Push(curBlock)
curBlock=B
EndBlock()
if(curBlock==global_block) return 0
curBlock=blocks.Pop()
return 1
ParseAssignment()
var/name=curToken.value
if(!options.IsValidID(name))
errors+=new/scriptError/InvalidID(curToken)
return
NextToken()
var/t=options.binary_operators[options.assign_operators[curToken.value]]
var/node/statement/VariableAssignment/stmt=new()
stmt.var_name=new(name)
NextToken()
if(t)
stmt.value=new t()
stmt.value:exp=new/node/expression/value/variable(stmt.var_name)
stmt.value:exp2=ParseExpression()
else
stmt.value=ParseExpression()
curBlock.statements+=stmt
ParseFunctionStatement()
if(!istype(curToken, /token/word))
errors+=new/scriptError("Bad identifier in function call.")
return
var/node/statement/FunctionCall/stmt=new
stmt.func_name=curToken.value
NextToken() //skip function name
if(!CheckToken("(", /token/symbol)) //Check for and skip open parenthesis
return
var/loops = 0
for()
loops++
if(loops>=800)
errors +=new/scriptError("Cannot find ending params.")
return
if(!curToken)
errors+=new/scriptError/EndOfFile()
return
if(istype(curToken, /token/symbol) && curToken.value==")")
curBlock.statements+=stmt
NextToken() //Skip close parenthesis
return
var/node/expression/P=ParseParamExpression(check_functions = 1)
stmt.parameters+=P
if(istype(curToken, /token/symbol) && curToken.value==",") NextToken()
-288
View File
@@ -1,288 +0,0 @@
/*
File: Scanner
*/
/*
Class: n_Scanner
An object responsible for breaking up source code into tokens for use by the parser.
*/
/n_Scanner
var
code
list
/*
Var: errors
A list of fatal errors found by the scanner. If there are any items in this list, then it is not safe to parse the returned tokens.
See Also:
- <scriptError>
*/
errors = new
/*
Var: warnings
A list of non-fatal problems in the source code found by the scanner.
*/
warnings = new
proc
/*
Proc: LoadCode
Loads source code.
*/
LoadCode(c)
code=c
/*
Proc: LoadCodeFromFile
Gets the code from a file and calls <LoadCode()>.
*/
LoadCodeFromFile(f)
LoadCode(file2text(f))
/*
Proc: Scan
Runs the scanner and returns the resulting list of tokens. Ensure that <LoadCode()> has been called first.
*/
Scan()
/*
Class: nS_Scanner
A scanner implementation for n_Script.
*/
/n_Scanner/nS_Scanner
var
/*
Variable: codepos
The scanner's position in the source code.
*/
codepos = 1
line = 1
linepos = 0 //column=codepos-linepos
n_scriptOptions/nS_Options/options
commenting = 0
// 1: single-line
// 2: multi-line
list
/*
Variable: ignore
A list of characters that are ignored by the scanner.
Default Value:
Whitespace
*/
ignore = list(" ", "\t", "\n") //Don't add tokens for whitespace
/*
Variable: end_stmt
A list of characters that end a statement. Each item may only be one character long.
Default Value:
Semicolon
*/
end_stmt = list(";")
/*
Variable: string_delim
A list of characters that can start and end strings.
Default Value:
Double and single quotes.
*/
string_delim = list("\"", "'")
/*
Variable: delim
A list of characters that denote the start of a new token. This list is automatically populated.
*/
delim = new
/*
Macro: COL
The current column number.
*/
#define COL codepos-linepos
/*
Constructor: New
Parameters:
code - The source code to tokenize.
options - An <nS_Options> object used to configure the scanner.
*/
New(code, n_scriptOptions/nS_Options/options)
.=..()
ignore+= ascii2text(13) //Carriage return
delim += ignore + options.symbols + end_stmt + string_delim
src.options=options
LoadCode(code)
Scan() //Creates a list of tokens from source code
var/list/tokens=new
for(, src.codepos<=lentext(code), src.codepos++)
var/char=copytext(code, codepos, codepos+1)
var/nextchar=copytext(code, codepos+1, codepos+2)
if(char=="\n")
line++
linepos=codepos
if(ignore.Find(char))
continue
else if(char == "/" && (nextchar == "/" || nextchar == "*"))
ReadComment()
else if(end_stmt.Find(char))
tokens+=new /token/end(char, line, COL)
else if(string_delim.Find(char))
codepos++ //skip string delimiter
tokens+=ReadString(char)
else if(options.CanStartID(char))
tokens+=ReadWord()
else if(options.IsDigit(char))
tokens+=ReadNumber()
else if(options.symbols.Find(char))
tokens+=ReadSymbol()
codepos=initial(codepos)
line=initial(line)
linepos=initial(linepos)
return tokens
proc
/*
Proc: ReadString
Reads a string in the source code into a token.
Parameters:
start - The character used to start the string.
*/
ReadString(start)
var
buf
for(, codepos <= lentext(code), codepos++)//codepos to lentext(code))
var/char=copytext(code, codepos, codepos+1)
switch(char)
if("\\") //Backslash (\) encountered in string
codepos++ //Skip next character in string, since it was escaped by a backslash
char=copytext(code, codepos, codepos+1)
switch(char)
if("\\") //Double backslash
buf+="\\"
if("n") //\n Newline
buf+="\n"
else
if(char==start) //\" Doublequote
buf+=start
else //Unknown escaped text
buf+=char
if("\n")
. = new/token/string(buf, line, COL)
errors+=new/scriptError("Unterminated string. Newline reached.", .)
line++
linepos=codepos
break
else
if(char==start) //string delimiter found, end string
break
else
buf+=char //Just a normal character in a string
if(!.) return new/token/string(buf, line, COL)
/*
Proc: ReadWord
Reads characters separated by an item in <delim> into a token.
*/
ReadWord()
var
char=copytext(code, codepos, codepos+1)
buf
while(!delim.Find(char) && codepos<=lentext(code))
buf+=char
char=copytext(code, ++codepos, codepos+1)
codepos-- //allow main Scan() proc to read the delimiter
if(options.keywords.Find(buf))
return new /token/keyword(buf, line, COL)
else
return new /token/word(buf, line, COL)
/*
Proc: ReadSymbol
Reads a symbol into a token.
*/
ReadSymbol()
var
char=copytext(code, codepos, codepos+1)
buf
while(options.symbols.Find(buf+char))
buf+=char
if(++codepos>lentext(code)) break
char=copytext(code, codepos, codepos+1)
codepos-- //allow main Scan() proc to read the next character
return new /token/symbol(buf, line, COL)
/*
Proc: ReadNumber
Reads a number into a token.
*/
ReadNumber()
var
char=copytext(code, codepos, codepos+1)
buf
dec=0
while(options.IsDigit(char) || (char=="." && !dec))
if(char==".") dec=1
buf+=char
codepos++
char=copytext(code, codepos, codepos+1)
var/token/number/T=new(buf, line, COL)
if(isnull(text2num(buf)))
errors+=new/scriptError("Bad number: ", T)
T.value=0
codepos-- //allow main Scan() proc to read the next character
return T
/*
Proc: ReadComment
Reads a comment and outputs the type of comment
*/
ReadComment()
var
char=copytext(code, codepos, codepos+1)
nextchar=copytext(code, codepos+1, codepos+2)
charstring = char+nextchar
comm = 1
// 1: single-line comment
// 2: multi-line comment
expectedend = 0
if(charstring == "//" || charstring == "/*")
if(charstring == "/*")
comm = 2 // starts a multi-line comment
while(comm)
if(++codepos>lentext(code)) break
if(expectedend) // ending statement expected...
char = copytext(code, codepos, codepos+1)
if(char == "/") // ending statement found - beak the comment
comm = 0
break
if(comm == 2)
// multi-line comments are broken by ending statements
char = copytext(code, codepos, codepos+1)
if(char == "*")
expectedend = 1
continue
else
char = copytext(code, codepos, codepos+1)
if(char == "\n")
comm = 0
break
if(expectedend) expectedend = 0
if(comm == 2)
errors+=new/scriptError/UnterminatedComment()
-38
View File
@@ -1,38 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/*
Class: Token
Represents an entity and position in the source code.
*/
/token
var/value
var/line
var/column
New(v, l=0, c=0)
value=v
line=l
column=c
string
symbol
word
keyword
number
New()
.=..()
if(!isnum(value))
value=text2num(value)
ASSERT(!isnull(value))
accessor
var/object
var/member
New(object, member, l=0, c=0)
src.object=object
src.member=member
src.value="[object].[member]" //for debugging only
src.line=l
src.column=c
end
@@ -0,0 +1,36 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# wip (For works in progress)
# tweak
# soundadd
# sounddel
# rscadd (general adding of nice things)
# rscdel (general deleting of nice things)
# imageadd
# imagedel
# spellcheck (typo fixes)
# experiment
# tgs (TG-ported fixes?)
#################################
# Your name.
author: MrPerson
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
changes:
- rscdel: "Removed NTSL. Sorry. People could write scripts that crashed the server, and this is the only thing that can be done to prevent them from doing that."
+3 -23
View File
@@ -504,7 +504,6 @@
#include "code\game\machinery\telecomms\telecomunications.dm"
#include "code\game\machinery\telecomms\computers\logbrowser.dm"
#include "code\game\machinery\telecomms\computers\telemonitor.dm"
#include "code\game\machinery\telecomms\computers\traffic_control.dm"
#include "code\game\machinery\telecomms\machines\allinone.dm"
#include "code\game\machinery\telecomms\machines\broadcaster.dm"
#include "code\game\machinery\telecomms\machines\bus.dm"
@@ -834,9 +833,9 @@
#include "code\modules\admin\NewBan.dm"
#include "code\modules\admin\newbanjob.dm"
#include "code\modules\admin\player_panel.dm"
#include "code\modules\admin\secrets.dm"
#include "code\modules\admin\stickyban.dm"
#include "code\modules\admin\sql_notes.dm"
#include "code\modules\admin\secrets.dm"
#include "code\modules\admin\sql_notes.dm"
#include "code\modules\admin\stickyban.dm"
#include "code\modules\admin\topic.dm"
#include "code\modules\admin\watchlist.dm"
#include "code\modules\admin\DB ban\functions.dm"
@@ -1493,25 +1492,6 @@
#include "code\modules\research\designs\telecomms_designs.dm"
#include "code\modules\research\designs\weapon_designs.dm"
#include "code\modules\research\xenobiology\xenobiology.dm"
#include "code\modules\scripting\Errors.dm"
#include "code\modules\scripting\IDE.dm"
#include "code\modules\scripting\Options.dm"
#include "code\modules\scripting\AST\AST Nodes.dm"
#include "code\modules\scripting\AST\Blocks.dm"
#include "code\modules\scripting\AST\Statements.dm"
#include "code\modules\scripting\AST\Operators\Binary Operators.dm"
#include "code\modules\scripting\AST\Operators\Unary Operators.dm"
#include "code\modules\scripting\Implementations\_Logic.dm"
#include "code\modules\scripting\Implementations\Telecomms.dm"
#include "code\modules\scripting\Interpreter\Evaluation.dm"
#include "code\modules\scripting\Interpreter\Interaction.dm"
#include "code\modules\scripting\Interpreter\Interpreter.dm"
#include "code\modules\scripting\Interpreter\Scope.dm"
#include "code\modules\scripting\Parser\Expressions.dm"
#include "code\modules\scripting\Parser\Keywords.dm"
#include "code\modules\scripting\Parser\Parser.dm"
#include "code\modules\scripting\Scanner\Scanner.dm"
#include "code\modules\scripting\Scanner\Tokens.dm"
#include "code\modules\security levels\keycard authentication.dm"
#include "code\modules\security levels\security levels.dm"
#include "code\modules\shuttle\shuttle.dm"