Code:
@name BulkOS
@inputs CharIn S:wirelink Switch InA InB InC InD
@outputs Out:string PortA PortB PortC PortD [TFG TBG]:vector
# Keyboard:
@persist CharBuffer:array [String Saved]:string FG BG
# Data:
@persist DB:table [M Action]:array File:string
# Console:
@persist D:array Busy
# By Filipe D, 11th of Jan to 12th of Jan 2010.
# Enjoy!
if(first() | duped()) { File = "bulkos.txt" runOnChat(1) }
if(first() | duped() | clk("clear")) {
if(first() | duped() ) { FG = 999 BG = 111 }
S[2041] = 1 S[2042] = BG
D:pushString("Welcome, "+owner():name())
D:pushString("Today is "+time("day")+"/"+time("month")+"/"+time("year"))
D:pushString("-":repeat(30))
TFG = vec(0,0,0) TBG = vec(80,80,80)
}
if(first() | clk("reload") | fileClk()) {
if(!fileLoaded(File)) {
fileLoad(File) runOnFile(1)
}
else{
D:pushString("File loaded!")
if(File == "bulkos.txt") { DB = glonDecodeTable(fileRead(File))
M[999,string] = DB["startup",string] timer("enter",10)
}
runOnFile(0)
}
}
# Keyboard input:
if(changed(CharIn) & CharIn>0) {
# Save key presses to the buffer:
# The buffer allows the user to type faster, preventing (or atleast reducing)
# any loss of keypresses in the process.
CharBuffer:pushNumber(CharIn)
}
while(CharBuffer:count()>0) {
# Do the actual key drawing on the screen:
Char = CharBuffer[1,number]
Key = toChar(CharBuffer[1,number]) CharBuffer:remove(1)
# print(""+Char)
# Keys:
# Backspace:
if(Char == 127 & String:length()>=0) {
String = String:left(String:length()-1)
}
# Shift key
elseif(Char == 154) {
# Do nothing.
}
elseif(Char == 151) {
S[2038] = -1
}
elseif(Char == 152) {
S[2038] = 1
}
# UP arrow
elseif(Char == 17) {
String = Saved
}
# ENTER key
elseif(Char == 13) {
D:pushString(">"+ String) M[999,string] = String
timer("enter",10)
if(String !="") { Saved = String }
String = ""
}
else{
# Everything else.
# -------------- #
String = String + Key
}
Out = String
}
if(chatClk() & lastSaid():index(1) == ">") {
Chat = lastSaid():right(lastSaid():length()-1)
D:pushString(">"+Chat)
M[999,string] = Chat timer("enter",20)
# hideChat(1)
}
if(clk("enter")) {
Get = M[999,string] Raw = Get:explode(" ")
C = Raw[1,string] Raw:remove(1)
A = Raw:concat(" "):trim()
if(!Busy) {
# GENERIC:
if(C == "prt") {
if(M[A:toNumber(),number]>0) {
D:pushString("M("+A+"):"+M[A:toNumber(),number]:toString())
}
elseif(M[A:toNumber(),string]!="") {
Line = M[A:toNumber(),string]
if(Line:length()>30) {
D:pushString("M("+A+")>>>>>>>")
M[997,string] = Line timer("lines",10) }
else{ D:pushString("M("+A+"):"+Line) }
}
elseif(DB[A,string]!="") {
Line = DB[A,string]
if(Line:length()>30) {
D:pushString("D("+A+")>>>>>>>")
M[997,string] = Line timer("lines",10) }
else{ D:pushString("D("+A+"):"+Line) }
}
else{
D:pushString("|:"+A)
}
}
elseif( C == "do") {
timer(A,20)
}
elseif(C == "file") {
M[1201,string] = A:replace(" ","")
D:pushString("file/function: ("+M[1201,string]+"):")
D:pushString("-":repeat(30))
Busy = 1
}
elseif(C == "run") {
Raw = DB[A,string]:explode(",")
for(I=1,Raw:count()) {
Action:pushString(Raw[I,string])
}
}
elseif(C == "for") {
Raw = A:explode(" ")
Start = Raw[1,string]:toNumber() End = Raw[2,string]:toNumber()
Str = ""
for(I=3,Raw:count()) {
Str = Str +" "+ Raw[I,string]
}
for(I=Start,End) {
Action:pushString(Str:trim())
}
}
elseif(C == "runfile") {
if(A== "script") {
File = "script.txt"
}
else{
File = M[A:toNumber(),string]
}
Raw = fileRead(File):trim():explode(",")
for(I=1,Raw:count()) {
Action:pushString(Raw[I,string])
}
}
elseif(C == "delay") {
M[996,number] = M[A:toNumber(),number]
}
elseif(C == "wait") {
M[995,number] = M[A:toNumber(),number]
}
elseif(C == "break") {
while(Action:count()>0) { Action:remove(1) }
stoptimer("enter")
}
elseif(C == "beep") {
soundPlay(1,0.2,"synth/tri.wav")
if(A!="") { soundPitch(1,M[A:toNumber(),number]) } else { soundPitch(1,100) }
}
# FNET Request:
elseif(C == "fnetreq") {
Raw = A:explode(" ")
Table = table()
Table["get",string] = M[Raw[2,string]:toNumber(),string]
Table["steamid",string] = owner():steamID()
Table["msg",string] = "SENT THROUGH BULKOS"
Table["id",number] = M[Raw[3,string]:toNumber(),number]
M[Raw[1,string]:toNumber(),string] = glonEncode(Table)
D:pushString("Built FNET request.")
}
# MEMORY HANDLING:
# Manual memory setting:
elseif(C == "setnum") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = Raw[2,string]:toNumber()
}
elseif(C == "setstr") {
Raw = A:explode(" ") Num = Raw[1,string]:toNumber() Raw:remove(1)
M[Num,string] = Raw:concat(" ")
}
# PRINT MEM
elseif(C == "prtmem") {
Raw = A:explode(" ")
From = Raw[1,string]:toNumber() To = Raw[2,string]:toNumber()
for(I=From,To) {
Action:pushString("prt "+I)
}
}
# Math:
elseif(C == "add") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[1,string]:toNumber(),number] + M[Raw[2,string]:toNumber(),number]
}
elseif(C == "sub") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[1,string]:toNumber(),number] - M[Raw[2,string]:toNumber(),number]
}
elseif(C == "mul") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[1,string]:toNumber(),number] * M[Raw[2,string]:toNumber(),number]
}
elseif(C == "div") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[1,string]:toNumber(),number] / M[Raw[2,string]:toNumber(),number]
}
elseif(C == "inc") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[1,string]:toNumber(),number] +1
}
elseif(C == "dec") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[1,string]:toNumber(),number] -1
}
elseif(C == "inv") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = !M[Raw[1,string]:toNumber(),number]
}
# Memory swap:
elseif(C == "swap") {
M = glonDecode(DB[M[Raw[1,string]:toNumber(),string],string])
}
# Memory swap:
elseif(C == "store") {
DB[M[Raw[1,string]:toNumber(),string],string] = glonEncode(M)
}
# Branching:
elseif(C == "equal") {
Raw = A:explode(" ")
BA = M[Raw[1,string]:toNumber(),number] BB = M[Raw[2,string]:toNumber(),number]
Equal = BA == BB
if(Equal) {
Str = ""
for(I=3,Raw:count()) { Str = Str +" "+ Raw[I,string] }
Action:pushString(Str:trim())
}
}
elseif(C == "notequal") {
Raw = A:explode(" ")
BA = M[Raw[1,string]:toNumber(),number] BB = M[Raw[2,string]:toNumber(),number]
Equal = BA != BB
if(Equal) {
Str = ""
for(I=3,Raw:count()) { Str = Str +" "+ Raw[I,string] }
Action:pushString(Str:trim())
}
}
elseif(C == "more") {
Raw = A:explode(" ")
BA = M[Raw[1,string]:toNumber(),number] BB = M[Raw[2,string]:toNumber(),number]
Equal = BA >= BB
if(Equal) {
Str = ""
for(I=3,Raw:count()) { Str = Str +" "+ Raw[I,string] }
Action:pushString(Str:trim())
}
}
elseif(C == "less") {
Raw = A:explode(" ")
BA = M[Raw[1,string]:toNumber(),number] BB = M[Raw[2,string]:toNumber(),number]
Equal = BA <= BB
if(Equal) {
Str = ""
for(I=3,Raw:count()) { Str = Str +" "+ Raw[I,string] }
Action:pushString(Str:trim())
}
}
# File functions:
elseif(C == "load") {
File = M[A:toNumber(),string]
timer("reload",30)
}
# File functions:
elseif(C == "read") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),string] = fileRead(M[Raw[2,string]:toNumber(),string])
}
elseif(C == "write") {
Raw = A:explode(" ")
fileWrite(M[Raw[1,string]:toNumber(),string],M[Raw[2,string]:toNumber(),string])
}
elseif(C == "append") {
Raw = A:explode(" ")
fileAppend(M[Raw[1,string]:toNumber(),string],M[Raw[2,string]:toNumber(),string])
}
elseif(C == "remove") {
fileRemove(M[A:toNumber(),string])
D:pushString("Removed file!")
}
# Data copy:
elseif(C == "putnum") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = M[Raw[2,string]:toNumber(),number]
}
elseif(C == "putstr") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),string] = M[Raw[2,string]:toNumber(),string]
}
elseif(C == "putstrdb") {
Raw = A:explode(" ")
DB[M[Raw[1,string]:toNumber(),string],string] = M[Raw[2,string]:toNumber(),string]
}
elseif(C == "putnumdb") {
Raw = A:explode(" ")
DB[M[Raw[1,string]:toNumber(),string],number] = M[Raw[2,string]:toNumber(),number]
}
elseif(C == "getstrdb") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),string] = DB[M[Raw[2,string]:toNumber(),string],string]
}
elseif(C == "getnumdb") {
Raw = A:explode(" ")
M[Raw[1,string]:toNumber(),number] = DB[M[Raw[2,string]:toNumber(),string],number]
}
elseif(C == "out") {
Raw = A:explode(" ") Num1 = M[Raw[1,string]:toNumber(),number] Num2 = Raw[2,string]:toNumber()
M[800+Num1,number] = M[Num2,number]
}
# Networking:
elseif(C == "connect") {
Raw = A:explode(" ")
M[994,string] = A
D:pushString("Connected to: "+A)
}
elseif(C == "sendstr") {
Raw = A:explode(" ")
gSetGroup(M[994,string]) gShare(1)
gSetStr(M[Raw[1,string]:toNumber(),number],M[Raw[2,string]:toNumber(),string])
}
elseif(C == "sendnum") {
Raw = A:explode(" ")
gSetGroup(M[994,string]) gShare(1)
gSetNum(M[Raw[1,string]:toNumber(),number],M[Raw[2,string]:toNumber(),number])
}
elseif(C == "recvstr") {
Raw = A:explode(" ")
gSetGroup(M[994,string]) gShare(1)
M[Raw[1,string]:toNumber(),string] = gDeleteStr(M[Raw[2,string]:toNumber(),number])
}
elseif(C == "recvnum") {
Raw = A:explode(" ")
gSetGroup(M[994,string]) gShare(1)
M[Raw[1,string]:toNumber(),number] = gDeleteNum(M[Raw[2,string]:toNumber(),number])
}
}
else{
if(Get == "end") { Busy = 0
DB[M[1201,string],string] = M[1200,string]:trim()
M[1200,string] = ""
D:pushString("-":repeat(30))
D:pushString("File stored.")
}
else {
M[1200,string] = M[1200,string] + Get
}
# if(Get:length()>30) {
# M[997,string] = Get timer("lines",10) }
# D:pushString("-":repeat(30))
}
}
# CALL functions:
elseif(clk("reset") | ~Switch & Switch) {
reset()
}
elseif(clk("dumpmem")) {
DB["mem",string] = glonEncode(M)
timer("save",50)
}
elseif(clk("loadmem")) {
M = glonDecode(DB["mem",string])
}
elseif(clk("lines")) {
Str = M[997,string]
T = Str:length()/30
for(I=0,T) {
D:pushString(Str:sub(31*I,Str:length()))
}
D:pushString("-":repeat(30))
}
elseif(clk("save")) {
File = "bulkos.txt"
fileWrite(File,glonEncode(DB))
D:pushString("File saved!")
}
elseif(clk("prtops")) {
D:pushString("ops:"+opcounter())
}
# Action buffer:
if(Action:count()>0) {
M[999,string] = Action[1,string]
Action:remove(1)
if(M[996,number]>20 & !Action:count()) { Time = M[996,number] }
else { Time = 20 }
if(M[995,number]>20) {
Time = M[995,number] M[995,number] = 0
}
timer("enter",Time)
}
# Output buffer:
while(D:count()>0) {
S[2038] = 1
S:writeString(D[1,string]:sub(0,30),0,17,FG,BG)
D:remove(1)
}
PortA = M[801,number] PortB = M[802,number]
PortC = M[803,number] PortD = M[804,number]
M[901,number] = InA M[902,number] = InB
M[903,number] = InC M[904,number] = InD
Bookmarks