view State.lua @ 72:9e5b0a2368ad

Big progress towards GUI usefulness and communication between clients
author John@Yosemite-PC
date Sat, 07 Apr 2012 13:35:57 -0400
parents d5e2dfe0c269
children 7eb2963eea7d
line wrap: on
line source
local bsk=bsk
local _G=_G
local table=table 
local pairs=pairs
local setmetatable=setmetatable
local ipairs=ipairs
local string=string
local sformat=string.format
local tostring=tostring
local type=type
local unpack=unpack
local getn=getn
setfenv(1,bsk)

-- simple state machine

--Begin loot
--Activate list ... only during looting?
--open bidding/rolling
--bid/roll occurred
--remove bid/roll
--close bidding
--remove item


-- we'll track state, but that may or may not result in a GUI change until down
-- the road

-- todo: transmit this all to only the raid, not the guild?

-- sample procedure
-- person B opens GUI.
-- person A begins looting, sets a list
-- person A begins bidding, transmists the state
-- person B goes into bidding state, their button activates
-- person B clicks the button. button changes state.
-- person B broadcasts their bid. if a bid, everyone just accepts it.
--              - if a roll, then the master does the roll and rebroadcasts

state = "neutral" -- states that are possible: neutral, looting, bidding
local looting = false
stateactive = nil
stateitem = nil
statebids = {}
staterolls = {}
stateactivelist = nil

local rollListeners = {}
function RegisterListenerRolls(listener)
    table.insert(rollListeners,listener)
end
function AlertRollListeners()
    for i,v in pairs(rollListeners) do
        print("roll out")
        v["RollEvent"](v)
    end
end

local listChangeListeners = {}
function RegisterListenerActiveListChanged(listener)
    table.insert(listChangeListeners,listener)
end
function AlertActiveListChangedListeners()
    for i,v in pairs(listChangeListeners) do
        print("list out")
        v["ActiveListEvent"](v)
    end
end

local stateChangeListeners = {}
function RegisterListenerStateChange(listener)
    table.insert(stateChangeListeners,listener)
end
function AlertStateChangeListeners()
    for i,v in pairs(stateChangeListeners) do
        print("state out")
        v["StateEvent"](v)
    end
end

function BeginLoot(listValue)
    if state == "neutral" then
        state = "looting"
        looting = true
        active = listValue
    else
        _G.error("Bad state transition", state, "looting")
    end
end


-- Activate List {{{
function ActivateList(packet) -- doesn't cause a transition, but we only enforce a list selection during certain times
    local list = unpack(packet)
    if state == "looting" then
        stateactivelist = list
        AlertActiveListChangedListeners()
    end
end

function InitiateActivateList(list)
    if state == "looting" then
        Comm:SendStateChange("AL",list)
    end
end
--}}}
-- Open Bidding {{{
function OpenBid(packet)
    local item = unpack(packet)
    --if state == "looting" then
        state = "bidding"
        item = value
    --end
end

function InitiateOpenBid(item)
    --if state == "looting" then
    Comm:SendStateChange("OB",item)
    --end
end
--}}}
-- Bid {{{
function ReceivedBid(packet) -- no state transition, but only matters during one state
    local person, roll = unpack(packet)

    if state == "bidding" then
        if roll then
            table.insert(statebids,person) -- todo:
        else
            table.insert(statebids,person) -- todo: keep sorted
        end
        AlertRollListeners()
    end

    -- else ignore ...
end

function InitiateBid(person,roll)
    if state == "bidding" then
        for i,v in pairs(statebids) do
            if person.value == v.value then
                print(person.value .. " is already on the list")
                return -- no double adds please
            end
        end
        Comm:SendStateChange("RB",person,roll)
    end
end
--}}}
-- Retration {{{
function ReceivedRetraction(packet)
    local person = unpack(packet)
    if state == "bidding" then
        for i,v in pairs(statebids) do
            if v.value == person.value then
                table.remove(statebids,i)
                AlertRollListeners()
                return
            end
        end
    end
end

function InitiateRetract(person)
    if state == "bidding" then
        Comm:SendStateChange("RR",person,roll)
    end
end
--}}}
-- Close Bidding {{{
function CloseBidding(packet)
    local awardedTo = unpack(packet) 
    state = "looting"
    -- remove the item from the window, record history
end

function InitiateCloseBidding(awardedTo)
    Comm:SendStateChange("CB",awardedTo)
end
--}}}

function CloseLooting(packet)
    state = "neutral"
    active = nil
    item = nil
    bids = {}
    rolls = {}
end

function InitiateCloseLooting()
    Comm:SendStateChange("CL")
end

function DispatchState(packet)
    local state = table.remove(packet,1)
    print("Dispatching", state)
    if state == "RB" then
        ReceivedBid(packet)
    elseif state == "RR" then
        ReceivedRetraction(packet)
    elseif state == "OB" then
        OpenBid(packet)
    elseif state == "CB" then
        CloseBidding(packet)
    elseif state == "CB" then
        CloseLooting(packet)
    elseif state == "AL" then
        ActivateList(packet)
    else -- todo ...

    end
end