Updating to 1.15-pre1 part 3

This commit is contained in:
Sollace 2019-11-23 23:06:07 +02:00
parent 4cc6d03fce
commit e1109223c2
14 changed files with 194 additions and 219 deletions

View file

@ -105,31 +105,4 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends PlayerEnti
((ClientPonyModel<T>)model).metadata = metadata;
}
}
/*@Override
public ModelPart getRandomCuboid(Random rand) {
// grab one at random, but cycle through the list until you find one that's filled.
// Return if you find one, or if you get back to where you started in which case there isn't any.
int randomI = rand.nextInt(cuboidList.size());
int index = randomI;
ModelPart result;
do {
result = cuboidList.get(randomI);
if (!result.cuboids.isEmpty()) return result;
index = (index + 1) % cuboidList.size();
} while (index != randomI);
if (result.cuboids.isEmpty()) {
result.addCuboid(0, 0, 0, 0, 0, 0);
}
if (result.cuboids.isEmpty()) {
throw new IllegalStateException("This model contains absolutely no boxes and a box could not be added!");
}
return result;
}*/
}

View file

@ -83,7 +83,7 @@ public class ModelPonyArmour<T extends LivingEntity> extends AbstractPonyModel<T
@Deprecated
protected void initBody(float yOffset, float stretch) {
super.initBody(yOffset, stretch);
//super.initBody(yOffset, stretch);
chestPiece = new com.minelittlepony.client.util.render.Part(this, 16, 8)
.around(HEAD_RP_X, HEAD_RP_Y + yOffset, HEAD_RP_Z)
@ -114,7 +114,7 @@ public class ModelPonyArmour<T extends LivingEntity> extends AbstractPonyModel<T
@Deprecated
protected void initLegs(float yOffset, float stretch) {
super.initLegs(yOffset, stretch);
//super.initLegs(yOffset, stretch);
int armLength = attributes.armLength;
int armWidth = attributes.armWidth;

View file

@ -5,15 +5,17 @@ import com.minelittlepony.client.util.render.Part;
import com.minelittlepony.model.ICapitated;
import com.minelittlepony.pony.IPonyData;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.SkullOverlayEntityModel;
import net.minecraft.client.util.math.MatrixStack;
public class ModelPonyHead extends SkullOverlayEntityModel implements ICapitated<ModelPart> {
private PonySnout snout;
private final UnicornHorn horn;
private UnicornHorn horn;
private final Part ears;
private ModelPart ears;
public IPonyData metadata = new PonyData();
@ -44,17 +46,17 @@ public class ModelPonyHead extends SkullOverlayEntityModel implements ICapitated
}
@Override
public void render(float move, float swing, float ticks, float headYaw, float headPitch, float scale) {
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
snout.isHidden = metadata.getRace().isHuman();
ears.field_3664 = snout.isHidden;
ears.visible = !snout.isHidden;
snout.setGender(metadata.getGender());
super.render(move, swing, ticks, headYaw, headPitch, scale);
super.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
if (metadata.hasHorn()) {
getHead().applyTransform(scale);
horn.renderPart(scale, null);
getHead().rotate(stack);
horn.renderPart(stack, vertices, overlayUv, lightUv, red, green, blue, alpha, null);
}
}
}

View file

@ -45,11 +45,6 @@ public class PonyElytra<T extends LivingEntity> extends AnimalModel<T> {
super.method_22696(t);
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float limbDistance, float limbAngle, float tickDelta, float alpha) {
super.render(stack, vertices, overlayUv, lightUv, limbDistance, limbAngle, tickDelta, alpha);
}
/**
* Sets the model's various rotation angles.
*

View file

@ -1,6 +1,7 @@
package com.minelittlepony.client.model.components;
import net.minecraft.client.model.Model;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.MathHelper;
@ -22,12 +23,9 @@ public class PonyTail extends Part implements IPart {
public PonyTail(AbstractPonyModel<?> model) {
super(model);
theModel = model;
}
@Override
public void init(float yOffset, float stretch) {
for (int i = 0; i < SEGMENTS; i++) {
addChild(new TailSegment(theModel, i, yOffset, stretch));
addChild(new TailSegment(theModel, i));
}
}
@ -82,39 +80,35 @@ public class PonyTail extends Part implements IPart {
render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
private class TailSegment extends Part {
private class TailSegment extends ModelPart {
private final int index;
public TailSegment(Model model, int index, float yOffset, float stretch) {
public TailSegment(Model model, int index) {
super(model);
this.index = index;
y = ((float)index)/4 + 0.063f;
pivotY = ((float)index)/4 + 0.063f;
init(yOffset, stretch);
}
public void init(float yOffset, float stretch) {
int texX = (index % 2) * 4;
around(TAIL_RP_X, TAIL_RP_Y + yOffset, 0);
around(TAIL_RP_X, TAIL_RP_Y, 0);
if (index == 0) {
tex(32, 0).top(-2, 0, 2, 4, 4, stretch);
tex(32, 0).top(-2, 0, 2, 4, 4, 0);
}
tex(36, texX) .east( 2, 0, 2, 4, 4, stretch)
.west(-2, 0, 2, 4, 4, stretch);
tex(32, texX).south(-2, 0, 2, 4, 4, stretch)
.north(-2, 0, 6, 4, 4, stretch);
tex(32, 0) .bottom(-2, 4, 2, 4, 4, stretch);
tex(36, texX) .east( 2, 0, 2, 4, 4, 0)
.west(-2, 0, 2, 4, 4, 0);
tex(32, texX).south(-2, 0, 2, 4, 4, 0)
.north(-2, 0, 6, 4, 4, 0);
tex(32, 0) .bottom(-2, 4, 2, 4, 4, 0);
}
@Override
public void render(float scale) {
public void render(MatrixStack stack, VertexConsumer renderContext, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
if (index < tailStop) {
super.render(scale);
super.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
}
}
}

View file

@ -7,10 +7,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import org.lwjgl.opengl.GL11;
import com.minelittlepony.client.util.render.Color;
import com.minelittlepony.client.util.render.Part;
import com.minelittlepony.model.BodyPart;
import com.minelittlepony.model.IModel;
import com.minelittlepony.pony.meta.Wearable;
@ -20,34 +17,27 @@ import java.util.UUID;
public class ChristmasHat extends AbstractGear {
private static boolean dayChecked = false;
private static boolean dayResult = false;
private static boolean isChristmasDay() {
if (!dayChecked) {
dayChecked = true;
Calendar cal = Calendar.getInstance();
dayResult = cal.get(Calendar.MONTH) == Calendar.DECEMBER
&& cal.get(Calendar.DAY_OF_MONTH) == 25;
}
return dayResult;
}
private static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/antlers.png");
private Part left;
private Part right;
private ModelPart left;
private ModelPart right;
private int tint;
@Override
public void init(float yOffset, float stretch) {
accept(left = new Part(this, 0, 0).size(16, 8)
.around(-7, 0.5F, 0.5F)
.offset(-7, 0, 0)
.at(3, -4, 0)
.box(0, 0, 0, 7, 1, 1, stretch)
.tex(0, 2).box(0, -1, 0, 1, 1, 1, stretch)
.tex(4, 2).box(2, -1, 0, 1, 1, 1, stretch)
.tex(8, 2).box(4, -1, 0, 1, 1, 1, stretch));
accept(right = new Part(this, 0, 4).size(16, 8)
.around(7, 0.5F, 0.5F)
.offset(0, 0, 0)
.at(-3, -4, 0)
.box(0, 0, 0, 7, 1, 1, stretch)
.tex(0, 6).box(6, -1, 0, 1, 1, 1, stretch)
.tex(4, 6).box(4, -1, 0, 1, 1, 1, stretch)
.tex(8, 6).box(2, -1, 0, 1, 1, 1, stretch));
}
@Override
public boolean canRender(IModel model, Entity entity) {
return isChristmasDay() || model.isWearing(Wearable.ANTLERS);
@ -73,12 +63,6 @@ public class ChristmasHat extends AbstractGear {
right.roll = -bodySwing;
}
private boolean isChristmasDay() {
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.MONTH) == Calendar.DECEMBER && cal.get(Calendar.DAY_OF_MONTH) == 25;
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;
@ -91,14 +75,13 @@ public class ChristmasHat extends AbstractGear {
@Override
public void renderPart(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
if (tint != 0) {
Color.glColor(tint, 1);
red = Color.r(tint);
green = Color.g(tint);
blue = Color.b(tint);
}
super.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
GL11.glPopAttrib();
left.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
right.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
}

View file

@ -3,29 +3,15 @@ package com.minelittlepony.client.model.gear;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.util.render.Part;
import com.minelittlepony.model.BodyPart;
import com.minelittlepony.model.IModel;
import com.minelittlepony.model.gear.IStackable;
import com.minelittlepony.pony.meta.Wearable;
import java.util.UUID;
public class Muffin extends AbstractGear implements IStackable {
private static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/muffin.png");
@Override
public void init(float yOffset, float stretch) {
this.accept(new Part(this, 0, 0).size(64, 44)
.around(-4, -12, -6)
.box(0, 0, 0, 8, 4, 8, stretch)
.box(3, -1.5F, 3, 2, 2, 2, stretch)
.tex(0, 12).box(1.5F, -1, 1.5F, 5, 1, 5, stretch)
.tex(0, 18).box(2, 1, 1, 4, 7, 6, stretch)
.tex(0, 18).box(1, 1, 2, 6, 7, 4, stretch));
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(Wearable.MUFFIN);

View file

@ -3,33 +3,14 @@ package com.minelittlepony.client.model.gear;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.util.render.Part;
import com.minelittlepony.model.BodyPart;
import com.minelittlepony.model.IModel;
import com.minelittlepony.model.gear.IStackable;
import com.minelittlepony.pony.meta.Wearable;
import java.util.UUID;
public class Stetson extends AbstractGear implements IStackable {
private static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/stetson.png");
@Override
public void init(float yOffset, float stretch) {
accept(rimshot = new Part(this).size(64, 64)
.tex(16, 33).top(-9, yOffset - 4, -12, 16, 17, stretch)
.tex(0, 33).bottom(-9, yOffset - 3.999F, -12, 16, 17, stretch)
.rotate(-0.3F, 0, 0.1F)
.child(new Part(this).size(64, 64)
.tex(0, 0).box(-5, yOffset - 8, -6, 9, 4, 9, stretch)
.tex(0, 13).box(-6, yOffset - 6, -7, 11, 2, 11, stretch)));
rimshot.child()
.around(-9, yOffset - 4, -12)
.tex(0, 27).south(0, yOffset - 6, 0, 16, 6, stretch)
.rotate(0.4F, 0, 0);
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;

View file

@ -2,13 +2,13 @@ package com.minelittlepony.client.render.tileentities.skull;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.components.ModelDeadMau5Ears;
import com.minelittlepony.client.render.RenderPony;
import com.minelittlepony.settings.PonyConfig;
import com.minelittlepony.settings.PonyLevel;
import com.mojang.authlib.GameProfile;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
@ -23,15 +23,6 @@ public class PlayerSkullRenderer extends PonySkull {
return config.ponyLevel.get() != PonyLevel.HUMANS;
}
@Override
public void preRender(boolean transparency) {
GlStateManager.setProfile(GlStateManager.RenderMode.PLAYER_SKIN);
if (!transparency) {
RenderPony.enableModelRenderProfile(false);
}
}
@Override
public Identifier getSkinResource(@Nullable GameProfile profile) {
deadMau5.setVisible(profile != null && "deadmau5".equals(profile.getName()));
@ -50,8 +41,8 @@ public class PlayerSkullRenderer extends PonySkull {
}
@Override
public void render(float animateTicks, float rotation, float scale) {
super.render(animateTicks, rotation, scale);
deadMau5.render(animateTicks, 0, 0, rotation, 0, scale);
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
super.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
deadMau5.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
}

View file

@ -1,5 +1,8 @@
package com.minelittlepony.client.render.tileentities.skull;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import com.minelittlepony.client.model.components.ModelPonyHead;
import com.minelittlepony.client.render.tileentities.skull.PonySkullRenderer.ISkull;
import com.minelittlepony.pony.IPony;
@ -19,7 +22,7 @@ public abstract class PonySkull implements ISkull {
}
@Override
public void render(float animateTicks, float rotation, float scale) {
ponyHead.render(animateTicks, 0, 0, rotation, 0, scale);
public void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha) {
ponyHead.render(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
}
}

View file

@ -8,29 +8,31 @@ import com.minelittlepony.settings.PonyConfig;
import com.mojang.authlib.GameProfile;
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
import net.minecraft.block.AbstractSkullBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.SkullBlock;
import net.minecraft.block.WallSkullBlock;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.Direction;
import org.lwjgl.opengl.GL11;
import java.util.Map;
import javax.annotation.Nullable;
import static com.mojang.blaze3d.platform.GlStateManager.*;
/**
* PonySkullRenderer! It renders ponies as skulls, or something...
*/
public class PonySkullRenderer extends SkullBlockEntityRenderer {
private static final PonySkullRenderer ponyInstance = new PonySkullRenderer();
private static SkullBlockEntityRenderer backup = null;
private static final Map<SkullBlock.SkullType, ISkull> skullMap = Util.create(Maps.newHashMap(), (skullMap) -> {
skullMap.put(SkullBlock.Type.SKELETON, new SkeletonSkullRenderer());
skullMap.put(SkullBlock.Type.WITHER_SKELETON, new WitherSkullRenderer());
@ -39,103 +41,91 @@ public class PonySkullRenderer extends SkullBlockEntityRenderer {
});
/**
* Resolves the games skull renderer to either a specialised pony skull renderer
* or some other skull renderer depending on the ponyskulls state.
*
* Original/Existing renderer is stored to a backup variable as a fallback in case of mods.
* Resolves the games skull renderer to either a special pony skull renderer
* or some other skull renderer depending on the ponyskull's state.
*/
public static void resolve(boolean ponySkulls) {
if (ponySkulls) {
if (!(INSTANCE instanceof PonySkullRenderer)) {
backup = INSTANCE;
BlockEntityRendererRegistry.INSTANCE.register(BlockEntityType.SKULL, ponyInstance);
}
BlockEntityRendererRegistry.INSTANCE.register(BlockEntityType.SKULL, new PonySkullRenderer(BlockEntityRenderDispatcher.INSTANCE));
} else {
if ((INSTANCE instanceof PonySkullRenderer)) {
if (backup == null) {
backup = new SkullBlockEntityRenderer();
}
BlockEntityRendererRegistry.INSTANCE.register(BlockEntityType.SKULL, backup);
BlockEntityRendererRegistry.INSTANCE.register(BlockEntityType.SKULL, new SkullBlockEntityRenderer(BlockEntityRenderDispatcher.INSTANCE));
}
}
public PonySkullRenderer(BlockEntityRenderDispatcher dispatcher) {
super(dispatcher);
}
@Override
public void render(float x, float y, float z, @Nullable Direction facing, float rotation, SkullBlock.SkullType skullType, @Nullable GameProfile profile, int destroyStage, float animateTicks) {
public void render(SkullBlockEntity skullBlockEntity, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, int j) {
float poweredTicks = skullBlockEntity.getTicksPowered(f);
BlockState state = skullBlockEntity.getCachedState();
boolean onWalll = state.getBlock() instanceof WallSkullBlock;
Direction direction = onWalll ? (Direction)state.get(WallSkullBlock.FACING) : null;
float angle = 22.5F * (direction != null ? (2 + direction.getHorizontal()) * 4F : (Integer)state.get(SkullBlock.ROTATION));
render(direction,
angle,
((AbstractSkullBlock)state.getBlock()).getSkullType(),
skullBlockEntity.getOwner(), poweredTicks,
matrixStack, vertexConsumerProvider, i);
}
public static void render(@Nullable Direction direction, float angle,
SkullBlock.SkullType skullType, @Nullable GameProfile profile, float poweredTicks,
MatrixStack stack, VertexConsumerProvider renderContext, int lightUv) {
ISkull skull = skullMap.get(skullType);
if (skull == null || !skull.canRender(MineLittlePony.getInstance().getConfig())) {
if (backup != null) {
backup.render(x, y, z, facing, rotation, skullType, profile, destroyStage, animateTicks);
} else {
super.render(x, y, z, facing, rotation, skullType, profile, destroyStage, animateTicks);
}
SkullBlockEntityRenderer.render(direction, angle, skullType, profile, poweredTicks, stack, renderContext, lightUv);
return;
}
float scale = 0.0625F;
if (destroyStage >= 0) {
bindTexture(DESTROY_STAGE_TEXTURES[destroyStage]);
matrixMode(GL11.GL_TEXTURE);
pushMatrix();
scalef(4, 2, 1);
translatef(scale, scale, scale);
matrixMode(GL11.GL_MODELVIEW);
} else {
Identifier skin = skull.getSkinResource(profile);
skull.bindPony(MineLittlePony.getInstance().getManager().getPony(skin));
bindTexture(skin);
}
stack.push();
pushMatrix();
disableCull();
rotation = handleRotation(x, y, z, facing, rotation);
enableRescaleNormal();
scalef(-1, -1, 1);
enableAlphaTest();
handleRotation(stack, direction);
stack.scale(-1, -1, 1);
skull.preRender(LevitatingItemRenderer.usesTransparency());
skull.render(animateTicks, rotation, scale);
popMatrix();
if (destroyStage >= 0) {
matrixMode(GL11.GL_TEXTURE);
popMatrix();
matrixMode(GL11.GL_MODELVIEW);
}
VertexConsumer vertices = renderContext.getBuffer(RenderLayer.getEntityTranslucent(skin));
skull.render(stack, vertices, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
stack.pop();
}
protected float handleRotation(float x, float y, float z, @Nullable Direction facing, float rotation) {
if (facing == null) {
translatef(x + 0.5F, y, z + 0.5F);
return rotation;
static void handleRotation(MatrixStack stack, @Nullable Direction direction) {
if (direction == null) {
stack.translate(0.5, 0, 0.5);
return;
}
switch (facing) {
switch (direction) {
case NORTH:
translatef(x + 0.5F, y + 0.25F, z + 0.74F);
stack.translate(0.5, 0.25, 0.74);
break;
case SOUTH:
translatef(x + 0.5F, y + 0.25F, z + 0.26F);
return 180;
stack.translate(0.5, 0.25, 0.26);
break;
case WEST:
translatef(x + 0.74F, y + 0.25F, z + 0.5F);
return 270;
stack.translate(0.74, 0.25, 0.5);
break;
case EAST:
default:
translatef(x + 0.26F, y + 0.25F, z + 0.5F);
stack.translate(0.26, 0.25, 0.5);
break;
}
return rotation;
}
/**
@ -147,7 +137,7 @@ public class PonySkullRenderer extends SkullBlockEntityRenderer {
void preRender(boolean transparency);
void render(float animateTicks, float rotation, float scale);
void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha);
boolean canRender(PonyConfig config);

View file

@ -0,0 +1,23 @@
{
"texture": {"w": 16, "h": 8},
"left": {
"center": [-7, 0.5, 0.5],
"offset": [-7, 0, 0],
"cubes": [
{ "from": [3, -4, 0], "size": [7, 1, 1] },
{ "from": [3, -5, 0], "size": [1, 1, 1], "texture": {"u": 0, "v": 2 } },
{ "from": [5, -5, 0], "size": [1, 1, 1], "texture": {"u": 4, "v": 2 } },
{ "from": [7, -5, 0], "size": [1, 1, 1], "texture": {"u": 8, "v": 2 } }
]
},
"left": {
"center": [7, 0.5, 0.5],
"offset": [0, 0, 0],
"cubes": [
{ "from": [-3, -4, 0], "size": [7, 1, 1] },
{ "from": [ 3, -5, 0], "size": [1, 1, 1], "texture": {"u": 0, "v": 2 } },
{ "from": [ 1, -5, 0], "size": [1, 1, 1], "texture": {"u": 4, "v": 2 } },
{ "from": [-1, -5, 0], "size": [1, 1, 1], "texture": {"u": 8, "v": 2 } }
]
}
}

View file

@ -0,0 +1,13 @@
{
"texture": {"w": 64, "h": 44},
"crown": {
"center": [-4, -12, -6],
"cubes": [
{ "from": [0, 0, 0], "size": [8, 4, 8] },
{ "from": [3, -1.5, 3], "size": [2, 2, 2] },
{ "from": [1.5, -1, 1.5], "size": [5, 1, 5], "texture": {"u": 0, "v": 12 } },
{ "from": [2, 1, 1], "size": [4, 7, 6], "texture": {"u": 0, "v": 18 } },
{ "from": [1, 1, 2], "size": [6, 7, 4], "texture": {"u": 0, "v": 18 } }
]
}
}

View file

@ -0,0 +1,41 @@
{
"texture": {"w": 64, "h": 64},
"rim": {
"texture": {"u": 16, "v": 33},
"rotate": [-0.3, 0, 0.1],
"cubes": [
{
"type": "mson:plane",
"face": "up",
"texture": {"u": 16, "v": 33},
"position": [-9, -4, -12], "size": [16, 17]
},
{
"type": "mson:plane",
"face": "down",
"texture": {"u": 0, "v": 33},
"position": [-9, -3.999, -12], "size": [16, 17]
}
],
"children": [
{
"cubes": [
{"from": [-5, -8, -6], "size": [9, 4, 9]},
{"from": [-6, -6, -7], "size": [11, 2, 11], "texture": {"u": 0, "v": 13}}
]
},
{
"center": [-9, -4, -12 ],
"rotate": [0.4, 0, 0],
"cubes": [
{
"type": "mson:plane",
"face": "south",
"texture": {"u": 0, "v": 27},
"position": [0, -6, 0], "size": [16, 6]
}
]
}
]
}
}