// 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 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 }