1
0
Fork 0
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:
Lars Martens 2021-08-20 20:43:29 +02:00
parent 1d6d6448ff
commit 8ccd87ae45
3 changed files with 318 additions and 3 deletions

View file

@ -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

View file

@ -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
View 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]";
}