Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for custom blocks #512

Merged
merged 88 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
2fa6415
Start of custom blocks.. yeah
TwistedAsylumMC Apr 3, 2022
a0466b6
Merge branch 'master' into feature/custom-blocks
TwistedAsylumMC May 15, 2022
dfeca65
packbuilder/blocks.go: Fix package name
TwistedAsylumMC May 15, 2022
b0b0a4a
world/block_state.go: horrible horrible horrible sorting code.
JustTalDevelops May 21, 2022
fca2e6a
world/block_state.go: woops
JustTalDevelops May 21, 2022
a01a1ba
world/block_state.go: Properly register existing states.
JustTalDevelops May 21, 2022
4e8a57d
world/block_state.go: Possibly simplify code.
JustTalDevelops May 21, 2022
8a06a04
world/block_state.go: Don't sort unnecessarily.
JustTalDevelops May 21, 2022
8b7e40f
world/block_state.go: Various fixes.
JustTalDevelops May 21, 2022
8c74e52
block: Added a PHP custom block for testing.
JustTalDevelops May 21, 2022
5222de9
world/block_state.go: Update hashes.
JustTalDevelops May 21, 2022
051c5bb
block/hash.go: Added a NextHash function.
JustTalDevelops May 22, 2022
d90fb7e
customblock: Various material target changes.
JustTalDevelops May 22, 2022
2ee89b3
world/block.go: Improve doc.
JustTalDevelops May 22, 2022
2a4c4b6
customblock/server.go: Properly handle no geometry.
JustTalDevelops May 22, 2022
ca04af0
customblock/material_target.go: Added a Name function.
JustTalDevelops May 22, 2022
c4ea4be
Merge branch 'master' into feature/custom-blocks
JustTalDevelops May 22, 2022
4ea1ef8
block/hash.go: Various fixes.
JustTalDevelops May 22, 2022
5f82b33
server/server.go: Added some basic components. (WIP)
JustTalDevelops May 22, 2022
0dc36c5
customblock/render_method.go: Simplify AmbientOcclusion.
JustTalDevelops May 22, 2022
7d44493
customblock/render_method.go: Fix doc.
JustTalDevelops May 22, 2022
fed0155
customblock/model.go: Use MaterialTarget.
JustTalDevelops May 22, 2022
58d8b64
Merge remote-tracking branch 'origin/feature/custom-blocks' into feat…
JustTalDevelops May 22, 2022
7027e3f
customblock/render_method.go: consistency!!11
JustTalDevelops May 22, 2022
ed227b4
customblock/model.go: woops.
JustTalDevelops May 22, 2022
94f0edf
server/server.go: consistency v2
JustTalDevelops May 22, 2022
19f2562
world/block_state.go: Various improvements.
JustTalDevelops May 22, 2022
c541855
world/block_state.go: Remove debug.
JustTalDevelops May 22, 2022
9e82cab
world/block_state.go: Woops.
JustTalDevelops May 22, 2022
d2f9ebd
world/block_state.go: Update airRID.
JustTalDevelops May 22, 2022
7419a89
server/server.go: Actually use components.
JustTalDevelops May 22, 2022
502fac7
server/server.go: Component fixes.
JustTalDevelops May 22, 2022
cd61a67
world/block_state.go: Cleaned up a ton of code.
JustTalDevelops May 22, 2022
f158efe
block/php.go: Removed changes.
JustTalDevelops May 22, 2022
52ccfa5
main.go: Fix creative item count.
JustTalDevelops May 22, 2022
0cd2b2e
world/block_state.go: Various changes.
JustTalDevelops May 23, 2022
6847587
server/server.go: Fix the LightEmitter component.
JustTalDevelops May 23, 2022
fb56c62
server/server.go: Fix creative items not properly functioning + light…
JustTalDevelops May 23, 2022
9c2bc3f
server/server.go: Support properties for custom blocks.
JustTalDevelops May 23, 2022
f997312
world/block.go: Fixesss
JustTalDevelops May 23, 2022
5341d42
packbuilder/blocks.go: Use Sprintf for consistency.
JustTalDevelops May 23, 2022
14e2f57
blockinternal: Moved component building.
JustTalDevelops May 24, 2022
4fc2be4
fixed client crashes caused by empty block entry
DaPigGuy May 24, 2022
3436f2e
server/server.go: Made an itemComponentEntries function for consistency.
JustTalDevelops May 24, 2022
6452534
blockinternal/blocks.go: Permutations?
JustTalDevelops May 24, 2022
ed0d697
block/php.go: woops.
JustTalDevelops May 24, 2022
9025740
blockinternal/builder.go: Set Molang version.
JustTalDevelops May 24, 2022
b5f3994
blockinternal/builder.go: Update Empty check.
JustTalDevelops May 24, 2022
b71c60b
blockinternal/builder.go: Remove useless Empty.
JustTalDevelops May 24, 2022
c02ffe9
blockinternal/builder.go: Remove useless Values.
JustTalDevelops May 24, 2022
d0c2f68
world/block.go: Allow custom blocks to opt into custom geometry.
JustTalDevelops May 24, 2022
10efae1
blockinternal/components.go: More of permutations.
JustTalDevelops May 25, 2022
40a61a7
blockinternal/components.go: Docs.
JustTalDevelops May 25, 2022
77dad5f
block/pig.go: Changes.
JustTalDevelops May 25, 2022
7954a8a
block/pig.go: Made Pig flammable.
JustTalDevelops May 25, 2022
ae0f82d
block/pig.go: Changes to permutation API.
JustTalDevelops May 26, 2022
43b4f50
block/block.go: Removed Placeable.
JustTalDevelops May 26, 2022
bfef090
block/material_target.go: Added missing material targets.
JustTalDevelops May 26, 2022
fa457da
block/pig.go: Start implementing new permutation system.
JustTalDevelops May 26, 2022
5de1093
blockinternal/components.go: More changes.
JustTalDevelops May 26, 2022
4ceb8c4
blockinternal/components.go: Support for other permutable components.
JustTalDevelops May 27, 2022
5ef03d6
block/pig.go: Various changes.
JustTalDevelops May 27, 2022
11e9225
blockinternal/builder.go: Set aim and block collision boxes.
JustTalDevelops May 27, 2022
7e5eb82
blockinternal/builder.go: Various changes.
JustTalDevelops May 27, 2022
1c29cdc
Merge branch 'master' into feature/custom-blocks
JustTalDevelops Jul 22, 2022
112cf1c
dragonfly: Various fixes to custom blocks.
JustTalDevelops Jul 22, 2022
195a269
world/block_state.go: Use fast hash.
JustTalDevelops Jul 22, 2022
ba461ea
customblock: Some work on permutation specific textures + cleanup.
JustTalDevelops Jul 22, 2022
ceed0c5
customblock: Permutation-specific geometry.
JustTalDevelops Jul 22, 2022
62f9c8b
blockinternal/builder.go: Removed pointless nil checks.
JustTalDevelops Jul 22, 2022
7d12471
world/block_state.go: Remove pointless else if.
JustTalDevelops Jul 23, 2022
ac22916
customblock/geometry.go: Made UV `any` because the idiots at Mojang d…
JustTalDevelops Jul 25, 2022
b191b9e
customblock/geometry.go: Abs the cube sizes
TwistedAsylumMC Jul 25, 2022
f4b1855
server/server.go: Lazy init block and item components
TwistedAsylumMC Jul 26, 2022
efaf160
blockinternal/builder.go: Don't write multiple traits.
JustTalDevelops Jul 26, 2022
3494f10
blockinternal/builder.go: Maintain registration order.
JustTalDevelops Jul 26, 2022
786ba66
Update server/internal/blockinternal/components.go
JustTalDevelops Aug 11, 2022
e313001
Update server/world/block_state.go
JustTalDevelops Aug 11, 2022
d1e48b8
updated contributor list
JustTalDevelops Aug 11, 2022
cbdfa9b
dragonfly: Merge master into feature/custom-blocks
TwistedAsylumMC Nov 2, 2023
273b125
dragonfly: Finish custom block implementation
TwistedAsylumMC Nov 3, 2023
9ec048c
dragonfly: Cleanup custom block code
TwistedAsylumMC Nov 3, 2023
21e8df6
sliceutil/sliceutil.go: Remove Insert() in favour of slices package
TwistedAsylumMC Nov 5, 2023
884aaa5
dragonfly: Use Go 1.21 and use std slices package
TwistedAsylumMC Nov 5, 2023
7e8918c
.github/workflows: Use Go 1.21
TwistedAsylumMC Nov 5, 2023
945d56d
block/hash.go: Remove dropper hash
TwistedAsylumMC Nov 5, 2023
17073c1
leveldat/data.go: Add naturalgeneration field
TwistedAsylumMC Nov 17, 2023
79f1c57
Merge branch 'master' into feature/custom-blocks
TwistedAsylumMC Dec 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions cmd/blockhash/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ func procPackage(pkg *ast.Package, fs *token.FileSet, w io.Writer) {

b.writePackage(w)
i := b.writeConstants(w)
b.writeNextHash(w)
b.writeMethods(w, i)
}

var (
packageFormat = "// Code generated by cmd/blockhash; DO NOT EDIT.\n\npackage %v\n\n"
methodFormat = "\nfunc (%v%v) Hash() uint64 {\n\treturn %v\n}\n"
methodFormat = "\n// Hash ...\nfunc (%v%v) Hash() uint64 {\n\treturn %v\n}\n"
constFormat = "\thash%v"
)

Expand Down Expand Up @@ -112,13 +113,28 @@ func (b *hashBuilder) writeConstants(w io.Writer) (bitSize int) {
i++
}

if _, err := fmt.Fprintln(w, ")"); err != nil {
if _, err := fmt.Fprintln(w, "\thashBase\n)"); err != nil {
log.Fatalln(err)
}

return bits.Len64(i)
}

func (b *hashBuilder) writeNextHash(w io.Writer) {
if _, err := fmt.Fprintln(w, "\n// base represents the base hash for all custom blocks."); err != nil {
log.Fatalln(err)
}
if _, err := fmt.Fprintln(w, "var base = uint64(hashBase - 1)"); err != nil {
log.Fatalln(err)
}
if _, err := fmt.Fprintln(w, "\n// NextHash returns the next free hash for custom blocks."); err != nil {
log.Fatalln(err)
}
if _, err := fmt.Fprintln(w, "func NextHash() uint64 {\n\tbase++\n\treturn base\n}"); err != nil {
log.Fatalln(err)
}
}

func (b *hashBuilder) writeMethods(w io.Writer, baseBits int) {
for _, name := range b.names {
fields := b.blockFields[name]
Expand Down
13 changes: 12 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ package main
import (
"fmt"
"github.com/df-mc/dragonfly/server"
"github.com/df-mc/dragonfly/server/block"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/item/creative"
"github.com/df-mc/dragonfly/server/player"
"github.com/df-mc/dragonfly/server/player/chat"
"github.com/df-mc/dragonfly/server/world"
"github.com/pelletier/go-toml"
"github.com/sirupsen/logrus"
"io/ioutil"
Expand All @@ -22,13 +27,19 @@ func main() {
log.Fatalln(err)
}

world.RegisterBlock(block.PHP{})
world.RegisterItem(block.PHP{})
creative.RegisterItem(item.NewStack(block.PHP{}, 64))

srv := server.New(&config, log)
srv.CloseOnProgramEnd()
if err := srv.Start(); err != nil {
log.Fatalln(err)
}

for srv.Accept(nil) {
for srv.Accept(func(p *player.Player) {
p.Inventory().AddItem(item.NewStack(block.PHP{}, 32))
}) {
}
}

Expand Down
47 changes: 47 additions & 0 deletions php.geo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.php.cube",
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 2,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [
0,
0.75,
0
]
},
"bones": [
{
"name": "bb_main",
"pivot": [
0,
0,
0
],
"cubes": [
{
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
16
],
"uv": [
0,
0
]
}
]
}
]
}
]
}
Binary file added php.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions server/block/customblock/geometry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package customblock

import (
"github.com/go-gl/mathgl/mgl64"
"math"
)

// Geometries represents the JSON structure of a vanilla geometry file. It contains a format version and a slice of
// unique geometries.
type Geometries struct {
FormatVersion string `json:"format_version"`
Geometry []Geometry `json:"minecraft:geometry"`
}

// Geometry represents a single geometry that contains bones and other information.
type Geometry struct {
Description struct {
Identifier string `json:"identifier"`
TextureWidth int `json:"texture_width"`
TextureHeight int `json:"texture_height"`
VisibleBoundsWidth float64 `json:"visible_bounds_width"`
VisibleBoundsHeight float64 `json:"visible_bounds_height"`
VisibleBoundsOffset mgl64.Vec3 `json:"visible_bounds_offset"`
} `json:"description"`
Bones []struct {
Name string `json:"name"`
Pivot mgl64.Vec3 `json:"pivot,omitempty"`
Rotation mgl64.Vec3 `json:"rotation,omitempty"`
Cubes []struct {
Origin mgl64.Vec3 `json:"origin"`
Size mgl64.Vec3 `json:"size"`
UV mgl64.Vec2 `json:"uv"`
Pivot mgl64.Vec3 `json:"pivot,omitempty"`
Rotation mgl64.Vec3 `json:"rotation,omitempty"`
Inflate float64 `json:"inflate,omitempty"`
} `json:"cubes"`
} `json:"bones"`
}

// Origin returns the origin of the geometry. It is calculated by using the smallest origin points of all cubes.
func (g Geometry) Origin() (x mgl64.Vec3) {
for _, bone := range g.Bones {
for _, cube := range bone.Cubes {
x[0] = math.Min(x[0], cube.Origin.X())
x[1] = math.Min(x[1], cube.Origin.Y())
x[2] = math.Min(x[2], cube.Origin.Z())
}
}
return
}

// Size returns the size of the geometry. It is calculated by using the largest size of all cubes.
func (g Geometry) Size() (x mgl64.Vec3) {
for _, bone := range g.Bones {
for _, cube := range bone.Cubes {
x[0] = math.Max(x[0], cube.Size.X())
x[1] = math.Max(x[1], cube.Size.Y())
x[2] = math.Max(x[2], cube.Size.Z())
}
}
return
}
66 changes: 66 additions & 0 deletions server/block/customblock/material.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package customblock

// Material represents a single material used for rendering part of a custom block.
type Material struct {
// texture is the name of the texture for the material.
texture string
// renderMethod is the method to use when rendering the material.
renderMethod RenderMethod
// faceDimming is if the material should be dimmed by the direction it's facing.
faceDimming bool
// ambientOcclusion is if the material should have ambient occlusion applied when lighting.
ambientOcclusion bool
}

// NewMaterial returns a new Material with the provided information. It also enabled face dimming and ambient occlusion
// by default based on the render method.
func NewMaterial(texture string, method RenderMethod) Material {
return Material{
faceDimming: true,
texture: texture,
renderMethod: method,
ambientOcclusion: method.AmbientOcclusion(),
}
}

// WithFaceDimming returns a copy of the Material with face dimming enabled.
func (m Material) WithFaceDimming() Material {
m.faceDimming = true
return m
}

// WithoutFaceDimming returns a copy of the Material with face dimming disabled.
func (m Material) WithoutFaceDimming() Material {
m.faceDimming = false
return m
}

// WithAmbientOcclusion returns a copy of the Material with ambient occlusion enabled.
func (m Material) WithAmbientOcclusion() Material {
m.ambientOcclusion = true
return m
}

// WithoutAmbientOcclusion returns a copy of the Material with ambient occlusion disabled.
func (m Material) WithoutAmbientOcclusion() Material {
m.ambientOcclusion = false
return m
}

// Encode returns the material encoded as a map[string]any.
func (m Material) Encode() map[string]any {
return map[string]any{
"texture": m.texture,
"render_method": m.renderMethod.String(),
"face_dimming": boolByte(m.faceDimming),
"ambient_occlusion": boolByte(m.ambientOcclusion),
}
}

// boolByte returns 1 if the bool passed is true, or 0 if it is false.
func boolByte(b bool) uint8 {
if b {
return 1
}
return 0
}
59 changes: 59 additions & 0 deletions server/block/customblock/material_target.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package customblock

// MaterialTarget represents a material target for a custom block. These are limited to either all targets, or the top,
// bottom, and sides.
type MaterialTarget struct {
materialTarget
}

// MaterialTargetAll represents the material target for all targets.
func MaterialTargetAll() MaterialTarget {
return MaterialTarget{0}
}

// MaterialTargetUp represents the material target for the top of the block.
func MaterialTargetUp() MaterialTarget {
return MaterialTarget{1}
}

// MaterialTargetDown represents the material target for the bottom of the block.
func MaterialTargetDown() MaterialTarget {
return MaterialTarget{2}
}

// MaterialTargetSides represents the material target for the sides of the block.
func MaterialTargetSides() MaterialTarget {
return MaterialTarget{3}
}

type materialTarget uint8

// Name returns the name of the material target.
func (m materialTarget) Name() string {
switch m {
case 0:
return "all"
case 1:
return "up"
case 2:
return "down"
case 3:
return "sides"
}
panic("should never happen")
}

// String returns the string representation of the material target.
func (m materialTarget) String() string {
switch m {
case 0:
return "*"
case 1:
return "up"
case 2:
return "down"
case 3:
return "sides"
}
panic("should never happen")
}
66 changes: 66 additions & 0 deletions server/block/customblock/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package customblock

import (
"fmt"
"github.com/go-gl/mathgl/mgl32"
"github.com/go-gl/mathgl/mgl64"
"golang.org/x/exp/maps"
)

// Model represents the model of a custom block. It can contain multiple materials applied to different parts of the
// model, as well as a reference to its geometry.
type Model struct {
materials map[string]Material
geometryName string
origin mgl64.Vec3
size mgl64.Vec3
}

// NewModel returns a new Model with the provided information. If the size is larger than 16x16x16, this method will
// panic since the client does not allow models larger than a single block.
func NewModel(geometryName string, origin, size mgl64.Vec3) Model {
if size.X() > 16 || size.Y() > 16 || size.Z() > 16 {
panic(fmt.Errorf("model size cannot exceed 16x16x16, got %v", size))
}
return Model{
geometryName: geometryName,
origin: origin,
size: size,
}
}

// WithMaterial returns a copy of the Model with the provided material.
func (m Model) WithMaterial(target string, material Material) Model {
m.materials = maps.Clone(m.materials)
m.materials[target] = material
return m
}

// Encode returns the model encoded as a map[string]any.
func (m Model) Encode() map[string]any {
materials := map[string]any{}
for target, material := range m.materials {
materials[target] = material.Encode()
}
origin := vec64To32(m.origin)
size := vec64To32(m.size)
return map[string]any{
"minecraft:material_instances": map[string]any{
"mappings": map[string]any{},
"materials": materials,
},
"minecraft:geometry": map[string]any{
"value": m.geometryName,
},
"minecraft:pick_collision": map[string]any{
"enabled": uint8(1),
"origin": origin[:],
"size": size[:],
},
}
}

// vec64To32 converts a mgl64.Vec3 to a mgl32.Vec3.
func vec64To32(vec3 mgl64.Vec3) mgl32.Vec3 {
return mgl32.Vec3{float32(vec3[0]), float32(vec3[1]), float32(vec3[2])}
}
Loading