Update menyelesaikan #1
1. **Survival Mode** – Pemain otomatis masuk . 2. **Village Generation** – Rumah desa (cobblestone, papan kayu, jendela, pintu) & pohon oak dibuat prosedural di . 3. **Ore & Terrain** – Semua ore vanilla (Coal–Emerald) dengan varian deepslate muncul sesuai kedalaman; bukit/gunung dibentuk via noise trigonometri. 4. **Mob Spawner** – Spawner periodik (babi, sapi, domba, zombie, skeleton) di sekitar pemain, cap maksimal 25 mob aktif. 5. **Struktur Baru** – Rumah kayu & cobblestone, aman dari batas chunk. 6. **Vegetasi** – Rumput, pakis, dan bunga dandelion otomatis di permukaan. 7. **Spawn Point** – Pemain baru spawn acak namun dekat pemain aktif lain. 8. **Cave Generation** – 3D noise carver untuk terowongan goa. 9. **Item Cleanup** – Auto-bersih item drop tiap 15 menit, notifikasi peringatan 5 menit sebelumnya. 10. **Auto Optimization** – + dijalankan tiap sesi cleanup untuk jaga performa server.
This commit is contained in:
@@ -3,11 +3,19 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
"math/rand/v2"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/df-mc/dragonfly/server"
|
||||
"github.com/df-mc/dragonfly/server/entity"
|
||||
"github.com/df-mc/dragonfly/server/player"
|
||||
"github.com/df-mc/dragonfly/server/player/chat"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
"github.com/pelletier/go-toml"
|
||||
)
|
||||
|
||||
@@ -26,9 +34,129 @@ func main() {
|
||||
|
||||
srv.Listen()
|
||||
|
||||
// 1. Periodic mob spawner loop
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(20 * time.Second)
|
||||
srv.World().Exec(func(tx *world.Tx) {
|
||||
mobsCount := 0
|
||||
for e := range tx.Entities() {
|
||||
if _, ok := e.H().Type().(entity.MobType); ok {
|
||||
mobsCount++
|
||||
}
|
||||
}
|
||||
|
||||
// Only spawn if count is below 25 to optimize performance
|
||||
if mobsCount < 25 {
|
||||
for plEntity := range tx.Players() {
|
||||
pl, ok := plEntity.(*player.Player)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 50% chance to spawn a mob around this player
|
||||
if rand.IntN(2) == 0 {
|
||||
dx := float64(rand.IntN(30) - 15)
|
||||
dz := float64(rand.IntN(30) - 15)
|
||||
if math.Abs(dx) > 5 || math.Abs(dz) > 5 {
|
||||
pos := pl.Position().Add(mgl64.Vec3{dx, 0, dz})
|
||||
y := float64(tx.HighestBlock(int(pos.X()), int(pos.Z()))) + 1.0
|
||||
if y > float64(tx.Range()[0]) {
|
||||
spawnPos := mgl64.Vec3{pos.X(), y, pos.Z()}
|
||||
types := []world.EntityType{
|
||||
entity.PigType,
|
||||
entity.CowType,
|
||||
entity.SheepType,
|
||||
entity.ZombieType,
|
||||
entity.SkeletonType,
|
||||
}
|
||||
t := types[rand.IntN(len(types))]
|
||||
|
||||
opts := world.EntitySpawnOpts{Position: spawnPos}
|
||||
h := opts.New(t, entity.PassiveBehaviourConfig{
|
||||
Gravity: 0.08,
|
||||
Drag: 0.02,
|
||||
})
|
||||
tx.AddEntity(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
// 2. Periodic item clearing and auto-optimization loop
|
||||
go func() {
|
||||
for {
|
||||
// Sleep 10 minutes, then notify
|
||||
time.Sleep(10 * time.Minute)
|
||||
srv.World().Exec(func(tx *world.Tx) {
|
||||
for plEntity := range tx.Players() {
|
||||
if pl, ok := plEntity.(*player.Player); ok {
|
||||
pl.Message("§e[Pemberitahuan] Semua item di tanah akan dibersihkan dalam 5 menit!§r")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Sleep 5 minutes, then clear and optimize
|
||||
time.Sleep(5 * time.Minute)
|
||||
srv.World().Exec(func(tx *world.Tx) {
|
||||
count := 0
|
||||
for e := range tx.Entities() {
|
||||
if e.H().Type().EncodeEntity() == "minecraft:item" {
|
||||
_ = e.Close()
|
||||
count++
|
||||
}
|
||||
}
|
||||
for plEntity := range tx.Players() {
|
||||
if pl, ok := plEntity.(*player.Player); ok {
|
||||
pl.Message(fmt.Sprintf("§a[Pemberitahuan] Berhasil membersihkan %d item di tanah!§r", count))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Trigger automatic optimization/GC
|
||||
runtime.GC()
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
}()
|
||||
|
||||
for p := range srv.Accept() {
|
||||
p.SetGameMode(world.GameModeCreative)
|
||||
p.Message("Selamat datang!")
|
||||
p.SetGameMode(world.GameModeSurvival)
|
||||
p.Message("§aSelamat datang! Bermainlah dalam Survival Mode.§r")
|
||||
|
||||
// Teleport player randomly near an existing player, or spawn
|
||||
go func(pl *player.Player) {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
pl.H().ExecWorld(func(tx *world.Tx, e world.Entity) {
|
||||
p := e.(*player.Player)
|
||||
var players []world.Entity
|
||||
for other := range tx.Players() {
|
||||
if other.H().UUID() != p.H().UUID() {
|
||||
players = append(players, other)
|
||||
}
|
||||
}
|
||||
|
||||
var basePos mgl64.Vec3
|
||||
if len(players) > 0 {
|
||||
target := players[rand.IntN(len(players))]
|
||||
basePos = target.Position()
|
||||
} else {
|
||||
basePos = tx.World().Spawn().Vec3()
|
||||
}
|
||||
|
||||
// Spawn randomly within 40 blocks of base position
|
||||
dx := float64(rand.IntN(80) - 40)
|
||||
dz := float64(rand.IntN(80) - 40)
|
||||
spawnX := basePos.X() + dx
|
||||
spawnZ := basePos.Z() + dz
|
||||
spawnY := float64(tx.HighestBlock(int(spawnX), int(spawnZ))) + 1.0
|
||||
|
||||
spawnPos := mgl64.Vec3{spawnX, spawnY, spawnZ}
|
||||
p.Teleport(spawnPos)
|
||||
})
|
||||
}(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user