mirror of
https://github.com/haselkern/Minecraft-ArmorStand.git
synced 2025-05-17 15:05:33 +00:00
Add code generation
This commit is contained in:
parent
1d6d6448ff
commit
8ccd87ae45
3 changed files with 318 additions and 3 deletions
|
@ -7,12 +7,14 @@ The following things still have to be done. Possibly in this order.
|
|||
- [ ] Equipment
|
||||
- [ ] Equipment locking
|
||||
- [ ] Can we scrape the MC wiki for a searchable dropdown list? https://minecraft.fandom.com/api.php ?
|
||||
* Only items that are available in a given minecraft version should show up
|
||||
- [ ] Colors for leather pieces
|
||||
- [ ] Helmet: player name
|
||||
- [ ] Helmet: Image URL
|
||||
- [ ] Helmet: https://minecraft-heads.com -> but use Minecraft-URL or Player name and skip the give code thing, that was confusing anyways. Have a help popup that explains this functionality with a few screenshots.
|
||||
- [ ] Custom name with styling options
|
||||
- [ ] Code generation
|
||||
- [ ] Hide controls that are not relevant for the chosen minecraft version
|
||||
- [ ] **Proper rotation conversion between Minecraft and ThreeJS**
|
||||
- [ ] /summon or /give
|
||||
- [ ] Hint for command block
|
||||
|
|
280
src/App.vue
280
src/App.vue
|
@ -50,7 +50,7 @@
|
|||
<div v-if="armorstand.enableEquipment">
|
||||
<input v-model="armorstand.equipHandRight" placeholder="Item in right hand"/>
|
||||
<input v-model="armorstand.equipHandLeft" placeholder="Item in left hand"/>
|
||||
<input v-model="armorstand.equipBoots" placeholder="Boots"/>
|
||||
<input v-model="armorstand.equipShoes" placeholder="Boots"/>
|
||||
<input v-model="armorstand.equipLeggings" placeholder="Leggings"/>
|
||||
<input v-model="armorstand.equipChestplate" placeholder="Chestplate"/>
|
||||
<input v-model="armorstand.equipHelmet" placeholder="Helmet"/>
|
||||
|
@ -93,6 +93,10 @@
|
|||
|
||||
<hr>
|
||||
|
||||
<p class="break-all">{{currentCode}}</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -101,6 +105,7 @@
|
|||
<script>
|
||||
import Scene from "./Scene.vue"
|
||||
import RotationSliderRow from "./RotationSliderRow.vue"
|
||||
import {generateIntArray, generateUUID, isXYZZero, xyzToTextArray} from "./util.js"
|
||||
|
||||
// The Armorstand will hold all attributes for an armor stand.
|
||||
class Armorstand {
|
||||
|
@ -129,7 +134,7 @@ class Armorstand {
|
|||
// Equipment attributes
|
||||
this.equipHandRight = ""
|
||||
this.equipHandLeft = ""
|
||||
this.equipBoots = ""
|
||||
this.equipShoes = ""
|
||||
this.equipLeggings = ""
|
||||
this.equipChestplate = ""
|
||||
this.equipHelmet = ""
|
||||
|
@ -147,6 +152,7 @@ class Armorstand {
|
|||
this.customNameStrikethrough = false
|
||||
|
||||
}
|
||||
|
||||
getScale() {
|
||||
if (this.small) {
|
||||
return { x: 0.6, y: 0.6, z: 0.6 }
|
||||
|
@ -154,10 +160,272 @@ class Armorstand {
|
|||
return { x: 1, y: 1, z: 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Return the code to generate this armorstand
|
||||
getCode(mcVersion) {
|
||||
// TODO Handle different versions
|
||||
//in 1.13, positions are no longer center-corrected. Adding .5 makes it centered. However for players it is already center-corrected
|
||||
var code = "/summon armor_stand ~ ~ ~ {"
|
||||
|
||||
// if (!give) { // TODO
|
||||
if (true) {
|
||||
// Old entity name
|
||||
if (mcVersion == "1.8" || mcVersion == "1.9"){
|
||||
code = "/summon ArmorStand ~ ~ ~ {"
|
||||
} else if (mcVersion == "1.11") {
|
||||
code = "/summon armor_stand ~ ~ ~ {"
|
||||
} else {
|
||||
if (this.centerCorrected) {
|
||||
code = "/summon armor_stand ~ ~-0.5 ~ {"
|
||||
} else {
|
||||
code = "/summon armor_stand ~ ~ ~ {"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(mcVersion == "1.8" || mcVersion == "1.9" || mcVersion == "1.11"){
|
||||
code = "/give @p minecraft:armor_stand 1 0 {EntityTag:{"
|
||||
} else {
|
||||
code = "/give @p armor_stand{EntityTag:{"
|
||||
}
|
||||
}
|
||||
|
||||
let tags = []
|
||||
|
||||
//CheckBoxes
|
||||
if (this.invisible) {
|
||||
tags.push("Invisible:1b")
|
||||
}
|
||||
if (this.invulnerable) {
|
||||
tags.push("Invulnerable:1b")
|
||||
}
|
||||
if (this.persistenceRequired) {
|
||||
tags.push("PersistenceRequired:1b")
|
||||
}
|
||||
if (this.noBasePlate) {
|
||||
tags.push("NoBasePlate:1b")
|
||||
}
|
||||
if (this.noGravity) {
|
||||
tags.push("NoGravity:1b")
|
||||
}
|
||||
if (this.showArms) {
|
||||
tags.push("ShowArms:1b")
|
||||
}
|
||||
if (this.small) {
|
||||
tags.push("Small:1b")
|
||||
}
|
||||
if (this.marker) {
|
||||
tags.push("Marker:1b")
|
||||
}
|
||||
|
||||
// Sliders
|
||||
if(this.rotation != 0) {
|
||||
tags.push("Rotation:["+this.rotation+"f]")
|
||||
}
|
||||
|
||||
// Equipment
|
||||
if (this.enableEquipment) {
|
||||
if (mcVersion == "1.8") {
|
||||
// Old 1.8 Equipment format
|
||||
let armor = []
|
||||
|
||||
armor.push(this.getHandRightItem())
|
||||
armor.push(this.getShoesItem())
|
||||
armor.push(this.getLeggingsItem())
|
||||
armor.push(this.getChestplateItem())
|
||||
armor.push(this.getHeadItem())
|
||||
|
||||
tags.push("Equipment:["+armor.join(",")+"]")
|
||||
} else {
|
||||
// New 1.9+ Equipment format
|
||||
let armor = []
|
||||
|
||||
armor.push(this.getShoesItem())
|
||||
armor.push(this.getLeggingsItem())
|
||||
armor.push(this.getChestplateItem())
|
||||
armor.push(this.getHeadItem());
|
||||
|
||||
tags.push("ArmorItems:["+armor.join(",")+"]")
|
||||
|
||||
let hands = []
|
||||
|
||||
hands.push(this.getHandRightItem())
|
||||
hands.push(this.getHandLeftItem())
|
||||
|
||||
tags.push("HandItems:["+hands.join(",")+"]")
|
||||
}
|
||||
}
|
||||
|
||||
// Custom name
|
||||
if (this.customName) {
|
||||
let name = []
|
||||
if (mcVersion == "1.8" || mcVersion == "1.9" || mcVersion == "1.11") {
|
||||
tags.push(`CustomName:"${this.customName}"`)
|
||||
} else if (mcVersion == "1.13") {
|
||||
name.push(this.getName())
|
||||
name.push(this.getNameColor())
|
||||
name.push(this.getNameBold())
|
||||
name.push(this.getNameItalic())
|
||||
name.push(this.getNameObfuscated())
|
||||
name.push(this.getNameStrikethrough())
|
||||
|
||||
tags.push(`CustomName:"{${name.join("")}}"`)
|
||||
} else {
|
||||
// CustomNames from 1.14+ can now use single quotes to contain json
|
||||
// Replace escaped double quotes with single quotes to make it look pretty
|
||||
name.push(this.getName().replaceAll("\\", ""))
|
||||
name.push(this.getNameColor().replaceAll("\\", ""))
|
||||
name.push(this.getNameBold().replaceAll("\\", ""))
|
||||
name.push(this.getNameItalic().replaceAll("\\", ""))
|
||||
name.push(this.getNameObfuscated().replaceAll("\\", ""))
|
||||
name.push(this.getNameStrikethrough().replaceAll("\\", ""))
|
||||
tags.push(`CustomName:'{${name.join("")}}'`)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.showCustomName) {
|
||||
tags.push("CustomNameVisible:1b")
|
||||
}
|
||||
|
||||
// DisabledSlots // TODO
|
||||
// if(useDisabledSlots){
|
||||
// tags.push("DisabledSlots:"+calculateDisabledSlotsFlag())
|
||||
// }
|
||||
|
||||
// Now the pose
|
||||
// TODO Somewhere a conversion between Minecraft and ThreeJS rotations must take place.
|
||||
let pose = []
|
||||
if (!isXYZZero(this.body)) {
|
||||
pose.push("Body:"+xyzToTextArray(this.body))
|
||||
}
|
||||
if (!isXYZZero(this.head)) {
|
||||
pose.push("Head:"+xyzToTextArray(this.head))
|
||||
}
|
||||
if (!isXYZZero(this.legLeft)) {
|
||||
pose.push("LeftLeg:"+xyzToTextArray(this.legLeft))
|
||||
}
|
||||
if (!isXYZZero(this.legRight)) {
|
||||
pose.push("RightLeg:"+xyzToTextArray(this.legRight))
|
||||
}
|
||||
if (this.showArms){
|
||||
if (!isXYZZero(this.armLeft)) {
|
||||
pose.push("LeftArm:"+xyzToTextArray(this.armLeft))
|
||||
}
|
||||
if (!isXYZZero(this.armRight)) {
|
||||
pose.push("RightArm:"+xyzToTextArray(this.armRight))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pose.length > 0) {
|
||||
tags.push("Pose:{"+pose.join(",")+"}")
|
||||
}
|
||||
|
||||
code += tags.join(",")
|
||||
code += "}"
|
||||
// if (give) { // TODO
|
||||
// code += "}"
|
||||
// if (mcVersion != "1.8" && mcVersion != "1.9" && mcVersion != "1.11") {
|
||||
// code += " 1"
|
||||
// }
|
||||
// }
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
getHandRightItem() {
|
||||
if(this.equipHandRight == "") return "{}"
|
||||
return "{id:\""+this.equipHandRight+"\",Count:1b}"
|
||||
}
|
||||
|
||||
getHandLeftItem() {
|
||||
if(this.equipHandLeft == "") return "{}"
|
||||
return "{id:\""+this.equipHandLeft+"\",Count:1b}"
|
||||
}
|
||||
|
||||
getShoesItem() {
|
||||
if(this.equipShoes == "") return "{}"
|
||||
return "{id:\""+this.equipShoes+"\",Count:1b"
|
||||
// +getLeatherColorString($("#shoecolor"), isLeatherArmor(equipShoes)) // TODO Leather armor
|
||||
+"}"
|
||||
}
|
||||
|
||||
getLeggingsItem() {
|
||||
if(this.equipLeggings == "") return "{}"
|
||||
return "{id:\""+this.equipLeggings+"\",Count:1b"
|
||||
// +getLeatherColorString($("#leggingscolor"), isLeatherArmor(this.equipLeggings))
|
||||
+"}"
|
||||
}
|
||||
|
||||
getChestplateItem() {
|
||||
if(this.equipChestplate == "") return "{}"
|
||||
return "{id:\""+this.equipChestplate+"\",Count:1b"
|
||||
// +getLeatherColorString($("#chestplatecolor"), isLeatherArmor(this.equipChestplate))
|
||||
+"}"
|
||||
}
|
||||
|
||||
getHeadItem() {
|
||||
if (this.equipHelmet == "") return "{}"
|
||||
|
||||
// Use input as item
|
||||
if (this.helmetMode == "item") {
|
||||
return "{id:\""+this.equipHelmet+"\",Count:1b"
|
||||
// +getLeatherColorString($("#helmetcolor"), isLeatherArmor(equipHelmet))
|
||||
+"}"
|
||||
}
|
||||
|
||||
// Use input as player name
|
||||
else if (this.helmetMode == "player") {
|
||||
if (mcVersion == "1.8" || mcVersion == "1.10" || mcVersion == "1.11") {
|
||||
return "{id:\"skull\",Count:1b,Damage:3b,tag:{SkullOwner:\""+this.equipHelmet+"\"}}"
|
||||
} else {
|
||||
return "{id:\"player_head\",Count:1b,tag:{SkullOwner:\""+this.equipHelmet+"\"}}"
|
||||
}
|
||||
}
|
||||
|
||||
// Use input as url
|
||||
// Best reference: http://redd.it/24quwx
|
||||
else if (this.helmetMode == "url") {
|
||||
let base64Value = btoa('{"textures":{"SKIN":{"url":"'+this.equipHelmet+'"}}}')
|
||||
|
||||
if (mcVersion == "1.8" || mcVersion == "1.9" || mcVersion == "1.11"){
|
||||
return '{id:"skull",Count:1b,Damage:3b,tag:{SkullOwner:{Id:"'+generateUUID()+'",Properties:{textures:[{Value:"'+base64Value+'"}]}}}}'
|
||||
} else if (mcVersion == "1.14") {
|
||||
return '{id:"minecraft:player_head",Count:1b,tag:{SkullOwner:{Id:"'+generateUUID()+'",Properties:{textures:[{Value:"'+base64Value+'"}]}}}}'
|
||||
} else {
|
||||
return '{id:"minecraft:player_head",Count:1b,tag:{SkullOwner:{Id:'+generateIntArray()+',Properties:{textures:[{Value:"'+base64Value+'"}]}}}}'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getName() {
|
||||
if (this.customName == "") return ""
|
||||
return `\\"text\\":\\"${this.customName}\\"`
|
||||
}
|
||||
|
||||
getNameColor() {
|
||||
if (this.customNameColor == "") return ""
|
||||
return `,\\"color\\":\\"${this.customNameColor}\\"`
|
||||
}
|
||||
|
||||
getNameBold() {
|
||||
if (!this.customNameBold) return ""
|
||||
return `,\\"bold\\":\\"true\\"`
|
||||
}
|
||||
|
||||
getNameItalic() {
|
||||
if (!this.customNameItalic) return ""
|
||||
return `,\\"italic\\":\\"true\\"`
|
||||
}
|
||||
|
||||
getNameStrikethrough() {
|
||||
if (!this.customNameStrikethrough) return ""
|
||||
return `,\\"strikethrough\\":\\"true\\"`
|
||||
}
|
||||
|
||||
getNameObfuscated() {
|
||||
if (!this.customNameObfuscated) return ""
|
||||
return `,\\"obfuscated\\":\\"true\\"`
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -167,6 +435,12 @@ export default {
|
|||
mcVersion: "1.16",
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// Code for the current armor stand
|
||||
currentCode() {
|
||||
return this.armorstand.getCode(this.mcVersion)
|
||||
},
|
||||
},
|
||||
components: { Scene, RotationSliderRow },
|
||||
}
|
||||
</script>
|
||||
|
|
39
src/util.js
Normal file
39
src/util.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
// This file contains small helper methods
|
||||
|
||||
// From here: http://stackoverflow.com/a/8809472/1456971
|
||||
export function generateUUID(){
|
||||
var d = new Date().getTime()
|
||||
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = (d + Math.random()*16)%16 | 0
|
||||
d = Math.floor(d/16)
|
||||
return (c=='x' ? r : (r&0x3|0x8)).toString(16)
|
||||
})
|
||||
return uuid
|
||||
}
|
||||
|
||||
export function generateIntArray() {
|
||||
const buffer = new Uint32Array(4)
|
||||
const UUID = new DataView(buffer.buffer)
|
||||
const paddings = [8, 4, 4, 4, 12]
|
||||
|
||||
let hexUUID = generateUUID().split("-").map((val, i) => val.padStart(paddings[i], "0")).join("")
|
||||
let ints = []
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
num = Number("0x" + hexUUID.substring(i*8, (i+1)*8))
|
||||
UUID.setInt32(i*4, num)
|
||||
ints.push(UUID.getInt32(i*4))
|
||||
}
|
||||
|
||||
return '[I;' + ints.join(",") + ']'
|
||||
}
|
||||
|
||||
// Check if the x, y, z attributes of the given thing are all zero.
|
||||
export function isXYZZero(thing) {
|
||||
return thing.x == 0 && thing.y == 0 && thing.z == 0
|
||||
}
|
||||
|
||||
// Returns a string with a JSON array from the x, y, z attributes of the given thing.
|
||||
export function xyzToTextArray(thing) {
|
||||
return "["+thing.x+"f,"+thing.y+"f,"+thing.z+"f]";
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue