mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-24 15:47:08 +00:00
Add loot table preview (#293)
* Initial loot table preview + item display counts * Add loot functions without NBT * Add loot conditions * Render item tooltips with name and lore components * Remove debug text component * Disable advanced tooltips in the tree * Minor style fixes * Add item slot overlay and tweak tooltip offset * Fix some items not rendering * Translate item names and text components * Translate params + more functions and tooltips * Add durability bar * Configurable stack mixing * Correct tooltip background and border * Add enchanting * Enchantment glint * Configurable luck, daytime and weather * Improve tooltip spacing * More tooltip spacing improvements * Remove debug logging
This commit is contained in:
@@ -63,8 +63,6 @@ export const BiomeSourcePreview = ({ model, data, shown, version }: PreviewProps
|
||||
}
|
||||
}, [version, state, scale, seed, yOffset, shown, biomeColors, project])
|
||||
|
||||
console.log(yOffset)
|
||||
|
||||
const changeScale = (newScale: number) => {
|
||||
newScale = Math.max(1, Math.round(newScale))
|
||||
offset.current[0] = offset.current[0] * scale / newScale
|
||||
|
||||
79
src/app/components/previews/LootTablePreview.tsx
Normal file
79
src/app/components/previews/LootTablePreview.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { DataModel } from '@mcschema/core'
|
||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import { useLocale, useVersion } from '../../contexts/index.js'
|
||||
import type { SlottedItem } from '../../previews/LootTable.js'
|
||||
import { generateLootTable } from '../../previews/LootTable.js'
|
||||
import { clamp, randomSeed } from '../../Utils.js'
|
||||
import { Btn, BtnMenu, NumberInput } from '../index.js'
|
||||
import { ItemDisplay } from '../ItemDisplay.jsx'
|
||||
import type { PreviewProps } from './index.js'
|
||||
|
||||
export const LootTablePreview = ({ data }: PreviewProps) => {
|
||||
const { locale } = useLocale()
|
||||
const { version } = useVersion()
|
||||
const [seed, setSeed] = useState(randomSeed())
|
||||
const [luck, setLuck] = useState(0)
|
||||
const [daytime, setDaytime] = useState(0)
|
||||
const [weather, setWeather] = useState('clear')
|
||||
const [mixItems, setMixItems] = useState(true)
|
||||
const [advancedTooltips, setAdvancedTooltips] = useState(true)
|
||||
const overlay = useRef<HTMLDivElement>(null)
|
||||
|
||||
const [items, setItems] = useState<SlottedItem[]>([])
|
||||
|
||||
const table = DataModel.unwrapLists(data)
|
||||
const state = JSON.stringify(table)
|
||||
useEffect(() => {
|
||||
const items = generateLootTable(table, { version, seed, luck, daytime, weather, stackMixer: mixItems ? 'container' : 'default' })
|
||||
setItems(items)
|
||||
}, [version, seed, luck, daytime, weather, mixItems, state])
|
||||
|
||||
return <>
|
||||
<div ref={overlay} class="preview-overlay">
|
||||
<img src="/images/container.png" alt="Container background" class="pixelated" draggable={false} />
|
||||
{items.map(({ slot, item }) =>
|
||||
<div key={slot} style={slotStyle(slot)}>
|
||||
<ItemDisplay item={item} slotDecoration={true} advancedTooltip={advancedTooltips} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div class="controls preview-controls">
|
||||
<BtnMenu icon="gear" tooltip={locale('settings')} >
|
||||
<div class="btn btn-input" onClick={e => e.stopPropagation()}>
|
||||
<span>{locale('preview.luck')}</span>
|
||||
<NumberInput value={luck} onChange={setLuck} />
|
||||
</div>
|
||||
<div class="btn btn-input" onClick={e => e.stopPropagation()}>
|
||||
<span>{locale('preview.daytime')}</span>
|
||||
<NumberInput value={daytime} onChange={setDaytime} />
|
||||
</div>
|
||||
<div class="btn btn-input" onClick={e => e.stopPropagation()}>
|
||||
<span>{locale('preview.weather')}</span>
|
||||
<select value={weather} onChange={e => setWeather((e.target as HTMLSelectElement).value)} >
|
||||
{['clear', 'rain', 'thunder'].map(v =>
|
||||
<option value={v}>{locale(`preview.weather.${v}`)}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
<Btn icon={mixItems ? 'square_fill' : 'square'} label="Fill container randomly" onClick={e => {setMixItems(!mixItems); e.stopPropagation()}} />
|
||||
<Btn icon={advancedTooltips ? 'square_fill' : 'square'} label="Advanced tooltips" onClick={e => {setAdvancedTooltips(!advancedTooltips); e.stopPropagation()}} />
|
||||
</BtnMenu>
|
||||
<Btn icon="sync" tooltip={locale('generate_new_seed')} onClick={() => setSeed(randomSeed())} />
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
const GUI_WIDTH = 176
|
||||
const GUI_HEIGHT = 81
|
||||
const SLOT_SIZE = 18
|
||||
|
||||
function slotStyle(slot: number) {
|
||||
slot = clamp(slot, 0, 26)
|
||||
const x = (slot % 9) * SLOT_SIZE + 7
|
||||
const y = (Math.floor(slot / 9)) * SLOT_SIZE + 20
|
||||
return {
|
||||
left: `${x*100/GUI_WIDTH}%`,
|
||||
top: `${y*100/GUI_HEIGHT}%`,
|
||||
width: `${SLOT_SIZE*100/GUI_WIDTH}%`,
|
||||
height: `${SLOT_SIZE*100/GUI_HEIGHT}%`,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user