Matter apis

This commit is contained in:
Daniel Mills
2021-08-04 19:27:28 -04:00
parent 6e369ea787
commit f2b301cb17
207 changed files with 1381 additions and 2386 deletions

View File

@@ -0,0 +1,245 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
import com.volmit.iris.util.data.Varint;
import com.volmit.iris.util.math.BlockPosition;
import java.io.*;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
/**
* When Red Matter isn't enough
*
* UVI width
* UVI height
* UVI depth
* UVI sliceCount
* UTF author
* UVL createdAt
* UVI version
* UTF sliceType (canonical class name)
* UVI nodeCount (for each slice)
* UVI position [(z * w * h) + (y * w) + x]
* ??? nodeData
*
*/
public interface Matter {
int VERSION = 1;
/**
* Get the header information
* @return the header info
*/
MatterHeader getHeader();
/**
* Get the width of this matter
* @return the width
*/
int getWidth();
/**
* Get the height of this matter
* @return the height
*/
int getHeight();
/**
* Get the depth of this matter
* @return the depth
*/
int getDepth();
/**
* Get the center of this matter
* @return the center
*/
default BlockPosition getCenter()
{
return new BlockPosition(getCenterX(), getCenterY(), getCenterZ());
}
/**
* Create a slice from the given type
* @param type the type class
* @param matter the matter this slice will go into (size provider)
* @param <T> the type
* @return the slice (or null if not supported)
*/
<T> MatterSlice<T> createSlice(Class<T> type, Matter matter);
/**
* Get the size of this matter
* @return the size
*/
default BlockPosition getSize()
{
return new BlockPosition(getWidth(), getHeight(), getDepth());
}
/**
* Get the center X of this matter
* @return the center X
*/
default int getCenterX()
{
return Math.round(getWidth() / 2);
}
/**
* Get the center Y of this matter
* @return the center Y
*/
default int getCenterY()
{
return Math.round(getHeight() / 2);
}
/**
* Get the center Z of this matter
* @return the center Z
*/
default int getCenterZ()
{
return Math.round(getDepth() / 2);
}
/**
* Return the slice for the given type
* @param t the type class
* @param <T> the type
* @return the slice or null
*/
default <T> MatterSlice<T> getSlice(Class<T> t)
{
return (MatterSlice<T>) getSliceMap().get(t);
}
/**
* Delete the slice for the given type
* @param c the type class
* @param <T> the type
* @return the deleted slice, or null if it diddn't exist
*/
default <T> MatterSlice<T> deleteSlice(Class<?> c)
{
return (MatterSlice<T>) getSliceMap().remove(c);
}
/**
* Put a given slice type
* @param c the slice type class
* @param slice the slice to assign to the type
* @param <T> the slice type
* @return the overwritten slice if there was an existing slice of that type
*/
default <T> MatterSlice<T> putSlice(Class<?> c, MatterSlice<T> slice)
{
return (MatterSlice<T>) getSliceMap().put(c, slice);
}
/**
* Check if a slice exists for a given type
* @param c the slice class type
* @return true if it exists
*/
default boolean hasSlice(Class<?> c)
{
return getSlice(c) != null;
}
/**
* Remove all slices
*/
default void clearSlices()
{
getSliceMap().clear();
}
/**
* Get the set backing the slice map keys (slice types)
* @return the slice types
*/
default Set<Class<?>> getSliceTypes()
{
return getSliceMap().keySet();
}
/**
* Get all slices
* @return the real slice map
*/
Map<Class<?>, MatterSlice<?>> getSliceMap();
/**
* Writes the data to the output stream. The data will be flushed to the provided output
* stream however the provided stream will NOT BE CLOSED, so be sure to actually close it
* @param out the output stream
* @throws IOException shit happens yo
*/
default void write(OutputStream out) throws IOException
{
DataOutputStream dos = new DataOutputStream(out);
// Write size
Varint.writeUnsignedVarInt(getWidth(), dos);
Varint.writeUnsignedVarInt(getHeight(), dos);
Varint.writeUnsignedVarInt(getDepth(), dos);
dos.writeByte(getSliceTypes().size() + Byte.MIN_VALUE);
getHeader().write(dos);
for(Class<?> i : getSliceTypes())
{
getSlice(i).write(dos);
}
dos.flush();
}
/**
* Reads the input stream into a matter object using a matter factory.
* Does not close the input stream. Be a man, close it yourself.
* @param in the input stream
* @param matterFactory the matter factory (size) -> new MatterImpl(size);
* @return the matter object
* @throws IOException shit happens yo
*/
static Matter read(InputStream in, Function<BlockPosition, Matter> matterFactory) throws IOException, ClassNotFoundException {
DataInputStream din = new DataInputStream(in);
// Read size into new matter object
Matter matter = matterFactory.apply(new BlockPosition(
Varint.readUnsignedVarInt(din),
Varint.readUnsignedVarInt(din),
Varint.readUnsignedVarInt(din)));
int sliceCount = din.readByte() - Byte.MIN_VALUE;
matter.getHeader().read(din);
while(sliceCount-- > 0)
{
Class<?> type = Class.forName(din.readUTF());
MatterSlice<?> slice = matter.createSlice(type, matter);
slice.read(din);
matter.putSlice(type, slice);
}
return matter;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
import com.volmit.iris.util.data.Varint;
import com.volmit.iris.util.math.M;
import lombok.Data;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@Data
public class MatterHeader {
private String author = "anonymous";
private long createdAt = M.ms();
private int version = Matter.VERSION;
public void write(DataOutputStream out) throws IOException
{
out.writeUTF(author);
Varint.writeUnsignedVarLong(createdAt, out);
Varint.writeUnsignedVarInt(version, out);
}
public void read(DataInputStream din) throws IOException
{
setAuthor(din.readUTF());
setCreatedAt(Varint.readUnsignedVarLong(din));
setVersion(Varint.readUnsignedVarInt(din));
}
}

View File

@@ -0,0 +1,83 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.storage.StorageHunk;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.function.Consumer4;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Map;
@SuppressWarnings({"DefaultAnnotationParam", "Lombok"})
@Data
@EqualsAndHashCode(callSuper = false)
public class MatterHunk<T> extends StorageHunk<T> implements Hunk<T> {
private final Map<Integer, T> data;
public MatterHunk(int w, int h, int d) {
super(w, h, d);
data = new KMap<>();
}
public int getCount()
{
return data.size();
}
@Override
public void setRaw(int x, int y, int z, T t) {
if (t == null) {
data.remove(index(x, y, z));
return;
}
data.put(index(x, y, z), t);
}
private Integer index(int x, int y, int z) {
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
@Override
public synchronized Hunk<T> iterateSync(Consumer4<Integer, Integer, Integer, T> c) {
int idx, z;
for (Map.Entry<Integer, T> g : data.entrySet()) {
idx = g.getKey();
z = idx / (getWidth() * getHeight());
idx -= (z * getWidth() * getHeight());
c.accept(idx % getWidth(), idx / getWidth(), z, g.getValue());
}
return this;
}
@Override
public void empty(T b) {
data.clear();
}
@Override
public T getRaw(int x, int y, int z) {
return data.get(index(x, y, z));
}
}

View File

@@ -0,0 +1,71 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.DataPalette;
import com.volmit.iris.util.data.IOAdapter;
import com.volmit.iris.util.data.NibbleDataPalette;
import com.volmit.iris.util.data.Varint;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class MatterPalette<T> implements IOAdapter<T> {
private final MatterSlice<T> slice;
private final DataPalette<T> palette;
public MatterPalette(MatterSlice<T> slice)
{
this.slice = slice;
palette = new DataPalette<T>();
}
public MatterPalette(MatterSlice<T> slice, DataInputStream din) throws IOException {
this.slice = slice;
palette = DataPalette.getPalette(this, din);
}
public void writeNode(T t, DataOutputStream dos) throws IOException {
Varint.writeUnsignedVarInt(palette.getIndex(t), dos);
}
public T readNode(DataInputStream din) throws IOException {
return palette.get(Varint.readUnsignedVarInt(din));
}
public void writePalette(DataOutputStream dos) throws IOException {
palette.write(this, dos);
}
@Override
public void write(T t, DataOutputStream dos) throws IOException {
slice.writeNode(t, dos);
}
@Override
public T read(DataInputStream din) throws IOException {
return slice.readNode(din);
}
public void assign(T b) {
palette.getIndex(b);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.data.Varint;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public interface MatterSlice<T> extends Hunk<T>
{
Class<T> getType();
void writeNode(T b, DataOutputStream dos) throws IOException;
T readNode(DataInputStream din) throws IOException;
default void write(DataOutputStream dos) throws IOException
{
int w = getWidth();
int h = getHeight();
dos.writeUTF(getType().getCanonicalName());
MatterPalette<T> palette = new MatterPalette<T>(this);
iterateSync((x,y,z,b) -> palette.assign(b));
palette.writePalette(dos);
Varint.writeUnsignedVarInt(((MatterHunk<?>) this).getCount(), dos);
iterateSyncIO((x,y,z,b) -> {
Varint.writeUnsignedVarInt((z * w * h) + (y * w) + x, dos);
palette.writeNode(b, dos);
});
}
default void read(DataInputStream din) throws IOException
{
int w = getWidth();
int h = getHeight();
// canonical is read in parent
MatterPalette<T> palette = new MatterPalette<T>(this, din);
int nodes = Varint.readUnsignedVarInt(din);
int[] pos;
while(nodes-- > 0)
{
pos = Cache.to3D(Varint.readUnsignedVarInt(din), w, h);
setRaw(pos[0], pos[1], pos[2], palette.readNode(din));
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import org.bukkit.block.data.BlockData;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class BlockMatter extends RawMatter<BlockData>
{
public BlockMatter(int width, int height, int depth) {
super(width, height, depth, BlockData.class);
}
@Override
public void writeNode(BlockData b, DataOutputStream dos) throws IOException {
NBTUtil.write(NBTWorld.getCompound(b), dos, false);
}
@Override
public BlockData readNode(DataInputStream din) throws IOException {
return NBTWorld.getBlockData((CompoundTag) NBTUtil.read(din, false).getTag());
}
}

View File

@@ -0,0 +1,40 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class BooleanMatter extends RawMatter<Boolean>
{
public BooleanMatter(int width, int height, int depth) {
super(width, height, depth, Boolean.class);
}
@Override
public void writeNode(Boolean b, DataOutputStream dos) throws IOException {
dos.writeBoolean(b);
}
@Override
public Boolean readNode(DataInputStream din) throws IOException {
return din.readBoolean();
}
}

View File

@@ -0,0 +1,28 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.nbt.tag.CompoundTag;
public class CompoundMatter extends NBTMatter<CompoundTag>
{
public CompoundMatter(int width, int height, int depth) {
super(width, height, depth, CompoundTag.class);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.data.Varint;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class IntMatter extends RawMatter<Integer>
{
public IntMatter(int width, int height, int depth) {
super(width, height, depth, Integer.class);
}
@Override
public void writeNode(Integer b, DataOutputStream dos) throws IOException {
Varint.writeSignedVarInt(b, dos);
}
@Override
public Integer readNode(DataInputStream din) throws IOException {
return Varint.readSignedVarInt(din);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.data.Varint;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class LongMatter extends RawMatter<Long>
{
public LongMatter(int width, int height, int depth) {
super(width, height, depth, Long.class);
}
@Override
public void writeNode(Long b, DataOutputStream dos) throws IOException {
Varint.writeSignedVarLong(b, dos);
}
@Override
public Long readNode(DataInputStream din) throws IOException {
return Varint.readSignedVarLong(din);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.nbt.tag.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class NBTMatter<T extends Tag<?>> extends RawMatter<T>
{
public NBTMatter(int width, int height, int depth, Class<T> c) {
super(width, height, depth, c);
}
@Override
public void writeNode(T b, DataOutputStream dos) throws IOException {
NBTUtil.write(b, dos, false);
}
@Override
public T readNode(DataInputStream din) throws IOException {
return (T) NBTUtil.read(din, false).getTag();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.matter.MatterHunk;
import com.volmit.iris.util.matter.MatterSlice;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public abstract class RawMatter<T> extends MatterHunk<T> implements MatterSlice<T> {
@Getter
private final Class<T> type;
public RawMatter(int width, int height, int depth, Class<T> type)
{
super(width, height, depth);
this.type = type;
}
@Override
public void setRaw(int x, int y, int z, T t) {
}
@Override
public T getRaw(int x, int y, int z) {
return null;
}
@Override
public abstract void writeNode(T b, DataOutputStream dos) throws IOException;
@Override
public abstract T readNode(DataInputStream din) throws IOException;
}

View File

@@ -0,0 +1,42 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.matter.MatterSlice;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class StringMatter extends RawMatter<String>
{
public StringMatter(int width, int height, int depth) {
super(width, height, depth, String.class);
}
@Override
public void writeNode(String b, DataOutputStream dos) throws IOException {
dos.writeUTF(b);
}
@Override
public String readNode(DataInputStream din) throws IOException {
return din.readUTF();
}
}