Skip to content

Instantly share code, notes, and snippets.

@MercerK

MercerK/block.ts Secret

Created September 14, 2021 01:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MercerK/ed0b5721ddbb00ba0e38a0eb86363ef5 to your computer and use it in GitHub Desktop.
Save MercerK/ed0b5721ddbb00ba0e38a0eb86363ef5 to your computer and use it in GitHub Desktop.
block state persistence
import { Material } from '../../references'
import { ItemStoreMechanic } from '../item'
import { ItemKeys } from '../item/data'
import { createCustomItem, ItemUtil } from '../item/itemInstance'
import yaml from 'yaml'
const serializeChunk = (chunk: obChunk) => `${chunk.getX()},${chunk.getZ()}`
const LocationUtil = (arg: obbBlock) => {
const location = arg.getLocation()
function relativeToChunk(loc = location) {
return {
x: location.getX() & 0x000f,
y: location.getY() & 0x00ff,
z: location.getZ() & 0x000f,
}
}
function serializeRelativeToChunk() {
const { x, y, z } = relativeToChunk()
return `${x},${y},${z}`
}
function serializeChunk() {
const chunk = location.getChunk()
return `${chunk.getX()},${chunk.getZ()}`
}
return {
relativeToChunk,
serializeRelativeToChunk,
serializeChunk,
}
}
const Registry = <Registry extends Record<any, any>>() => {
let instances = []
return (name: string, folder: string) => {
const path = `plugins/grakkit/data/server/${folder}/${name}.yml`
const file = core.file(path)
const registry: Record<string, Registry> = loadFile()
let length = 0
function loadFile() {
let data = file.exists ? yaml.parse(file.read()) : {}
if (!file.exists) {
file.entry().write(yaml.stringify(data))
}
length = getLength(data)
if (length > 0) console.log(`Loading ${length} items`)
return data
}
function saveFile() {
file.write(yaml.stringify(registry))
}
function get(key: string) {
return registry[key]
}
function set(key: string, value: Registry) {
if (!registry[key]) length++
registry[key] = value
saveFile()
}
function has(key: string) {
return registry[key] !== undefined
}
function unset(key: string) {
length--
delete registry[key]
}
function getLength(data = registry) {
return Object.keys(data).length
}
function toString() {
return JSON.stringify(registry)
}
return {
get,
set,
has,
unset,
getLength,
toString,
toJSON: toString,
}
}
}
const BlockRegistry = Registry<{
placed: string
itemId: ItemKeys
}>()
const ChunkRegistry = Registry<{
blocks: ReturnType<typeof BlockRegistry>
}>()
const WorldRegistry = Registry<{
chunks: ReturnType<typeof ChunkRegistry>
}>()
export class BlockStorage {
static registry = ChunkRegistry('chunks', '')
static initializeEvents() {
// Unload Chunks
core.event('org.bukkit.event.world.ChunkUnloadEvent', (event) => {
const serializedChunk = serializeChunk(event.getChunk())
if (BlockStorage.registry.has(serializedChunk)) {
BlockStorage.registry.unset(serializedChunk)
console.log(`[Verbose] Unloading Chunk ${serializeChunk(event.getChunk())}`)
}
})
// Adds to Registry
core.event('org.bukkit.event.block.BlockPlaceEvent', (event) => {
const block = event.getBlock()
const item = event.getItemInHand()
if (block.getType() !== Material.PLAYER_HEAD && block.getType() !== Material.PLAYER_WALL_HEAD)
return
const itemId = ItemUtil(item).getItemId()
if (!itemId) return
BlockStorage.setBlock(block, itemId)
})
// Removes block from registry and drops correct item
core.event('org.bukkit.event.block.BlockBreakEvent', (event) => {
const block = event.getBlock()
if (block.getType() !== Material.PLAYER_HEAD && block.getType() !== Material.PLAYER_WALL_HEAD)
return
const state = BlockStorage.getBlock(block)
if (!state) return
const { itemId } = state
const customItem = ItemStoreMechanic.getItem(itemId)
if (!customItem) return
event.setDropItems(false)
block.getWorld().dropItem(block.getLocation(), createCustomItem(customItem))
})
}
private static getBlock(block: obbBlock) {
const util = LocationUtil(block)
const serializedChunk = util.serializeChunk()
const chunk = BlockStorage.registry.get(serializedChunk)
if (!chunk) return
const serializedBlock = util.serializeRelativeToChunk()
if (!chunk.blocks.get) {
chunk.blocks = BlockRegistry(serializedChunk, 'chunks')
}
const blockState = chunk.blocks.get(serializedBlock)
chunk.blocks.unset(serializedBlock)
return blockState
}
private static setBlock(block: obbBlock, itemId: ItemKeys) {
const util = LocationUtil(block)
const serializedChunk = util.serializeChunk()
let chunk = BlockStorage.registry.get(serializedChunk)
if (!chunk) {
BlockStorage.registry.set(serializedChunk, {
blocks: BlockRegistry(serializedChunk, 'chunks'),
})
chunk = BlockStorage.registry.get(serializedChunk)
}
if (!chunk.blocks.get) {
chunk.blocks = BlockRegistry(serializedChunk, 'chunks')
}
chunk.blocks.set(LocationUtil(block).serializeRelativeToChunk(), {
placed: new Date().toISOString(),
itemId,
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment