Rebuild SCUM plugin-owned data flow
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
@@ -416,7 +417,7 @@ func rewardGrant(payload map[string]any) (RewardGrant, error) {
|
||||
playerID, playerOK := payload["playerId"].(string)
|
||||
rawItems, itemsOK := payload["items"].([]any)
|
||||
rawOperations, operationsOK := payload["operations"].([]any)
|
||||
if !grantOK || !playerOK || !itemsOK || !operationsOK || (len(rawItems) == 0 && len(rawOperations) == 0) || len(rawItems) > 8 {
|
||||
if !grantOK || !playerOK || !itemsOK || !operationsOK || (len(rawItems) == 0 && len(rawOperations) == 0) {
|
||||
return RewardGrant{}, fmt.Errorf("reward payload is invalid")
|
||||
}
|
||||
items := make([]RewardItem, 0, len(rawItems))
|
||||
@@ -427,7 +428,7 @@ func rewardGrant(payload map[string]any) (RewardGrant, error) {
|
||||
}
|
||||
code, codeOK := item["catalogCode"].(string)
|
||||
quantity, quantityOK := integerPayloadValue(item["quantity"])
|
||||
if !codeOK || !supportedCatalogCode(code) || !quantityOK || quantity < 1 || quantity > 100 {
|
||||
if !codeOK || !supportedCatalogCode(code) || !quantityOK || quantity < 1 {
|
||||
return RewardGrant{}, fmt.Errorf("reward payload is invalid")
|
||||
}
|
||||
items = append(items, RewardItem{CatalogCode: code, Quantity: quantity})
|
||||
@@ -456,7 +457,7 @@ func eventStartRequest(payload map[string]any) (EventStartRequest, error) {
|
||||
for index, key := range []string{"npc", "item", "zombie", "animal"} {
|
||||
if value, exists := payload[key]; exists {
|
||||
count, ok := integerPayloadValue(value)
|
||||
if !ok || count < 0 || count > 10000 {
|
||||
if !ok || count < 0 {
|
||||
return EventStartRequest{}, fmt.Errorf("event start payload is invalid")
|
||||
}
|
||||
counts[index] = count
|
||||
@@ -466,7 +467,7 @@ func eventStartRequest(payload map[string]any) (EventStartRequest, error) {
|
||||
if value, exists := payload["maxParticipants"]; exists {
|
||||
var ok bool
|
||||
participants, ok = integerPayloadValue(value)
|
||||
if !ok || participants < 1 || participants > 1000 {
|
||||
if !ok || participants < 1 {
|
||||
return EventStartRequest{}, fmt.Errorf("event start payload is invalid")
|
||||
}
|
||||
}
|
||||
@@ -478,7 +479,7 @@ func eventStartRequest(payload map[string]any) (EventStartRequest, error) {
|
||||
return EventStartRequest{}, fmt.Errorf("event start payload is invalid")
|
||||
}
|
||||
}
|
||||
if !eventIDOK || !eventTypeOK || !classOK || !titleOK || !durationOK || !percentOK || !placardOK || !producesOK || !supportedEventType(eventType) || eventClass < 1 || eventClass > 2 || (eventClass == 1) != (eventType == "range") || strings.TrimSpace(eventID) == "" || strings.TrimSpace(title) == "" || len(placard) > 500 || percent < 0 || percent > 100 || duration < 30 || duration > 86400 {
|
||||
if !eventIDOK || !eventTypeOK || !classOK || !titleOK || !durationOK || !percentOK || !placardOK || !producesOK || !supportedEventType(eventType) || eventClass < 1 || eventClass > 2 || (eventClass == 1) != (eventType == "range") || strings.TrimSpace(eventID) == "" || strings.TrimSpace(title) == "" || len(placard) > 500 || percent < 0 || percent > 100 || duration < 1 {
|
||||
return EventStartRequest{}, fmt.Errorf("event start payload is invalid")
|
||||
}
|
||||
return EventStartRequest{EventID: eventID, EventType: eventType, Class: eventClass, Title: title, Placard: placard, Percent: percent, NPC: counts[0], Item: counts[1], Zombie: counts[2], Animal: counts[3], Produces: produces, DurationSeconds: duration, MaxParticipants: participants, Announce: announce}, nil
|
||||
@@ -486,7 +487,7 @@ func eventStartRequest(payload map[string]any) (EventStartRequest, error) {
|
||||
|
||||
func eventProduceRequests(value any) ([]EventProduceRequest, bool) {
|
||||
raw, ok := value.([]any)
|
||||
if !ok || len(raw) > 100 {
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
result := make([]EventProduceRequest, 0, len(raw))
|
||||
@@ -502,7 +503,7 @@ func eventProduceRequests(value any) ([]EventProduceRequest, bool) {
|
||||
x, xOK := numberPayloadValue(produce["x"])
|
||||
y, yOK := numberPayloadValue(produce["y"])
|
||||
z, zOK := numberPayloadValue(produce["z"])
|
||||
if !idOK || strings.TrimSpace(tradeGoodsID) == "" || len(tradeGoodsID) > 128 || !percentOK || percent < 0 || percent > 100 || !quantityOK || quantity < 1 || quantity > 10000 || !radiusOK || radius < 0 || radius > 2000000 || !xOK || !yOK || !zOK || x < -2000000 || x > 2000000 || y < -2000000 || y > 2000000 || z < -2000000 || z > 2000000 {
|
||||
if !idOK || strings.TrimSpace(tradeGoodsID) == "" || len(tradeGoodsID) > 128 || !percentOK || percent < 0 || percent > 100 || !quantityOK || quantity < 1 || !radiusOK || radius < 0 || !xOK || !yOK || !zOK {
|
||||
return nil, false
|
||||
}
|
||||
result = append(result, EventProduceRequest{TradeGoodsID: tradeGoodsID, Percent: percent, Value: quantity, Radius: radius, X: x, Y: y, Z: z})
|
||||
@@ -529,20 +530,22 @@ func integerPayloadValue(value any) (int, bool) {
|
||||
}
|
||||
|
||||
func numberPayloadValue(value any) (float64, bool) {
|
||||
var result float64
|
||||
switch number := value.(type) {
|
||||
case float64:
|
||||
return number, true
|
||||
result = number
|
||||
case float32:
|
||||
return float64(number), true
|
||||
result = float64(number)
|
||||
case int:
|
||||
return float64(number), true
|
||||
result = float64(number)
|
||||
case int32:
|
||||
return float64(number), true
|
||||
result = float64(number)
|
||||
case int64:
|
||||
return float64(number), true
|
||||
result = float64(number)
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
return result, !math.IsNaN(result) && !math.IsInf(result, 0)
|
||||
}
|
||||
|
||||
func supportedCatalogCode(value string) bool {
|
||||
|
||||
@@ -104,6 +104,13 @@ func TestRewardDeliveryAcceptsRealSCUMCatalogCodesAndReturnsDeclaredResult(t *te
|
||||
if len(port.grants) != 1 || port.grants[0].Items[0] != (RewardItem{CatalogCode: "BPC_Improvised_Backpack.01", Quantity: 2}) || len(port.grants[0].Operations) != 1 || port.grants[0].Operations[0] != "#SpawnItem BPC_Improvised_Backpack.01 2" {
|
||||
t.Fatalf("reward items or operations did not reach the typed reward port: %+v", port.grants)
|
||||
}
|
||||
manyItems := make([]any, 9)
|
||||
for index := range manyItems {
|
||||
manyItems[index] = map[string]any{"catalogCode": "BPC_Apple", "quantity": float64(101 + index)}
|
||||
}
|
||||
if _, err := adapter.DeliverReward(context.Background(), map[string]any{"grantId": "grant-many", "playerId": "76561198000000001", "items": manyItems, "operations": []any{}}); err != nil || len(port.grants) != 2 || len(port.grants[1].Items) != 9 || port.grants[1].Items[0].Quantity != 101 {
|
||||
t.Fatalf("valid reward count or quantity was rejected: grants=%+v err=%v", port.grants, err)
|
||||
}
|
||||
before := len(port.grants)
|
||||
if _, err := adapter.DeliverReward(context.Background(), map[string]any{
|
||||
"grantId": "grant-2", "playerId": "76561198000000001",
|
||||
@@ -114,6 +121,17 @@ func TestRewardDeliveryAcceptsRealSCUMCatalogCodesAndReturnsDeclaredResult(t *te
|
||||
}
|
||||
}
|
||||
|
||||
func TestEventStartAcceptsPositiveCountsAndDurationWithoutInventedUpperLimits(t *testing.T) {
|
||||
produces := make([]any, 101)
|
||||
for index := range produces {
|
||||
produces[index] = map[string]any{"tradeGoodsId": "cargo-drop", "percent": float64(80), "value": float64(10001 + index), "r": float64(2000001 + index), "x": float64(3000000 + index), "y": float64(-3000000 - index), "z": float64(index)}
|
||||
}
|
||||
request, err := eventStartRequest(map[string]any{"eventId": "event-large", "eventType": "range", "class": float64(1), "title": "Large Event", "placard": "", "percent": float64(100), "npc": float64(10001), "item": float64(10002), "zombie": float64(10003), "animal": float64(10004), "produces": produces, "durationSeconds": float64(86401), "maxParticipants": float64(1001)})
|
||||
if err != nil || request.DurationSeconds != 86401 || request.MaxParticipants != 1001 || request.NPC != 10001 || len(request.Produces) != 101 || request.Produces[0].Value != 10001 || request.Produces[0].Radius != 2000001 {
|
||||
t.Fatalf("valid event values above old limits were rejected: request=%+v err=%v", request, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRewardDeliverySupportsOperationsWithoutItemsAndRejectsEmptyGrant(t *testing.T) {
|
||||
port := &rewardPortFixture{receipt: DeliveryReceipt{Outcome: "delivered"}}
|
||||
adapter := RuntimeAdapter{BoundServerID: "server-1", Rewards: port}
|
||||
|
||||
Reference in New Issue
Block a user