bsp

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 28, 2023 License: Unlicense Imports: 11 Imported by: 18

README

GoDoc Go report card GolangCI Build Status CircleCI codecov

Bsp

Go library for handling Source Engine .bsp map files.

Features:
  • Read support for (most) non-xbox360 BSPs (v20,21). v19 support limited, may work
  • Freely modify and resize any Lump data
  • Limited write support, mostly untested
Not all lumps are currently supported, but can be freely read and modified, as they are treated as []byte

The following lumps currently have a full implementation for v20 & v21 BSPs (tested against CS:S & CS:GO):

0: Entdata
1: Planes
2: Texdata
3: Vertexes
4: Visibility
5: Nodes
6: Texinfo
7: Faces
8: Lighting
9: Occlusion
10: Leafs
11: FaceId
12: Edges
13: Surfedges
14: Models
15: WorldLight
16: Leaffaces
17: LeafBrushes
18: Brushes
19: Brushsides
20: Areas
21: AreaPortals
26: DispInfo
27: OriginalFaces
28: PhysDisp
30: VertNormals
31: VertNormalIndices
33: DispVerts
34: DispLightmapSamplePosition
35: Game lump (partial: sprp only)
36: LeafWaterData
37: Primitives
38: PrimVerts
39: PrimIndices
40: Pakfile
41: ClipPortalVerts
42: Cubemaps
43: Texdatastringdata
44: Texdatastringtable
45: Overlays
46: LeafMinDistToWater
47: FaceMacroTextureInfo
48: DispTris
51: LeafAmbientIndexHDR
52: LeafAmbientIndex
53: WorldLightHDR
54: WorldLightHDR
55: LeafAmbientLightingHDR
56: LeafAmbientLighting
58: FacesHDR
59: MapFlags
60: OverlayFades
This library may reorganise lump order during the first export. This is intentional to handle lump resizing, but will change your checksum if you export without changes.

Usage

Minimal example of obtaining entdata from a BSP. The following will print the entdata lump (entdata is a single json-like string) of a specified .bsp to console.

package main

import (
	"github.com/galaco/bsp"
	"github.com/galaco/bsp/lumps"
	"log"
	"os"
)

func main() {
	f,_ := os.Open("de_dust2.bsp")

	// Create a new bsp reader
	reader := bsp.NewReader(f)
	
	// Read buffer
	file,err := reader.Read()
	if err != nil {
		log.Fatal(err)
	}
	f.Close()
    
	lump := file.Lump(bsp.LumpEntities).(*lumps.Entities)
	log.Println(lump.GetData())
}

Real World examples

Contributing

All contributions welcome. Known unsupported games/maps are especially useful.

Documentation

Index

Constants

View Source
const (
	CONTENTS_EMPTY = 0 // No contents

	CONTENTS_SOLID        = 0x1 // an eye is never valid in a solid
	CONTENTS_WINDOW       = 0x2 // translucent, but not watery (glass)
	CONTENTS_AUX          = 0x4
	CONTENTS_GRATE        = 0x8 // alpha-tested "grate" textures.  Bullets/sight pass through, but solids don't
	CONTENTS_SLIME        = 0x10
	CONTENTS_WATER        = 0x20
	CONTENTS_BLOCKLOS     = 0x40 // block AI line of sight
	CONTENTS_OPAQUE       = 0x80 // things that cannot be seen through (may be non-solid though)
	LAST_VISIBLE_CONTENTS = 0x80

	ALL_VISIBLE_CONTENTS = LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS - 1)

	CONTENTS_TESTFOGVOLUME = 0x100
	CONTENTS_UNUSED        = 0x200

	// unused
	// NOTE: If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS
	// if not visible, then grab from the bottom.
	CONTENTS_UNUSED6 = 0x400

	CONTENTS_TEAM1 = 0x800  // per team contents used to differentiate collisions
	CONTENTS_TEAM2 = 0x1000 // between players and objects on different teams

	// ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW
	CONTENTS_IGNORE_NODRAW_OPAQUE = 0x2000

	// hits entities which are MOVETYPE_PUSH (doors, plats, etc.)
	CONTENTS_MOVEABLE = 0x4000

	// remaining contents are non-visible, and don't eat brushes
	CONTENTS_AREAPORTAL = 0x8000

	CONTENTS_PLAYERCLIP  = 0x10000
	CONTENTS_MONSTERCLIP = 0x20000

	// currents can be added to any other contents, and may be mixed
	CONTENTS_CURRENT_0    = 0x40000
	CONTENTS_CURRENT_90   = 0x80000
	CONTENTS_CURRENT_180  = 0x100000
	CONTENTS_CURRENT_270  = 0x200000
	CONTENTS_CURRENT_UP   = 0x400000
	CONTENTS_CURRENT_DOWN = 0x800000

	CONTENTS_ORIGIN = 0x1000000 // removed before bsping an entity

	CONTENTS_MONSTER     = 0x2000000 // should never be on a brush, only in game
	CONTENTS_DEBRIS      = 0x4000000
	CONTENTS_DETAIL      = 0x8000000  // brushes to be added after vis leafs
	CONTENTS_TRANSLUCENT = 0x10000000 // auto set if any surface has trans
	CONTENTS_LADDER      = 0x20000000
	CONTENTS_HITBOX      = 0x40000000 // use accurate hitboxes on trace

	// NOTE: These are stored in a short in the engine now.  Don't use more than 16 bits
	SURF_LIGHT    = 0x0001 // value will hold the light strength
	SURF_SKY2D    = 0x0002 // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox
	SURF_SKY      = 0x0004 // don't draw, but add to skybox
	SURF_WARP     = 0x0008 // turbulent water warp
	SURF_TRANS    = 0x0010
	SURF_NOPORTAL = 0x0020 // the surface can not have a portal placed on it
	SURF_TRIGGER  = 0x0040 // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders
	SURF_NODRAW   = 0x0080 // don't bother referencing the texture

	SURF_HINT = 0x0100 // make a primary bsp splitter

	SURF_SKIP      = 0x0200 // completely ignore, allowing non-closed brushes
	SURF_NOLIGHT   = 0x0400 // Don't calculate light
	SURF_BUMPLIGHT = 0x0800 // calculate three lightmaps for the surface for bumpmapping
	SURF_NOSHADOWS = 0x1000 // Don't receive shadows
	SURF_NODECALS  = 0x2000 // Don't receive decals
	SURF_NOCHOP    = 0x4000 // Don't subdivide patches on this surface
	SURF_HITBOX    = 0x8000 // surface is part of a hitbox

	// -----------------------------------------------------
	// spatial content masks - used for spatial queries (traceline,etc.)
	// -----------------------------------------------------
	MASK_ALL = (0xFFFFFFFF)

	// everything that is normally solid
	MASK_SOLID = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_GRATE)

	// everything that blocks player movement
	MASK_PLAYERSOLID = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_GRATE)

	// blocks npc movement
	MASK_NPCSOLID = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_MONSTERCLIP | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_GRATE)

	// water physics in these contents
	MASK_WATER = (CONTENTS_WATER | CONTENTS_MOVEABLE | CONTENTS_SLIME)

	// everything that blocks lighting
	MASK_OPAQUE = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_OPAQUE)

	// everything that blocks lighting, but with monsters added.
	MASK_OPAQUE_AND_NPCS = (MASK_OPAQUE | CONTENTS_MONSTER)

	// everything that blocks line of sight for AI
	MASK_BLOCKLOS = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_BLOCKLOS)

	// everything that blocks line of sight for AI plus NPCs
	MASK_BLOCKLOS_AND_NPCS = (MASK_BLOCKLOS | CONTENTS_MONSTER)

	// everything that blocks line of sight for players
	MASK_VISIBLE = (MASK_OPAQUE | CONTENTS_IGNORE_NODRAW_OPAQUE)

	// everything that blocks line of sight for players, but with monsters added.
	MASK_VISIBLE_AND_NPCS = (MASK_OPAQUE_AND_NPCS | CONTENTS_IGNORE_NODRAW_OPAQUE)

	// bullets see these as solid
	MASK_SHOT = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_MONSTER | CONTENTS_WINDOW | CONTENTS_DEBRIS | CONTENTS_HITBOX)

	// non-raycasted weapons see this as solid (includes grates)
	MASK_SHOT_HULL = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_MONSTER | CONTENTS_WINDOW | CONTENTS_DEBRIS | CONTENTS_GRATE)

	// hits solids (not grates) and passes through everything else
	MASK_SHOT_PORTAL = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_MONSTER)

	// everything normally solid, except monsters (world+brush only)
	MASK_SOLID_BRUSHONLY = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_GRATE)

	// everything normally solid for player movement, except monsters (world+brush only)
	MASK_PLAYERSOLID_BRUSHONLY = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_PLAYERCLIP | CONTENTS_GRATE)

	// everything normally solid for npc movement, except monsters (world+brush only)
	MASK_NPCSOLID_BRUSHONLY = (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_MONSTERCLIP | CONTENTS_GRATE)

	// just the world, used for route rebuilding
	MASK_NPCWORLDSTATIC = (CONTENTS_SOLID | CONTENTS_WINDOW | CONTENTS_MONSTERCLIP | CONTENTS_GRATE)

	// These are things that can split areaportals
	MASK_SPLITAREAPORTAL = (CONTENTS_WATER | CONTENTS_SLIME)

	// UNDONE: This is untested, any moving water
	MASK_CURRENT = (CONTENTS_CURRENT_0 | CONTENTS_CURRENT_90 | CONTENTS_CURRENT_180 | CONTENTS_CURRENT_270 | CONTENTS_CURRENT_UP | CONTENTS_CURRENT_DOWN)

	// everything that blocks corpse movement
	// UNDONE: Not used yet / may be deleted
	MASK_DEADSOLID = (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_GRATE)
)
View Source
const (
	// LumpEntities is Entity keyvalue data stored as string
	LumpEntities = LumpId(0)
	// LumpPlanes is bsp planes
	LumpPlanes = LumpId(1)
	// LumpTexData is texture data used by bsp faces
	LumpTexData = LumpId(2)
	// LumpVertexes is vertex data
	LumpVertexes = LumpId(3)
	// LumpVisibility is vvis calculated visibility pvs & pas information
	LumpVisibility = LumpId(4)
	// LumpNodes is bsp node tree entries
	LumpNodes = LumpId(5)
	// LumpTexInfo is face texture information
	LumpTexInfo = LumpId(6)
	// LumpFaces is  bsp faces
	LumpFaces = LumpId(7)
	// LumpLighting
	LumpLighting = LumpId(8)
	// LumpOcclusion
	LumpOcclusion = LumpId(9)
	// LumpLeafs
	LumpLeafs = LumpId(10)
	// LumpFaceIds is contents is normally stripped out by compiler
	LumpFaceIds = LumpId(11)
	// LumpEdges is face edges. v1->v2, vertex order may be reversed
	LumpEdges = LumpId(12)
	// LumpSurfEdges
	LumpSurfEdges = LumpId(13)
	// LumpModels is models are root bsp nodes. m[0] = worldspawn. m[0+n] are brush entity data
	LumpModels = LumpId(14)
	// LumpWorldLights
	LumpWorldLights = LumpId(15)
	// LumpLeafFaces is faces that separate leaves.
	LumpLeafFaces = LumpId(16)
	// LumpLeafBrushes is brushes that define a leaf volume
	LumpLeafBrushes = LumpId(17)
	// LumpBrushes
	LumpBrushes = LumpId(18)
	// LumpBrushSides
	LumpBrushSides = LumpId(19)
	// LumpAreas
	LumpAreas = LumpId(20)
	// LumpAreaPortals
	LumpAreaPortals = LumpId(21)
	// LumpPortals
	LumpPortals = LumpId(22)
	// LumpUnused0
	LumpUnused0 = LumpId(22)
	// LumpPropCollision
	LumpPropCollision = LumpId(22)
	// LumpClusters
	LumpClusters = LumpId(23)
	// LumpUnused1
	LumpUnused1 = LumpId(23)
	// LumpPropHulls
	LumpPropHulls = LumpId(23)
	// LumpPortalVerts
	LumpPortalVerts = LumpId(24)
	// LumpUnused2
	LumpUnused2 = LumpId(24)
	// LumpPropHullVerts
	LumpPropHullVerts = LumpId(24)
	// LumpClusterPortals
	LumpClusterPortals = LumpId(25)
	// LumpUnused3
	LumpUnused3 = LumpId(25)
	// LumpPropTris
	LumpPropTris = LumpId(25)
	// LumpDispInfo
	LumpDispInfo = LumpId(26)
	// LumpOriginalFaces
	LumpOriginalFaces = LumpId(27)
	// LumpPhysDisp
	LumpPhysDisp = LumpId(28)
	// LumpPhysCollide
	LumpPhysCollide = LumpId(29)
	// LumpVertNormals
	LumpVertNormals = LumpId(30)
	// LumpVertNormalIndices
	LumpVertNormalIndices = LumpId(31)
	// LumpDispLightmapAlphas is contents is normally stripped out
	LumpDispLightmapAlphas = LumpId(32)
	// LumpDispVerts
	LumpDispVerts = LumpId(33)
	// LumpDispLightmapSamplePositions
	LumpDispLightmapSamplePositions = LumpId(34)
	// LumpGame is game specific data. includes staticprop data
	LumpGame = LumpId(35)
	// LumpLeafWaterData
	LumpLeafWaterData = LumpId(36)
	// LumpPrimitives
	LumpPrimitives = LumpId(37)
	// LumpPrimVerts
	LumpPrimVerts = LumpId(38)
	// LumpPrimIndices
	LumpPrimIndices = LumpId(39)
	// LumpPakfile is uncompressed zip of packed custom content
	LumpPakfile = LumpId(40)
	// LumpClipPortalVerts
	LumpClipPortalVerts = LumpId(41)
	// LumpCubemaps
	LumpCubemaps = LumpId(42)
	// LumpTexDataStringData is raw string data of material paths
	LumpTexDataStringData = LumpId(43)
	// LumpTexDataStringTable references entries in the string data lump
	LumpTexDataStringTable = LumpId(44)
	// LumpOverlays
	LumpOverlays = LumpId(45)
	// LumpLeafMinDistToWater
	LumpLeafMinDistToWater = LumpId(46)
	// LumpFaceMacroTextureInfo
	LumpFaceMacroTextureInfo = LumpId(47)
	// LumpDispTris
	LumpDispTris = LumpId(48)
	// LumpPhysCollideSurface is deprecated
	LumpPhysCollideSurface = LumpId(49)
	// LumpPropBlob
	LumpPropBlob = LumpId(49)
	// LumpWaterOverlays
	LumpWaterOverlays = LumpId(50)
	// LumpLightmapPages
	LumpLightmapPages = LumpId(51)
	// LumpLeafAmbientIndexHDR
	LumpLeafAmbientIndexHDR = LumpId(51)
	// LumpLightmapPagesInfo
	LumpLightmapPagesInfo = LumpId(52)
	// LumpLeafAmbientIndex
	LumpLeafAmbientIndex = LumpId(52)
	// LumpLightingHDR
	LumpLightingHDR = LumpId(53)
	// LumpWorldLightsHDR
	LumpWorldLightsHDR = LumpId(54)
	// LumpLeafAmbientLightingHDR
	LumpLeafAmbientLightingHDR = LumpId(55)
	// LumpLeafAmbientLighting
	LumpLeafAmbientLighting = LumpId(56)
	// LumpXZipPakfile is deprecated, and xbox specific
	LumpXZipPakfile = LumpId(57)
	// LumpFacesHDR
	LumpFacesHDR = LumpId(58)
	// LumpMapFlags
	LumpMapFlags = LumpId(59)
	// LumpOverlayFades
	LumpOverlayFades = LumpId(60)
	// LumpOverlaySystemLevels
	LumpOverlaySystemLevels = LumpId(61)
	// LumpPhysLevel
	LumpPhysLevel = LumpId(62)
	// LumpDispMultiBlend
	LumpDispMultiBlend = LumpId(63)
)

Lump Identifiers

Variables

This section is empty.

Functions

This section is empty.

Types

type Bsp

type Bsp struct {
	// contains filtered or unexported fields
}

Bsp is the root .bsp filetype container. Consists of a 1036byte header and 64 lump blocks.

func ReadFromFile

func ReadFromFile(filepath string) (*Bsp, error)

ReadFromFile Wraps ReadFromStream to control the file access as well. Use ReadFromStream if you already have a file handle

func ReadFromStream

func ReadFromStream(reader io.Reader) (*Bsp, error)

ReadFromStream Reads from any struct that implements io.Reader handy for passing in a string/bytes/other stream

func (*Bsp) CRC32 added in v0.3.0

func (bsp *Bsp) CRC32() (uint32, error)

func (*Bsp) Header added in v0.2.0

func (bsp *Bsp) Header() *Header

Header gets the header for a bsp.

func (*Bsp) Lump added in v0.2.0

func (bsp *Bsp) Lump(index LumpId) lumps.ILump

Lump gets the lump for a given id.

func (*Bsp) RawLump added in v0.2.0

func (bsp *Bsp) RawLump(index LumpId) *Lump

RawLump gets the lump for a given id.

func (*Bsp) SetLump

func (bsp *Bsp) SetLump(index LumpId, lump Lump)

SetLump sets the lump data for a given id.

type Header struct {
	Id       int32
	Version  int32
	Lumps    [64]HeaderLump
	Revision int32
}

Header is the Bsp header. Contains format and lump layout data. Do not trust lump information between import and export

type HeaderLump

type HeaderLump struct {
	Offset  int32
	Length  int32
	Version int32
	Id      [4]byte
}

HeaderLump contains layout information for a given lump, stored in the Header.

type Lump

type Lump struct {
	// contains filtered or unexported fields
}

Lump is a container for a lump. Also includes metadata about the lump. N.B. Some information mirrors the header's lump descriptor, but header information should not be trusted after import completion.

func (*Lump) Contents added in v0.2.0

func (l *Lump) Contents() lumps.ILump

Contents Get the contents of a lump. NOTE: Will need to be cast to the relevant lumps

func (*Lump) Length added in v0.2.0

func (l *Lump) Length() int32

Length Get length of a lump in bytes.

func (*Lump) RawContents added in v0.2.0

func (l *Lump) RawContents() []byte

RawContents Get the raw []byte contents of a lump. N.B. This is the raw imported value. To get the raw value of a modified lump, use Contents().Marshall()

func (*Lump) SetContents

func (l *Lump) SetContents(data lumps.ILump)

SetContents Set content type of a lump.

func (*Lump) SetId

func (l *Lump) SetId(index LumpId)

SetId sets lump identifier Id is the lump type id (not the id for the order the lumps are stored)

func (*Lump) SetRawContents

func (l *Lump) SetRawContents(raw []byte)

SetRawContents Set raw []byte contents of a lump.

type LumpId added in v0.2.0

type LumpId int

LumpId is the lump reference used by Source

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader is a Bsp File reader.

func (*Reader) Read

func (r *Reader) Read() (bsp *Bsp, err error)

Read reads the BSP into internal byte structure Note that parsing is somewhat lazy. Proper data structures are only generated for lumps that are requested at a later time. This generated the header, then []byte data for each lump

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer is a Bsp export writer.

func NewWriter

func NewWriter() Writer

NewWriter Returns a new bsp writer instance.

func (*Writer) GetBsp

func (w *Writer) GetBsp() Bsp

GetBsp Gets bsp file to write.

func (*Writer) SetBsp

func (w *Writer) SetBsp(file Bsp)

SetBsp Sets bsp file to write.

func (*Writer) Write

func (w *Writer) Write() ([]byte, error)

Write bsp to []byte.

func (*Writer) WriteLump

func (w *Writer) WriteLump(index LumpId) ([]byte, error)

WriteLump Exports a single lump to []byte.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL