Two sources capturing the same game name the same map, and the shared tile tree named their pyramids identically -- the second built would replace the first, and both games' bundles then embedded whichever survived. When names collide, every collider now takes its layer path into its directory name, all of them, so the outcome does not depend on the order the archive lists its games in.
- commit
- a2ee4b2179af3da2b6c40953f1bcdc8fd2f3c2a3
- parent
- ecce87aa1c51b67e377ea47c75ea0d1bb754fabc
- author
- Dami <dami.etoile@gmail.com>
| M | tools/ | 67 | +++++++++++++++++++++--------- |
@@ -308,7 +308,12 @@ func run(source, output string, force bool) error {
308308 var carried int309309 derived := make(map[string]bool)310310 311- out := manifest{TileSize: tileSize, Size: worldSize}311+ type pendingPlan struct {312+ gameTitle string313+ title string314+ plan tilePlan315+ }316+ var pending []pendingPlan312317 for _, game := range index.Games {313318 mapDirs, err := filepath.Glob(filepath.Join(source, game.Directory, "maps", "*"))314319 if err != nil {@@ -332,27 +337,51 @@ func run(source, output string, force bool) error {
332337 continue333338 }334339 for _, plan := range plans {335- stamp := planStamp(plan)336- if kept, ok := carry(built, plan, stamp, output, force); ok {337- // The window is read from the archive rather than derived338- // from the pyramid, so it is answered from the plan even339- // for a layer nothing has changed under.340- kept.Grid = plan.Frame.grid()341- out.Variants = append(out.Variants, kept)342- carried++343- continue344- }345- fmt.Printf("tile %s / %s / %s\n", game.Title, title, plan.SourcePath)346- entry, err := buildPyramid(temp, plan)347- if err != nil {348- return fmt.Errorf("%s / %s: %w", title, plan.SourcePath, err)349- }350- entry.Stamp = stamp351- out.Variants = append(out.Variants, entry)352- derived[plan.AssetPath] = true340+ pending = append(pending, pendingPlan{gameTitle: game.Title, title: title, plan: plan})353341 }354342 }355343 }344+345+ // Two sources capturing the same game name the same directory for the346+ // same map. Every collider takes its layer path into its name -- all of347+ // them, so the outcome does not depend on the order the archive lists348+ // its games in.349+ byAssetPath := make(map[string][]int, len(pending))350+ for index := range pending {351+ byAssetPath[pending[index].plan.AssetPath] = append(352+ byAssetPath[pending[index].plan.AssetPath], index)353+ }354+ for _, colliders := range byAssetPath {355+ if len(colliders) < 2 {356+ continue357+ }358+ for _, at := range colliders {359+ pending[at].plan.AssetPath += "__" + slugify(pending[at].plan.SourcePath)360+ }361+ }362+363+ out := manifest{TileSize: tileSize, Size: worldSize}364+ for _, entry := range pending {365+ plan := entry.plan366+ stamp := planStamp(plan)367+ if kept, ok := carry(built, plan, stamp, output, force); ok {368+ // The window is read from the archive rather than derived369+ // from the pyramid, so it is answered from the plan even370+ // for a layer nothing has changed under.371+ kept.Grid = plan.Frame.grid()372+ out.Variants = append(out.Variants, kept)373+ carried++374+ continue375+ }376+ fmt.Printf("tile %s / %s / %s\n", entry.gameTitle, entry.title, plan.SourcePath)377+ variant, err := buildPyramid(temp, plan)378+ if err != nil {379+ return fmt.Errorf("%s / %s: %w", entry.title, plan.SourcePath, err)380+ }381+ variant.Stamp = stamp382+ out.Variants = append(out.Variants, variant)383+ derived[plan.AssetPath] = true384+ }356385 sort.Slice(out.Variants, func(i, j int) bool {357386 return out.Variants[i].SourcePath < out.Variants[j].SourcePath358387 })