Skip to content

Commit

Permalink
Initialize
Browse files Browse the repository at this point in the history
  • Loading branch information
edwinsyarief committed Feb 4, 2025
0 parents commit 856b166
Show file tree
Hide file tree
Showing 6 changed files with 415 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Build and Test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.23.4'

- name: Build
run: go build -v ./...

- name: Test
run: go test -v ./...

- name: Vet
run: go vet ./...

- name: Lint
uses: golangci/golangci-lint-action@v3
with:
version: latest
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Asset Packer

## Overview

Asset Packer is a powerful tool designed to streamline the packaging and management of game assets. It provides a seamless workflow for developers, ensuring that assets are efficiently packed and ready for use in the game.

## Installation

`go get github.com/edwinsyarief/asset-packer`

### Secure Asset Pipeline

- **Encrypted Assets**: All game assets (images, audio, maps) are encrypted using AES-GCM encryption
- **Compression**: Assets are automatically compressed using gzip before encryption
- **Streamlined Loading**: Fast asset loading with built-in decompression and decryption

### Asset Types Support

- Sprites and animations
- Audio files (BGM, SFX)
- Map data and configurations
- UI elements and fonts

### Security Features

- AES-GCM authenticated encryption
- Secure random nonce generation
- Key rotation support
- Protected asset integrity

This system ensures your game assets are protected while maintaining excellent performance and developer experience.

## Quick Start Example

Here's a simple example of packing game assets:

```go
package main

import (
"fmt"
"github.com/edwinsyarief/assetpacker"
)

func main() {
// Define your game assets
assets := []assetpacker.Asset{
{Path: "assets/sprites/player.png", Type: "sprite"},
{Path: "assets/audio/background.mp3", Type: "audio"},
{Path: "assets/maps/level1.json", Type: "map"},
}

// Your secret key (32 bytes)
key := []byte("your-secret-key-32-bytes-required!")

// Pack assets into a single encrypted file
err := assetpacker.PackAssets(assets, "game_assets.pak", key)
if err != nil {
fmt.Printf("Failed to pack assets: %v\n", err)
return
}

// Later, in your game code:
reader, err := assetpacker.NewAssetReader("game_assets.pak", key)
if err != nil {
fmt.Printf("Failed to read assets: %v\n", err)
return
}

fmt.Println("Assets packed and ready for your game!")
}
22 changes: 22 additions & 0 deletions asset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package assetpacker

import (
"fmt"
"os"
)

// Asset defines an asset with its type and content.
type Asset struct {
Path string
Type string
Content []byte
}

func openFile(path string) ([]byte, error) {
content, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("error reading %s: %v", path, err)
}

return content, nil
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/edwinsyarief/assetpacker

go 1.23.4
79 changes: 79 additions & 0 deletions packer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package assetpacker

import (
"bytes"
"compress/gzip"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
"os"
)

// packAssets compresses, encrypts, and writes assets to a binary file.
func PackAssets(assets []Asset, outputPath string, key []byte) error {
// Use AES for encryption
block, err := aes.NewCipher(key)
if err != nil {
return err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return err
}

// Write to file
file, err := os.Create(outputPath)
if err != nil {
return err
}
defer file.Close()

// Write each asset
for _, asset := range assets {
asset.Content, err = openFile(asset.Path)
if err != nil {
return err
}

compressed, err := compressAsset(asset.Content)
if err != nil {
return err
}

nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return err
}

encrypted := gcm.Seal(nonce, nonce, compressed, nil)

// Debug - Print what's being written
fmt.Printf("Writing metadata for %s: %s:%s:%d:\n", asset.Path, asset.Path, asset.Type, len(encrypted))

// Write asset metadata followed by encrypted content
_, err = file.WriteString(fmt.Sprintf("%s:%s:%d:", asset.Path, asset.Type, len(encrypted)))
if err != nil {
return err
}
_, err = file.Write(encrypted)
if err != nil {
return err
}
}
return nil
}

// compressAsset uses gzip to compress the asset data.
func compressAsset(data []byte) ([]byte, error) {
var b bytes.Buffer
gz := gzip.NewWriter(&b)
if _, err := gz.Write(data); err != nil {
return nil, err
}
if err := gz.Close(); err != nil {
return nil, err
}
return b.Bytes(), nil
}
Loading

0 comments on commit 856b166

Please sign in to comment.