Skip to content

Commit

Permalink
Make places hay bales edible
Browse files Browse the repository at this point in the history
  • Loading branch information
Sollace committed Jan 19, 2024
1 parent d47a1a5 commit f2b817d
Show file tree
Hide file tree
Showing 44 changed files with 1,027 additions and 50 deletions.
1 change: 1 addition & 0 deletions assets/models/hay_bale.bbmodel
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"meta":{"format_version":"4.5","model_format":"java_block","box_uv":false},"name":"hay_bale_bse","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"bottom_south_east","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[8,0,8],"to":[16,8,16],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[0,8,8,16],"texture":0},"east":{"uv":[0,8,8,16],"texture":1},"south":{"uv":[8,8,16,16],"texture":1},"west":{"uv":[8,8,16,16],"texture":0},"up":{"uv":[8,8,16,16],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"523f4164-daa5-4b79-eec7-013710b7ae88"},{"name":"bottom_north_west","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[0,0,0],"to":[8,8,8],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[8,8,16,16],"texture":1},"east":{"uv":[8,8,16,16],"texture":0},"south":{"uv":[0,8,8,16],"texture":0},"west":{"uv":[0,8,8,16],"texture":1},"up":{"uv":[0,0,8,8],"texture":0},"down":{"uv":[0,8,8,16],"texture":0}},"type":"cube","uuid":"1fd288fe-a293-1ca2-a5b7-15d602eb44f6"},{"name":"top_south_east","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[8,8,8],"to":[16,16,16],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,8],"texture":0},"east":{"uv":[0,0,8,8],"texture":1},"south":{"uv":[8,0,16,8],"texture":1},"west":{"uv":[8,0,16,8],"texture":0},"up":{"uv":[8,8,16,16],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"4f48967d-c722-5593-6f77-079ee47d08af"},{"name":"top_north_west","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[0,8,0],"to":[8,16,8],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[8,0,16,8],"texture":1},"east":{"uv":[8,0,16,8],"texture":0},"south":{"uv":[0,0,8,8],"texture":0},"west":{"uv":[0,0,8,8],"texture":1},"up":{"uv":[0,0,8,8],"texture":0},"down":{"uv":[0,8,8,16],"texture":0}},"type":"cube","uuid":"c4356ab3-a7a5-43e5-489a-9ebb52492675"},{"name":"bottom_south_west","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[0,0,8],"to":[8,8,16],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[8,8,16,16],"texture":0},"east":{"uv":[0,8,8,16],"texture":0},"south":{"uv":[0,8,8,16],"texture":1},"west":{"uv":[8,8,16,16],"texture":1},"up":{"uv":[0,8,8,16],"texture":0},"down":{"uv":[0,0,8,8],"texture":0}},"type":"cube","uuid":"d07d02d7-5ab9-0026-b3ed-029701536cf6"},{"name":"bottom_north_east","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[8,0,0],"to":[16,8,8],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[0,8,8,16],"texture":1},"east":{"uv":[8,8,16,16],"texture":1},"south":{"uv":[8,8,16,16],"texture":0},"west":{"uv":[0,8,8,16],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,8,16,16],"texture":0}},"type":"cube","uuid":"d10fb8d4-fe44-ca10-77f0-63b32855f5d6"},{"name":"top_south_west","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[0,8,8],"to":[8,16,16],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[8,0,16,8],"texture":0},"east":{"uv":[0,0,8,8],"texture":0},"south":{"uv":[0,0,8,8],"texture":1},"west":{"uv":[8,0,16,8],"texture":1},"up":{"uv":[0,8,8,16],"texture":0},"down":{"uv":[0,0,8,8],"texture":0}},"type":"cube","uuid":"b9c9d695-4003-c9e6-efbb-9a75c658b47e"},{"name":"top_north_east","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[8,8,0],"to":[16,16,8],"autouv":0,"color":2,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,8],"texture":1},"east":{"uv":[8,0,16,8],"texture":1},"south":{"uv":[8,0,16,8],"texture":0},"west":{"uv":[0,0,8,8],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,8,16,16],"texture":0}},"type":"cube","uuid":"20a14bb3-edf7-1ae1-132e-ef3d56d84f67"}],"outliner":["523f4164-daa5-4b79-eec7-013710b7ae88","4f48967d-c722-5593-6f77-079ee47d08af","d10fb8d4-fe44-ca10-77f0-63b32855f5d6","20a14bb3-edf7-1ae1-132e-ef3d56d84f67","d07d02d7-5ab9-0026-b3ed-029701536cf6","b9c9d695-4003-c9e6-efbb-9a75c658b47e","1fd288fe-a293-1ca2-a5b7-15d602eb44f6","c4356ab3-a7a5-43e5-489a-9ebb52492675"],"textures":[{"path":"/home/sollace/Desktop/hay_block_top.png","name":"hay_block_top.png","folder":"blocks","namespace":"minecraft","id":"top","particle":false,"render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"mode":"bitmap","saved":true,"uuid":"f73f23e2-d591-dd05-db6f-60869e1592c7","relative_path":"../../../../../../../Desktop/hay_block_top.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAVVJREFUOE9tkyFOBEEQRWvckEAyuBWYFSRgCQgk3IgDcAKC4wo4rgBIxBIsJIg1iHVsAgnjhryevE6xTJvd6ar69ev/6ub+thte3yJmXR+c1bqNn++I+V5f/nuMm8Mvd83VRTccHUd8rvrYnbWRwUhafrQVjAJBDw/Gmubuuh3sMt+PWL5HASKY79df4x2xl+eRIeCFgXRBJXh+1sfTog2+ZSQTm/C9tR3R3Fx2AzPzwZkqMtkRpM84VQNpcUkiRTCRetbi9KSPh8dRmz8aMF+3858+oBQJZpPCABFVX/s2rWJuNNHKPFLRAHTVpxgWdFPA3FEm5FUbcwIBmHDcDxhk+opITmGgaHqrrapO1zyC+1H3gE66QDDPTFLeVGjneBFRilNWyirvCXmAolHdRH3O6wttHw06ObuuVQ1y0ua2EXM/cMojSMNzZi5fWX7KWdwppxjjF8NCOiclFu9xAAAAAElFTkSuQmCC"},{"path":"/home/sollace/Desktop/hay_block_side.png","name":"hay_block_side.png","folder":"blocks","namespace":"minecraft","id":"side","particle":true,"render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"mode":"bitmap","saved":true,"uuid":"1cf36f16-9f26-3125-d49c-45217088cbc7","relative_path":"../../../../../../../Desktop/hay_block_side.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAV1JREFUOE+VU7tOQkEUPGtiuAokeCExNIpBK2x9tITK7/EHqCmJv2DlNxhblZqORK2MiVxJBLmEhDVzktkclopt9p7X7OzcWde7bfiL6wMZDsfSalVl8Pwj7U5FXl4zjZn//pxKrV5aixunRXF33SNvGzFwdZmuARymBfnKFgpIIBx0crwrDgz2yytBE05AgYyQe/tYCup/vzs6gBg7l7u/Ofc+8ZJNckkrSSgg5ppNF1IsFTbq6NcrkCJPxAmgbPOMyYDMggaxSBTz6XGilGNAArmH/pnH3QEAVa36EPN9NFNtbN2KugGAAQvEwRiIfQqAASa23QMAqJNyDGivEDNUH8TOs+rjV0JALDoVPqHort9uehTpAZc7GedzqSZ7An8wtj34pm+CE5GE2+yiA7Fjxc5EXgFoUTTR1tYw9AEPsdYOTuQAH419E3xs1qnoh3aBgR20otKRVn2+Vuz/aIRXgq2GkfcAAAAASUVORK5CYII="}]}
113 changes: 113 additions & 0 deletions assets/models/hay_bale.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"textures": {
"top": "blocks/hay_block_top",
"particle": "blocks/hay_block_side",
"side": "blocks/hay_block_side"
},
"elements": [
{
"name": "bottom_south_east",
"from": [8, 0, 8],
"to": [16, 8, 16],
"faces": {
"north": {"uv": [0, 8, 8, 16], "texture": "#top"},
"east": {"uv": [0, 8, 8, 16], "texture": "#side"},
"south": {"uv": [8, 8, 16, 16], "texture": "#side"},
"west": {"uv": [8, 8, 16, 16], "texture": "#top"},
"up": {"uv": [8, 8, 16, 16], "texture": "#top"},
"down": {"uv": [8, 0, 16, 8], "texture": "#top"}
}
},
{
"name": "top_south_east",
"from": [8, 8, 8],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 8, 8], "texture": "#top"},
"east": {"uv": [0, 0, 8, 8], "texture": "#side"},
"south": {"uv": [8, 0, 16, 8], "texture": "#side"},
"west": {"uv": [8, 0, 16, 8], "texture": "#top"},
"up": {"uv": [8, 8, 16, 16], "texture": "#top"},
"down": {"uv": [8, 0, 16, 8], "texture": "#top"}
}
},
{
"name": "bottom_north_east",
"from": [8, 0, 0],
"to": [16, 8, 8],
"faces": {
"north": {"uv": [0, 8, 8, 16], "texture": "#side"},
"east": {"uv": [8, 8, 16, 16], "texture": "#side"},
"south": {"uv": [8, 8, 16, 16], "texture": "#top"},
"west": {"uv": [0, 8, 8, 16], "texture": "#top"},
"up": {"uv": [8, 0, 16, 8], "texture": "#top"},
"down": {"uv": [8, 8, 16, 16], "texture": "#top"}
}
},
{
"name": "top_north_east",
"from": [8, 8, 0],
"to": [16, 16, 8],
"faces": {
"north": {"uv": [0, 0, 8, 8], "texture": "#side"},
"east": {"uv": [8, 0, 16, 8], "texture": "#side"},
"south": {"uv": [8, 0, 16, 8], "texture": "#top"},
"west": {"uv": [0, 0, 8, 8], "texture": "#top"},
"up": {"uv": [8, 0, 16, 8], "texture": "#top"},
"down": {"uv": [8, 8, 16, 16], "texture": "#top"}
}
},
{
"name": "bottom_south_west",
"from": [0, 0, 8],
"to": [8, 8, 16],
"faces": {
"north": {"uv": [8, 8, 16, 16], "texture": "#top"},
"east": {"uv": [0, 8, 8, 16], "texture": "#top"},
"south": {"uv": [0, 8, 8, 16], "texture": "#side"},
"west": {"uv": [8, 8, 16, 16], "texture": "#side"},
"up": {"uv": [0, 8, 8, 16], "texture": "#top"},
"down": {"uv": [0, 0, 8, 8], "texture": "#top"}
}
},
{
"name": "top_south_west",
"from": [0, 8, 8],
"to": [8, 16, 16],
"faces": {
"north": {"uv": [8, 0, 16, 8], "texture": "#top"},
"east": {"uv": [0, 0, 8, 8], "texture": "#top"},
"south": {"uv": [0, 0, 8, 8], "texture": "#side"},
"west": {"uv": [8, 0, 16, 8], "texture": "#side"},
"up": {"uv": [0, 8, 8, 16], "texture": "#top"},
"down": {"uv": [0, 0, 8, 8], "texture": "#top"}
}
},
{
"name": "bottom_north_west",
"from": [0, 0, 0],
"to": [8, 8, 8],
"faces": {
"north": {"uv": [8, 8, 16, 16], "texture": "#side"},
"east": {"uv": [8, 8, 16, 16], "texture": "#top"},
"south": {"uv": [0, 8, 8, 16], "texture": "#top"},
"west": {"uv": [0, 8, 8, 16], "texture": "#side"},
"up": {"uv": [0, 0, 8, 8], "texture": "#top"},
"down": {"uv": [0, 8, 8, 16], "texture": "#top"}
}
},
{
"name": "top_north_west",
"from": [0, 8, 0],
"to": [8, 16, 8],
"faces": {
"north": {"uv": [8, 0, 16, 8], "texture": "#side"},
"east": {"uv": [8, 0, 16, 8], "texture": "#top"},
"south": {"uv": [0, 0, 8, 8], "texture": "#top"},
"west": {"uv": [0, 0, 8, 8], "texture": "#side"},
"up": {"uv": [0, 0, 8, 8], "texture": "#top"},
"down": {"uv": [0, 8, 8, 16], "texture": "#top"}
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Pos;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.block.state.StateUtil;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
Expand All @@ -29,7 +30,6 @@
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.state.property.Property;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
Expand Down Expand Up @@ -233,16 +233,7 @@ public Result checkPattern(World world, BlockPos pos) {
}

public BlockState getResult(World world, BlockPos pos) {
BlockState input = world.getBlockState(pos);
BlockState output = this.output;
for (var property : input.getProperties()) {
output = copyProperty(input, output, property);
}
return output;
}

private <T extends Comparable<T>> BlockState copyProperty(BlockState from, BlockState to, Property<T> property) {
return to.withIfExists(property, from.get(property));
return StateUtil.copyState(world.getBlockState(pos), output);
}

record Result (TransmutationRecipe recipe, Set<BlockPos> matchedLocations) {
Expand Down
214 changes: 214 additions & 0 deletions src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package com.minelittlepony.unicopia.block;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import org.jetbrains.annotations.Nullable;

import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.block.state.StateUtil;
import com.minelittlepony.unicopia.entity.player.Pony;

import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HayBlock;
import net.minecraft.block.ShapeContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.sound.SoundCategory;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;

public class EdibleBlock extends HayBlock {
private static final List<EdibleBlock> REGISTRY = new ArrayList<>();

static final BooleanProperty TOP_NORTH_EAST = BooleanProperty.of("top_north_east");
static final BooleanProperty TOP_NORTH_WEST = BooleanProperty.of("top_north_west");
static final BooleanProperty TOP_SOUTH_EAST = BooleanProperty.of("top_south_east");
static final BooleanProperty TOP_SOUTH_WEST = BooleanProperty.of("top_south_west");

static final BooleanProperty BOTTOM_NORTH_EAST = BooleanProperty.of("bottom_north_east");
static final BooleanProperty BOTTOM_NORTH_WEST = BooleanProperty.of("bottom_north_west");
static final BooleanProperty BOTTOM_SOUTH_EAST = BooleanProperty.of("bottom_south_east");
static final BooleanProperty BOTTOM_SOUTH_WEST = BooleanProperty.of("bottom_south_west");

// [up/down][north/south][west/east]
private static final BooleanProperty[] SEGMENTS = {
BOTTOM_NORTH_WEST,
BOTTOM_NORTH_EAST,
BOTTOM_SOUTH_WEST,
BOTTOM_SOUTH_EAST,
TOP_NORTH_WEST,
TOP_NORTH_EAST,
TOP_SOUTH_WEST,
TOP_SOUTH_EAST
};
private static final VoxelShape[] SHAPES = {
Block.createCuboidShape(0, 0, 0, 8, 8, 8),
Block.createCuboidShape(8, 0, 0, 16, 8, 8),
Block.createCuboidShape(0, 0, 8, 8, 8, 16),
Block.createCuboidShape(8, 0, 8, 16, 8, 16),
Block.createCuboidShape(0, 8, 0, 8, 16, 8),
Block.createCuboidShape(8, 8, 0, 16, 16, 8),
Block.createCuboidShape(0, 8, 8, 8, 16, 16),
Block.createCuboidShape(8, 8, 8, 16, 16, 16)
};
private static final Function<BlockState, VoxelShape> SHAPE_CACHE = Util.memoize(state -> {
@Nullable
VoxelShape shape = null;
for (int i = 0; i < SEGMENTS.length; i++) {
if (state.get(SEGMENTS[i])) {
shape = shape == null ? SHAPES[i] : VoxelShapes.union(shape, SHAPES[i]);
}
}
return shape == null ? VoxelShapes.fullCube() : shape.simplify();
});

static void bootstrap() {
UseBlockCallback.EVENT.register((PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) -> {
if (!Pony.of(player).getSpecies().isEquine()
|| (player.shouldCancelInteraction() && (!player.getMainHandStack().isEmpty() || !player.getOffHandStack().isEmpty()))) {
return ActionResult.PASS;
}

BlockPos pos = hitResult.getBlockPos();
BlockState state = world.getBlockState(pos);

for (EdibleBlock edibleBlock : REGISTRY) {
Block match = edibleBlock.getBaseBlock();
if (match != Blocks.AIR && state.isOf(match)) {
ActionResult result = StateUtil.copyState(state, edibleBlock.getDefaultState()).onUse(world, player, hand, hitResult);

if (result.isAccepted()) {
return result;
}
}
}

return ActionResult.PASS;
});
}

private final Identifier baseBlock;

public EdibleBlock(Identifier baseBlock, boolean register) {
super(Settings.copy(Blocks.HAY_BLOCK));
for (BooleanProperty segment : SEGMENTS) {
setDefaultState(getDefaultState().with(segment, true));
}
this.baseBlock = baseBlock;
if (register) {
REGISTRY.add(this);
FlammableBlockRegistry.getDefaultInstance().add(this, 60, 20);
}
}

public Block getBaseBlock() {
return Registries.BLOCK.get(baseBlock);
}

@Override
public String getTranslationKey() {
return getBaseBlock().getTranslationKey();
}

@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(SEGMENTS);
}

@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return SHAPE_CACHE.apply(state);
}

@Override
@Deprecated
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (player.isSpectator()) {
return ActionResult.FAIL;
}

ItemStack stack = player.getStackInHand(hand);
if (stack.isOf(Items.WHEAT)) {
BooleanProperty segment = getHitCorner(hit, 1);

if (!state.get(segment)) {
stack.decrement(1);
if (!world.isClient) {
state = state.with(segment, true);
if (SHAPE_CACHE.apply(state) == VoxelShapes.fullCube()) {
state = StateUtil.copyState(state, getBaseBlock().getDefaultState());
}
world.setBlockState(pos, state);
}
world.playSound(player, pos, this.getSoundGroup(state).getPlaceSound(), SoundCategory.BLOCKS);

return ActionResult.SUCCESS;
}

return ActionResult.FAIL;
}

BooleanProperty corner = getHitCorner(hit, -1);

if (!state.get(corner)) {
return ActionResult.PASS;
}

if (!(player.isCreative() || player.getHungerManager().isNotFull()) || !player.isSneaking()) {
return ActionResult.FAIL;
}

if (!world.isClient) {
state = state.with(corner, false);
if (SHAPE_CACHE.apply(state) == VoxelShapes.fullCube()) {
world.removeBlock(pos, false);
} else {
world.setBlockState(pos, state);
}
}
player.playSound(USounds.Vanilla.ENTITY_GENERIC_EAT, 1, 1);
if (world.random.nextInt(10) == 0) {
player.playSound(USounds.Vanilla.ENTITY_PLAYER_BURP, 1, player.getSoundPitch());
}
player.getHungerManager().add(4, 2.3F);
return ActionResult.SUCCESS;
}

static BooleanProperty getHitCorner(BlockHitResult hit, int direction) {
Vec3d pos = hit.getPos().add(Vec3d.of(hit.getSide().getVector()).multiply(direction * 0.001F));

BlockPos bPos = hit.getBlockPos();

return SEGMENTS[
(4 * getIndex(pos.y, bPos.getY()))
+ (2 * getIndex(pos.z, bPos.getZ()))
+ (1 - getIndex(pos.x, bPos.getX()))
];
}

static int getIndex(double axisHit, int tile) {
axisHit = Math.abs(axisHit);
tile = Math.abs(tile);
return axisHit - ((int)axisHit) > 0.5 ? 1 : 0;
}
}
Loading

0 comments on commit f2b817d

Please sign in to comment.