85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
package mapping
|
|
|
|
import (
|
|
"github.com/akmalfairuz/legacy-version/internal"
|
|
"github.com/df-mc/worldupgrader/blockupgrader"
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
|
"golang.org/x/exp/maps"
|
|
)
|
|
|
|
func convert(entries []protocol.BlockEntry) (states []blockupgrader.BlockState) {
|
|
for _, entry := range entries {
|
|
propertiesMap := map[string][]any{}
|
|
if props := jsonCheck[[]any](entry.Properties, "properties"); props != nil {
|
|
for _, prop := range *props {
|
|
prop := prop.(map[string]any)
|
|
name := jsonCheck[string](prop, "name")
|
|
enum := jsonCheck[[]any](prop, "enum")
|
|
if enum == nil {
|
|
int32Enum := jsonCheck[[]int32](prop, "enum")
|
|
if int32Enum != nil {
|
|
enum = &[]any{}
|
|
for _, i := range *int32Enum {
|
|
*enum = append(*enum, i)
|
|
}
|
|
}
|
|
}
|
|
if name == nil || enum == nil {
|
|
panic("could not find field `name` and `enum`")
|
|
}
|
|
propertiesMap[*name] = *enum
|
|
}
|
|
}
|
|
|
|
combinations := make([]map[string]any, 0)
|
|
generateCombinationsRecursively(propertiesMap, internal.NewIterator(maps.Keys(propertiesMap)), map[string]any{}, &combinations)
|
|
if len(combinations) == 0 {
|
|
combinations = append(combinations, map[string]any{})
|
|
}
|
|
|
|
for _, combination := range combinations {
|
|
blockState := blockupgrader.BlockState{
|
|
Name: entry.Name,
|
|
Properties: combination,
|
|
}
|
|
|
|
states = append(states, blockState)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func generateCombinationsRecursively[K comparable, V any](all map[K][]V, iterator *internal.Iterator[K], current map[K]V, output *[]map[K]V) {
|
|
if !iterator.HasNext() {
|
|
entry := map[K]V{}
|
|
for k, v := range current {
|
|
entry[k] = v
|
|
}
|
|
out := append(*output, entry)
|
|
*output = out
|
|
} else {
|
|
key := iterator.Next()
|
|
set := all[key]
|
|
|
|
for _, value := range set {
|
|
current[key] = value
|
|
generateCombinationsRecursively[K, V](all, iterator, current, output)
|
|
delete(current, key)
|
|
}
|
|
|
|
iterator.Previous()
|
|
}
|
|
}
|
|
|
|
func jsonCheck[T any](json map[string]any, field string) *T {
|
|
fieldValue, found := json[field]
|
|
if !found {
|
|
return nil
|
|
}
|
|
castedValue, ok := fieldValue.(T)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return &castedValue
|
|
}
|