Skip to content

Commit 13ad209

Browse files
authored
Merge pull request mc-wiki#100 from Nickid2018/main
Add two types for protocol viewer
2 parents 7e82190 + 320abfb commit 13ad209

8 files changed

Lines changed: 160 additions & 2 deletions

File tree

‎src/tools/protocol/constants.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export const DATA_REPO =
22
'https://raw.githubusercontent.com/Nickid2018/MC_Protocol_Data/refs/heads/master'
3+
// 'http://localhost:3001'
34
export const VERSIONS_JSON = `${DATA_REPO}/java_edition/versions.json`
45
export const INDEX_CSV = `${DATA_REPO}/java_edition/indexes.csv`
56
export const PACKETS_CSV = `${DATA_REPO}/java_edition/packets.csv`

‎src/tools/protocol/locale/en.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
"protocol.type.buffer": "Byte Sequence",
2525
"protocol.type.codec": "Registry Codec according to {link}",
2626
"protocol.type.codec.void": "This field is discarded in this packet",
27+
"protocol.type.direct_holder.complex": "Registry Network ID for {registry} or Direct Holder",
28+
"protocol.type.direct_holder.primitive": "Registry Network ID for {registry} or {type}",
29+
"protocol.type.either": "Conditional Field according to Boolean",
30+
"protocol.type.either.true": "True",
31+
"protocol.type.either.false": "False",
2732
"protocol.type.entity_metadata_loop": "Entity Metadata Loop (End with {endVal})",
2833
"protocol.type.f32": "32-bit IEEE-754 Floating Point Number",
2934
"protocol.type.f64": "64-bit IEEE-754 Floating Point Number",

‎src/tools/protocol/locale/zh-cn.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
"protocol.type.buffer": "字节序列",
2525
"protocol.type.codec": "依赖{link}的注册表编码",
2626
"protocol.type.codec.void": "此字段被跳过",
27+
"protocol.type.direct_holder.complex": "注册表{registry}网络ID或具体结构",
28+
"protocol.type.direct_holder.primitive": "注册表{registry}网络ID或{type}",
29+
"protocol.type.either": "依赖布尔值的条件字段",
30+
"protocol.type.either.true": "真",
31+
"protocol.type.either.false": "假",
2732
"protocol.type.entity_metadata_loop": "实体元数据循环(以{endVal}结尾)",
2833
"protocol.type.f32": "32位IEEE-754浮点数",
2934
"protocol.type.f64": "64位IEEE-754浮点数",
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<script setup lang="ts">
2+
import type { GetOrCache, IndexerType } from '../constants.ts'
3+
import { asyncComputed } from '@vueuse/core'
4+
import { CdxButton, CdxTextInput } from '@wikimedia/codex'
5+
import { computed, inject, nextTick, ref } from 'vue'
6+
import { useI18n } from 'vue-i18n'
7+
import { getAsPrimitiveProtocol, indexed, isActionKey } from '../constants.ts'
8+
import TypeChoice from './TypeChoice.vue'
9+
10+
const props = defineProps<{ data: object; version: number }>()
11+
const { t } = useI18n()
12+
const cacheGet = inject('cache-get') as GetOrCache
13+
const getIndexFor = inject('get-index-for') as IndexerType
14+
15+
const errorState =
16+
!Array.isArray(props.data) || props.data[0] !== 'direct_holder' || props.data.length !== 3
17+
const registry = (props.data as any[])[1] as string
18+
const content = (props.data as any[])[2] as string | object
19+
const primitive = getAsPrimitiveProtocol(content)
20+
const desc = primitive
21+
? t('protocol.type.direct_holder.primitive', { registry, type: t(`protocol.type.${primitive}`) })
22+
: t('protocol.type.direct_holder.complex', { registry })
23+
24+
const showSubType = ref(false)
25+
const loadingState = ref(true)
26+
const data = asyncComputed<string[]>(
27+
async () => {
28+
if (!showSubType.value) return Promise.resolve([]) // lazy
29+
const index = getIndexFor(props.version, registry)
30+
if (index === -1) return Promise.resolve([])
31+
return await cacheGet(props.version, `registry.${registry}`, async () => {
32+
return (await (await fetch(indexed(index, `registries/${registry}.json`))).json()) || []
33+
})
34+
},
35+
[],
36+
loadingState,
37+
)
38+
const writeableRegistry = computed(() => data.value.length === 0)
39+
40+
const mode = ref(true)
41+
const input = ref('0')
42+
const result = computed(() => {
43+
if (mode.value) {
44+
const num = Number(input.value)
45+
if (Number.isNaN(num)) return 'Not a number'
46+
return data.value[num] || 'Invalid network ID'
47+
} else {
48+
const index = data.value.findIndex((i) => i === input.value)
49+
if (index >= 0) return `${index}`
50+
return 'Invalid ID'
51+
}
52+
})
53+
54+
function changeMode() {
55+
const lastResult = result.value
56+
mode.value = !mode.value
57+
nextTick(() => (input.value = lastResult))
58+
}
59+
</script>
60+
<template>
61+
<div class="complex-padding flex">
62+
<span v-if="errorState" class="error-state">{{ t('protocol.error.data') }}</span>
63+
<span v-else class="flex-1">{{ desc }}</span>
64+
<span
65+
v-if="!primitive && !errorState"
66+
class="action-text"
67+
tabindex="0"
68+
@click="showSubType = !showSubType"
69+
@keyup="(e: KeyboardEvent) => isActionKey(e) && (showSubType = !showSubType)"
70+
>
71+
[{{ showSubType ? t('protocol.action.collapse') : t('protocol.action.expand') }}]
72+
</span>
73+
</div>
74+
<div v-if="loadingState && showSubType" class="px-[0.4em]">{{ t('protocol.loading') }}</div>
75+
<div v-else-if="showSubType && writeableRegistry" class="px-[0.4em] pb-[0.2em] italic">
76+
{{ t('protocol.type.registry.writeable') }}
77+
</div>
78+
<div v-else-if="showSubType" class="sub-type w-full flex flex-row items-center">
79+
<CdxButton @click="changeMode">
80+
{{ t(`protocol.action.search_registry.${mode ? 'network_id' : 'id_network'}`) }}
81+
</CdxButton>
82+
<CdxTextInput v-model="input" :input-type="mode ? 'number' : 'text'" translate="no" />
83+
<span class="px-[0.4em] py-[0.2em] min-w-16 text-center" translate="no">{{ result }}</span>
84+
</div>
85+
<TypeChoice v-if="showSubType" :data="content" :version="version" type="div" class="sub-type" />
86+
</template>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue'
3+
import { useI18n } from 'vue-i18n'
4+
import { isActionKey } from '../constants.ts'
5+
import TypeChoice from './TypeChoice.vue'
6+
7+
const props = defineProps<{ data: object; version: number }>()
8+
const { t } = useI18n()
9+
10+
const errorState =
11+
!Array.isArray(props.data) || props.data[0] !== 'either' || props.data.length !== 3
12+
const trueContent = (props.data as any[])[1] as string | object
13+
const falseContent = (props.data as any[])[2] as string | object
14+
15+
const showSubType = ref(false)
16+
</script>
17+
<template>
18+
<div class="complex-padding flex">
19+
<span v-if="errorState" class="error-state">{{ t('protocol.error.data') }}</span>
20+
<span v-else class="flex-1">{{ t('protocol.type.either') }}</span>
21+
<span
22+
v-if="!errorState"
23+
class="action-text"
24+
tabindex="0"
25+
@click="showSubType = !showSubType"
26+
@keyup="(e: KeyboardEvent) => isActionKey(e) && (showSubType = !showSubType)"
27+
>
28+
[{{ showSubType ? t('protocol.action.collapse') : t('protocol.action.expand') }}]
29+
</span>
30+
</div>
31+
<table v-if="showSubType" class="either-table w-full">
32+
<tr>
33+
<td class="non-complex">{{ t('protocol.type.either.true') }}</td>
34+
<TypeChoice :data="trueContent" :version="version" />
35+
</tr>
36+
<tr>
37+
<td class="non-complex">{{ t('protocol.type.either.false') }}</td>
38+
<TypeChoice :data="falseContent" :version="version" />
39+
</tr>
40+
</table>
41+
</template>
42+
<style>
43+
.either-table > tr > td:first-child {
44+
border-left: none;
45+
}
46+
.either-table > tr > td:last-child {
47+
border-right: none;
48+
}
49+
.either-table > tr:last-child > td {
50+
border-bottom: none;
51+
}
52+
</style>

‎src/tools/protocol/types/ReferenceType.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const showSubType = ref(false)
2525
const loadingState = ref(true)
2626
const data = asyncComputed<string | object>(
2727
async () => {
28-
if (!showSubType.value) return Promise.resolve([]) // lazy
28+
if (!showSubType.value) return Promise.resolve('void') // lazy
2929
return await cacheGet(props.version, `structure.${content}`, async () => {
3030
const index = getPacketFor(props.version, content)
3131
return (await (await fetch(indexed(index, `structures/${content}.json`))).json()) || 'void'

‎src/tools/protocol/types/RegistryType.vue‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ const loadingState = ref(true)
2525
const data = asyncComputed<string[]>(
2626
async () => {
2727
if (!showSearching.value) return Promise.resolve([]) // lazy
28+
const index = getIndexFor(props.version, content)
29+
if (index === -1) return Promise.resolve([])
2830
return await cacheGet(props.version, `registry.${content}`, async () => {
29-
const index = getIndexFor(props.version, content)
3031
return (await (await fetch(indexed(index, `registries/${content}.json`))).json()) || []
3132
})
3233
},

‎src/tools/protocol/types/TypeChoice.vue‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import ArrayType from './ArrayType.vue'
66
import BitfieldType from './BitfieldType.vue'
77
import CodecType from './CodecType.vue'
88
import Container from './Container.vue'
9+
import DirectHolderType from './DirectHolderType.vue'
10+
import EitherType from './EitherType.vue'
911
import EntityMetadataLoopType from './EntityMetadataLoopType.vue'
1012
import MapperType from './MapperType.vue'
1113
import OptionType from './OptionType.vue'
@@ -76,6 +78,12 @@ const type = props.type || 'td'
7678
<component :is="type" v-else-if="props.data[0] === 'codec'">
7779
<CodecType :data="props.data" :version="props.version" />
7880
</component>
81+
<component :is="type" v-else-if="props.data[0] === 'either'">
82+
<EitherType :data="props.data" :version="props.version" />
83+
</component>
84+
<component :is="type" v-else-if="props.data[0] === 'direct_holder'">
85+
<DirectHolderType :data="props.data" :version="props.version" />
86+
</component>
7987
<component :is="type" v-else-if="props.data[0] === 'fix_buffer'" class="non-complex">
8088
{{ t('protocol.type.fix_buffer', { length: props.data[1] }) }}
8189
</component>

0 commit comments

Comments
 (0)