Terraria Map Viewer

Developed or developing a new product in PureBasic? Tell the world about it.
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Terraria Map Viewer

Post by epidemicz »

I've been playing with a (dirt simple) Terraria Map Viewer. I've seen a lot of guys' projects floating around and I thought I'd do my own quick & dirty version in PB.

*edit* Forgot to mention it's not completely done, still missing a few things.

Based heavily on this one in particular -> http://seancode.com/terrafirma/.

First, you'll need this xml file, call it tiles.xml. You can get that here -> http://pastebin.com/CncqbM8W.
Second, you'll need a world file for terraria. Should be able to find one here - > http://anotherprophecy.com/system/scrip ... world3.rar.

Code: Select all

;epidemicz
;6/26/2011
;Terraria Map Viewer for 1.0.5
;Based off terrafirma http://seancode.com/terrafirma/


;map vars
Structure tile
  isActive.b
  type.b
  hasLight.b
  wall.b
  liquid.b
  isLava.b
  u.w
  v.w
  wallu.w
  wallv.w
  light.d
  mysteryByte1.b
  mysteryByte2.b
EndStructure

Structure tileInfo
  name.s
  color.l
  hasExtra.b
  light.d
  transparent.b
EndStructure

;windows
#MainWindow = 1000

;menus
#FileMenu   = 2000
#FileOpen   = 2100
#FileSave   = 2101
#FileExit   = 2102

;gadgets
#ScrollArea = 3000
#ImageGadget= 3001

;xml tile data
Global Dim tileInfo.tileInfo(200)
Global loaded, img

Procedure Load()
  ;default terraria map directory
  filename$ = OpenFileRequester("Select a world file.", "%USERPROFILE%\My Documents\My Games\Terraria\Worlds\", "World File (*.wld)|*.wld", 0)
  mapFile = OpenFile(#PB_Any, filename$)

  ;close if did not find a file
  If Not mapFile
    ProcedureReturn
  EndIf

  ;reading map
  mapVersion.l    = ReadLong(mapFile)
  ReadData(mapFile, @mapTitle, ReadByte(mapFile))   ;read length-prefixed string
  FileSeek(mapFile, Loc(mapFile)+20)    ;skip id and bounds
  tilesHigh.l     = ReadLong(mapFile)
  tilesWide.l     = ReadLong(mapFile)
  spawnX.l        = ReadLong(mapFile)
  spawnY.l        = ReadLong(mapFile)
  groundLevel.l   = ReadDouble(mapFile)
  rockLevel.l     = ReadDouble(mapFile)
  FileSeek(mapFile, Loc(mapFile)+48)   ;skip flags and other settings
  Global Dim tiles.tile(tilesWide * tilesHigh)

  img = CreateImage(#PB_Any, tilesWide, tilesHigh)

  start = ElapsedMilliseconds()

  For i = 0 To tilesWide * tilesHigh
    tiles(i)\isActive = ReadByte(mapFile)
    If tiles(i)\isActive
      tiles(i)\type = ReadByte(mapFile)
      If tiles(i)\type > -1
        If tileInfo(tiles(i)\type)\hasExtra
          tiles(i)\u = ReadWord(mapFile)
          tiles(i)\v = ReadWord(mapFile)
        Else
          tiles(i)\u = -1
          tiles(i)\v = -1
        EndIf
      EndIf
    EndIf
    tiles(i)\hasLight = ReadByte(mapFile)
    tiles(i)\mysteryByte1 = ReadByte(mapFile)
    If tiles(i)\mysteryByte1
      tiles(i)\wall = ReadByte(mapFile)
      tiles(i)\wallu = -1
      tiles(i)\wallv = -1
    Else
      tiles(i)\wall = 0
    EndIf
    tiles(i)\mysteryByte2 = ReadByte(mapFile)
    If tiles(i)\mysteryByte2
      tiles(i)\liquid = ReadByte(mapFile)
      tiles(i)\isLava = ReadByte(mapFile)
    Else
      tiles(i)\liquid = 0
    EndIf
  Next
  
  CloseFile(mapFile)

  ;drawing
  i = 0
  StartDrawing(ImageOutput(img))
  For x = 0 To tilesWide - 1
    For y = 0 To tilesHigh- 1
      If tiles(i)\isActive
        Plot(x, y, RGB(Blue(tileInfo(tiles(i)\type)\color), Green(tileInfo(tiles(i)\type)\color), Red(tileInfo(tiles(i)\type)\color)))
      Else
        If y < groundLevel
          Plot(x, y,RGB(132, 170, 248))
        Else
          Plot(x, y,RGB(74, 67, 60))
        EndIf     
      EndIf
      i + 1
    Next
  Next
  StopDrawing()

  ;attach image to image gadget + set scroll area
  SetGadgetState(3001, ImageID(img))
  SetGadgetAttribute(#ScrollArea, #PB_ScrollArea_InnerWidth, tilesWide)
  SetGadgetAttribute(#ScrollArea, #PB_ScrollArea_InnerHeight, tilesHigh)
  loaded = #True
EndProcedure

;loading xml
If LoadXML(0, "tiles.xml")
  If XMLStatus(0) <> #PB_XML_Success
    MessageRequester("Error", "Cannot read xml file.")
  EndIf
  *MainNode = MainXMLNode(0)
  *CurrentNode = ChildXMLNode(*MainNode)
  While *CurrentNode <> 0
    tag.s = GetXMLNodeName(*CurrentNode)
    If tag = "tile"
      tileInfo(i)\name = GetXMLAttribute(*CurrentNode, "num")
      tileInfo(i)\color = Val("$"+Mid(GetXMLAttribute(*CurrentNode, "color"),2))
      tileInfo(i)\hasExtra = Val(GetXMLAttribute(*CurrentNode, "hasExtra"))
      If GetXMLAttribute(*CurrentNode, "light") <> ""
        tileInfo(i)\light = ValD(GetXMLAttribute(*CurrentNode, "light"))
      Else
        tileinfo(i)\light = 0.0
      EndIf
      tileinfo(i)\transparent = Val(GetXMLAttribute(*CurrentNode, "letLight"))
      i + 1
    EndIf
    *CurrentNode = NextXMLNode(*CurrentNode)
  Wend
Else
  MessageRequester("Missing Tiles", "Could not find tiles.xml")
  End
EndIf

OpenWindow(#MainWindow, 0, 0, 800, 600, "Epi's Terraria Map Viewer", #PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)

CreateMenu(#FileMenu, WindowID(#MainWindow))
MenuTitle("&File")
MenuItem(#FileOpen, "Open")
MenuItem(#FileSave, "Save")
MenuItem(#FileExit, "Exit")

ScrollAreaGadget(#ScrollArea, 0, 0, 400, 400, 50, 50)
ImageGadget(#ImageGadget, 0, 0, 400, 400, 0)
CloseGadgetList()

Repeat
  event = WaitWindowEvent(1)

  Select event
    Case #PB_Event_SizeWindow
      ResizeGadget(#ScrollArea, 0, 0, WindowWidth(#MainWindow), WindowHeight(#MainWindow)-20)
     
    Case #PB_Event_Menu
      menu = EventMenu()
      If menu = #FileOpen
        Load()
      EndIf
     
      If menu = #FileSave
        If loaded
          fileName$ = SaveFileRequester("save?", "", "Ye Olde Bitmap (*.bmp)|*.bmp", 0)
          If GetExtensionPart(fileName$) = ""
            fileName$ + ".bmp"
          EndIf
          SaveImage(img, fileName$)
        EndIf
      EndIf
     
      If menu = #FileExit
        result = MessageRequester("Quit?", "Are you sure?", #PB_MessageRequester_YesNo)
        If result = #PB_MessageRequester_Yes
          End
        EndIf
      EndIf
  EndSelect
Until event = #PB_Event_CloseWindow
Last edited by epidemicz on Tue Jul 12, 2011 2:04 am, edited 2 times in total.
Image
User avatar
OldSkoolGamer
Enthusiast
Enthusiast
Posts: 150
Joined: Mon Dec 15, 2008 11:15 pm
Location: Nashville, TN
Contact:

Re: Terraria Map Viewer

Post by OldSkoolGamer »

Nice,

Simple & short code, thanks for sharing :D
citystate
Enthusiast
Enthusiast
Posts: 638
Joined: Sun Feb 12, 2006 10:06 pm

Re: Terraria Map Viewer

Post by citystate »

works well - a very helpful tool.

only one issue I encountered - it doesn't close the world file once it's finished with it; this blocks the game from accessing it. I suggest inserting CloseFile(mapFile) at the end of the Load() procedure.

Also, you can probably get some speed increase by changing the Hex2Dec procedure - the tiles.xml stores its color values as '#rrggbb' where the rrggbb is a hex value - try replacing your function with Val("$"+mid(hex,2))
there is no sig, only zuul (and the following disclaimer)

WARNING: may be talking out of his hat
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Re: Terraria Map Viewer

Post by epidemicz »

citystate wrote:works well - a very helpful tool.

only one issue I encountered - it doesn't close the world file once it's finished with it; this blocks the game from accessing it. I suggest inserting CloseFile(mapFile) at the end of the Load() procedure.

Also, you can probably get some speed increase by changing the Hex2Dec procedure - the tiles.xml stores its color values as '#rrggbb' where the rrggbb is a hex value - try replacing your function with Val("$"+mid(hex,2))
Thanks :) and nice catch. I updated the original post to add these things in.
Image
Post Reply