func LuaPushSmartFunctionTable(L *lua.State, ft FunctionTable) { // Copy it just in case - I can't imagine someone changing it after passing // it to this function, but I don't want to take any chances. myft := make(FunctionTable) for n, f := range ft { myft[n] = f } names := make([]string, len(myft))[0:0] for name := range myft { names = append(names, name) } sort.Strings(names) valid_selectors := "[" for i, name := range names { if i > 0 { valid_selectors += ", " } valid_selectors += fmt.Sprintf("'%s'", name) } valid_selectors += "]." L.NewTable() L.PushString("__index") L.PushGoFunctionAsCFunction(func(L *lua.State) int { name := L.ToString(-1) if f, ok := myft[name]; ok { f() } else { base.Error().Printf("'%s' is not a valid selector, valid seletors are %s", name, valid_selectors) L.PushNil() } return 1 }) L.SetTable(-3) }
func readInput(l *lua.State) { bstdin := bufio.NewReader(os.Stdin) for { var line string // TODO: Something better for windows? line, e := bstdin.ReadString('\n') if e != nil { shell.Println(e) } er := l.LoadString(line) if er != 0 { // Pop of the error description str := l.ToString(-1) shell.Println("Error loading: ", str) continue } er = l.PCall(0, lua.LUA_MULTRET, 0) if er != 0 { str := l.ToString(-1) shell.Println("Error running: ", str) continue } sesLog.Println(line) } }
func LuaIsEntity(L *lua.State, index int) bool { L.PushString("type") L.GetTable(index - 1) if L.IsNil(-1) { L.Pop(1) return false } if L.ToString(-1) == "Entity" { L.Pop(1) return true } L.Pop(1) return false }
// Encodes a lua value, only bool, number, nil, table, and string can be // encoded. If an unencodable value is encountered an error will be // returned. func LuaEncodeValue(w io.Writer, L *lua.State, index int) error { var err1, err2, err3 error switch { case L.IsBoolean(index): err1 = binary.Write(w, binary.LittleEndian, luaEncBool) var v byte = 0 if L.ToBoolean(index) { v = 1 } err2 = binary.Write(w, binary.LittleEndian, v) case L.IsNumber(index): err1 = binary.Write(w, binary.LittleEndian, luaEncNumber) err2 = binary.Write(w, binary.LittleEndian, L.ToNumber(index)) case L.IsNil(index): err1 = binary.Write(w, binary.LittleEndian, luaEncNil) case LuaIsEntity(L, index): err1 = binary.Write(w, binary.LittleEndian, luaEncEntity) L.PushString("id") L.GetTable(index - 1) err2 = binary.Write(w, binary.LittleEndian, uint64(L.ToInteger(-1))) L.Pop(1) case L.IsTable(index): err1 = binary.Write(w, binary.LittleEndian, luaEncTable) err2 = LuaEncodeTable(w, L, index) case L.IsString(index): err1 = binary.Write(w, binary.LittleEndian, luaEncString) str := L.ToString(index) err2 = binary.Write(w, binary.LittleEndian, uint32(len(str))) err3 = binary.Write(w, binary.LittleEndian, []byte(str)) default: return errors.New(fmt.Sprintf("Cannot encode lua type id == %d.", L.Type(index))) } switch { case err1 != nil: return err1 case err2 != nil: return err2 case err3 != nil: return err3 } return nil }
func LuaStringifyParam(L *lua.State, index int) string { if L.IsTable(index) { str := "table <not implemented> {" return str first := true L.PushNil() for L.Next(index-1) != 0 { if !first { str += ", " } first = false str += fmt.Sprintf("(%s) -> (%s)", LuaStringifyParam(L, -2), LuaStringifyParam(L, -1)) L.Pop(1) } return str + "}" } if L.IsBoolean(index) { if L.ToBoolean(index) { return "true" } return "false" } return L.ToString(index) }
func LuaCheckParamsOk(L *lua.State, name string, params ...LuaType) bool { fmt.Sprintf("%s(") n := L.GetTop() if n != len(params) { LuaDoError(L, fmt.Sprintf("Got %d parameters to %s.", n, luaMakeSigniature(name, params))) return false } for i := -n; i < 0; i++ { ok := false switch params[i+n] { case LuaInteger: ok = L.IsNumber(i) case LuaFloat: ok = L.IsNumber(i) case LuaBoolean: ok = L.IsBoolean(i) case LuaString: ok = L.IsString(i) case LuaEntity: if L.IsTable(i) { L.PushNil() for L.Next(i-1) != 0 { if L.ToString(-2) == "type" && L.ToString(-1) == "Entity" { ok = true } L.Pop(1) } } case LuaPoint: if L.IsTable(i) { var x, y bool L.PushNil() for L.Next(i-1) != 0 { if L.ToString(-2) == "X" { x = true } if L.ToString(-2) == "Y" { y = true } L.Pop(1) } ok = x && y } case LuaRoom: if L.IsTable(i) { var floor, room, door bool L.PushNil() for L.Next(i-1) != 0 { switch L.ToString(-2) { case "floor": floor = true case "room": room = true case "door": door = true } L.Pop(1) } ok = floor && room && !door } case LuaDoor: if L.IsTable(i) { var floor, room, door bool L.PushNil() for L.Next(i-1) != 0 { switch L.ToString(-2) { case "floor": floor = true case "room": room = true case "door": door = true } L.Pop(1) } ok = floor && room && door } case LuaSpawnPoint: if L.IsTable(i) { L.PushNil() for L.Next(i-1) != 0 { if L.ToString(-2) == "type" && L.ToString(-1) == "SpawnPoint" { ok = true } L.Pop(1) } } case LuaArray: // Make sure that all of the indices 1..length are there, and no others. check := make(map[int]int) if L.IsTable(i) { L.PushNil() for L.Next(i-1) != 0 { if L.IsNumber(-2) { check[L.ToInteger(-2)]++ } else { break } L.Pop(1) } } count := 0 for i := 1; i <= len(check); i++ { if _, ok := check[i]; ok { count++ } } ok = (count == len(check)) case LuaTable: ok = L.IsTable(i) case LuaAnything: ok = true } if !ok { LuaDoError(L, fmt.Sprintf("Unexpected parameters to %s.", luaMakeSigniature(name, params))) return false } } return true }