- Joined
- Feb 6, 2014
- Messages
- 2,466
JASS:
library SystemConsole /*
SystemConsole v1.01
by Flux
SystemConsole is a text-console simulation for Warcraft 3.
It main purpose is to display information to players in a
console format thus it logs all messages displayed so
players can view it again anytime. It can hold up to 8192
line messages in its buffer.
It can also be used as a debugging tool through its
SystemTest feature.
*/ requires /*
(nothing)
*/ optional Table /*
If not found, it will create a hashtable. Hashtables are limited to
255 per map.
Includes:
* SystemMsg
- The interface for displaying game messages.
API:
- SystemMsg.create(string msg)
Display message.
- SystemMsg.createEx(string title, string msg)
Display titled message.
- SystemMsg.createIf(boolean condition, string msg)
Display message if condition is true.
- SystemMsg.createIfEx(boolean condition, string title, string msg)
Display titled message if condition is true.
- set SystemMsg.show = true/false
Controls the visibility of System Messages.
* SystemTest
- Test a function or a group of functions if it
will execute without fail. Enclosed the function(s)
to be tested between SystemTest.start(msg) and
SystemTest.end().
API:
- SystemTest.start(string msg)
Starting block of SystemTest
- SystemTest.startEx(string title, string msg)
Titled starting block of SystemTest
- SystemTest.end()
End block of SystemTest
*/
globals
//The Player who can see the System messages. Use GetLocalPlayer() to make
//it visible to all.
private constant player HOST = Player(0)
//Title color for titled messages
private constant string TITLE_COLOR = "|cffffcc00"
//Duration of system messages
private constant real DURATION = 10000
//The time allotted for a SystemTest to finish before it is considered a failure
private constant real DELAY = 0.25
//Maximum number of lines saved in memory
public constant integer BUFFER = 256
endglobals
struct SystemMsg
string value
readonly thistype next
readonly thistype prev
private static boolean privShow = true
readonly static integer count = 0
static integer lineCount = 0
static integer cursor = 16
static method refresh takes nothing returns nothing
local thistype this = thistype(0).next
local integer i = 0
local integer j = thistype.count - cursor
if thistype.privShow then
if HOST == GetLocalPlayer() then
call ClearTextMessages()
endif
loop
exitwhen this == 0
if i >= j and i < j + 16 then
call DisplayTimedTextToPlayer(HOST, 0, 0, DURATION, this.value)
endif
set i = i + 1
set this = this.next
endloop
endif
endmethod
method destroy takes nothing returns nothing
set this.next.prev = this.prev
set this.prev.next = this.next
set thistype.count = thistype.count - 1
call this.deallocate()
endmethod
static method create takes string s returns thistype
local thistype this = thistype.allocate()
set thistype.lineCount = thistype.lineCount + 1
set this.value = "|cff999999#" + I2S(thistype.lineCount) + "|r: " + s
set this.next = 0
set this.prev = thistype(0).prev
set this.next.prev = this
set this.prev.next = this
if thistype.count == BUFFER then
call thistype(0).next.destroy()
else
set thistype.count = thistype.count + 1
endif
if thistype.privShow and thistype.cursor <= 16 then
call DisplayTimedTextToPlayer(HOST, 0, 0, DURATION, this.value)
endif
if thistype.cursor > 16 then
set thistype.cursor = thistype.cursor + 1
endif
return this
endmethod
static method createEx takes string title, string s returns thistype
return thistype.create(TITLE_COLOR + "[" + title + "]|r " + s)
endmethod
static method createIf takes boolean b, string s returns thistype
if b then
return thistype.create(s)
endif
return 0
endmethod
static method createIfEx takes boolean b, string title, string s returns thistype
if b then
return thistype.createEx(title, s)
endif
return 0
endmethod
static method operator show takes nothing returns boolean
return thistype.privShow
endmethod
static method operator show= takes boolean b returns nothing
set thistype.privShow = b
if b then
call thistype.refresh()
else
if HOST == GetLocalPlayer() then
call ClearTextMessages()
endif
endif
endmethod
endstruct
struct SystemTest
private boolean checker
private timer t
private SystemMsg msg
private thistype next
static if LIBRARY_Table then
private static Table tb
else
private static hashtable hash = InitHashtable()
endif
method destroy takes nothing returns nothing
if this.checker then
set this.msg.value = this.msg.value + " [ |cff00ff00OK|r ]"
else
set this.msg.value = this.msg.value + " [ |cffff0000Failed|r ]"
endif
call SystemMsg.refresh()
static if LIBRARY_Table then
call thistype.tb.remove(GetHandleId(this.t))
else
call RemoveSavedInteger(thistype.hash, GetHandleId(this.t), 0)
endif
call PauseTimer(this.t)
call DestroyTimer(this.t)
set this.t = null
call this.deallocate()
endmethod
private static method expires takes nothing returns nothing
static if LIBRARY_Table then
call thistype(thistype.tb[GetHandleId(GetExpiredTimer())]).destroy()
else
call thistype(LoadInteger(thistype.hash, GetHandleId(GetExpiredTimer()), 0)).destroy()
endif
endmethod
static method create takes string s returns thistype
local thistype this = thistype.allocate()
set this.msg = SystemMsg.create(s)
set this.checker = false
set this.t = CreateTimer()
static if LIBRARY_Table then
set thistype.tb[GetHandleId(t)] = this
else
call SaveInteger(thistype.hash, GetHandleId(t), 0, this)
endif
call TimerStart(this.t, DELAY, false, function thistype.expires)
return this
endmethod
static method start takes string s returns nothing
local thistype this = thistype.create(s)
//Push
set this.next = thistype(0).next
set thistype(0).next = this
endmethod
static method startEx takes string title, string s returns nothing
call thistype.create(TITLE_COLOR + "[" + title + "]|r " + s)
endmethod
static method end takes nothing returns nothing
local thistype this = thistype(0).next
debug if this == 0 then
debug call SystemMsg.create("Missing SystemTest.start(<message>)")
debug return
debug endif
//Pop
set thistype(0).next = this.next
set this.checker = true
call this.destroy()
endmethod
static if LIBRARY_Table then
private static method onInit takes nothing returns nothing
set thistype.tb = Table.create()
endmethod
endif
endstruct
endlibrary
JASS:
library SystemConsoleCommands requires SystemConsole
/*
SystemConsoleCommands v1.00
by Flux
Contains various console commands to control visibility
or to scroll the console messages.
COMMANDS:
">show" - Shows/unhide the console
">hide" - Hides the console
">down #" - Scroll the console cursor downward by # lines
">up #" - Scroll the console cursor upward by # lines
">clear" - Clears the console
*/
globals
private constant string CMD_PREFIX = ">"
endglobals
struct ConsoleCommand extends array
private static method show takes nothing returns boolean
if GetLocalPlayer() == GetTriggerPlayer() then
set SystemMsg.show = true
endif
return false
endmethod
private static method hide takes nothing returns boolean
if GetLocalPlayer() == GetTriggerPlayer() then
set SystemMsg.show = false
endif
return false
endmethod
private static method clear takes nothing returns boolean
local SystemMsg this = SystemMsg(0).next
loop
exitwhen this == 0
call this.destroy()
set this = this.next
endloop
set SystemMsg.lineCount = 0
call SystemMsg.refresh()
return false
endmethod
private static method up takes nothing returns boolean
local string s = GetEventPlayerChatString()
local integer length = StringLength(s)
local integer d = 1
local integer temp
if length > 4 then
set d = S2I(SubString(s, 4, length))
if d < 1 then
set d = 0
endif
endif
if GetLocalPlayer() == GetTriggerPlayer() then
set temp = SystemMsg.cursor + d
if temp < SystemMsg.count + 16 then
set SystemMsg.cursor = temp
else
set SystemMsg.cursor = SystemMsg.count + 15
endif
endif
call SystemMsg.refresh()
return false
endmethod
private static method down takes nothing returns boolean
local string s = GetEventPlayerChatString()
local integer length = StringLength(s)
local integer d = 1
if length > 6 then
set d = S2I(SubString(s, 6, length))
if d < 1 then
set d = 0
endif
endif
if GetLocalPlayer() == GetTriggerPlayer() then
if SystemMsg.cursor - d > 16 then
set SystemMsg.cursor = SystemMsg.cursor - d
else
set SystemMsg.cursor = 16
endif
endif
call SystemMsg.refresh()
return false
endmethod
//! textmacro CONSOLE_CMD_TRIGGER_REGISTER takes WORD, MATCH
set t = CreateTrigger()
call TriggerRegisterPlayerChatEvent(t, p, CMD_PREFIX + "$WORD$", $MATCH$)
call TriggerAddCondition(t, function thistype.$WORD$)
//! endtextmacro
static method register takes player p returns nothing
local trigger t
//! runtextmacro CONSOLE_CMD_TRIGGER_REGISTER("show", "true")
//! runtextmacro CONSOLE_CMD_TRIGGER_REGISTER("hide", "true")
//! runtextmacro CONSOLE_CMD_TRIGGER_REGISTER("clear", "true")
//! runtextmacro CONSOLE_CMD_TRIGGER_REGISTER("up", "false")
//! runtextmacro CONSOLE_CMD_TRIGGER_REGISTER("down", "false")
set t = null
endmethod
private static method onInit takes nothing returns nothing
call thistype.register(GetLocalPlayer())
endmethod
endstruct
endlibrary
Basic Example:
JASS:
call SystemMsg.create("Hello Cruel World!")
JASS:
local unit u
call SystemTest.start("Killing Undefined unit:")
call KillUnit(u) //unit u does not have a value
call SystemTest.end()
call SystemMsg.create("This won't run because the function prematurely ends")
Killing Undefined unit: [ Failed ]
I highly advised checking out the attached map because it has more demos
Changelog:
v1.00 - [18 September 2016]
- Initial Release
v1.01 - [19 September 2016]
- Included SystemConsoleCommands
- Improved Demos
- Fixed ClearTextMessage affecting all players.
Attachments
Last edited: