mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +00:00
Objects "Matter"
This commit is contained in:
parent
f4191ad984
commit
412c67b47a
@ -40,4 +40,16 @@ public interface Cache<V> {
|
||||
static int keyZ(long key) {
|
||||
return (int) key;
|
||||
}
|
||||
|
||||
static int to1D(int x, int y, int z, int w, int h) {
|
||||
return (z * w * h) + (y * w) + x;
|
||||
}
|
||||
|
||||
static int[] to3D(int idx, int w, int h) {
|
||||
final int z = idx / (w * h);
|
||||
idx -= (z * w * h);
|
||||
final int y = idx / w;
|
||||
final int x = idx % w;
|
||||
return new int[]{x, y, z};
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.engine.stream.interpolation.Interpolated;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.function.*;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.oldnbt.ByteArrayTag;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.Biome;
|
||||
@ -557,6 +558,18 @@ public interface Hunk<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
default Hunk<T> iterateSyncIO(Consumer4IO<Integer, Integer, Integer, T> c) throws IOException {
|
||||
for (int i = 0; i < getWidth(); i++) {
|
||||
for (int j = 0; j < getHeight(); j++) {
|
||||
for (int k = 0; k < getDepth(); k++) {
|
||||
c.accept(i, j, k, get(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
default Hunk<T> iterate(int parallelism, Consumer3<Integer, Integer, Integer> c) {
|
||||
compute3D(parallelism, (x, y, z, h) ->
|
||||
{
|
||||
@ -971,6 +984,26 @@ public interface Hunk<T> {
|
||||
return getRaw(x >= getWidth() ? getWidth() - 1 : x < 0 ? 0 : x, y >= getHeight() ? getHeight() - 1 : y < 0 ? 0 : y, z >= getDepth() ? getDepth() - 1 : z < 0 ? 0 : z);
|
||||
}
|
||||
|
||||
default BlockPosition getCenter()
|
||||
{
|
||||
return new BlockPosition(getCenterX(), getCenterY(), getCenterZ());
|
||||
}
|
||||
|
||||
default int getCenterX()
|
||||
{
|
||||
return Math.round(getWidth() / 2);
|
||||
}
|
||||
|
||||
default int getCenterY()
|
||||
{
|
||||
return Math.round(getHeight() / 2);
|
||||
}
|
||||
|
||||
default int getCenterZ()
|
||||
{
|
||||
return Math.round(getDepth() / 2);
|
||||
}
|
||||
|
||||
default void fill(T t) {
|
||||
set(0, 0, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1, t);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
package com.volmit.iris.engine.hunk.storage;
|
||||
|
||||
import com.volmit.iris.engine.cache.Cache;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@ -47,7 +48,7 @@ public class ArrayHunk<T> extends StorageHunk<T> implements Hunk<T> {
|
||||
}
|
||||
|
||||
private int index(int x, int y, int z) {
|
||||
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
|
||||
return Cache.to1D(x, y, z, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
24
src/main/java/com/volmit/iris/engine/object/IrisMatter.java
Normal file
24
src/main/java/com/volmit/iris/engine/object/IrisMatter.java
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.engine.object;
|
||||
|
||||
// Because Red Matter is too weak
|
||||
public class IrisMatter {
|
||||
|
||||
}
|
245
src/main/java/com/volmit/iris/engine/object/matter/Matter.java
Normal file
245
src/main/java/com/volmit/iris/engine/object/matter/Matter.java
Normal 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.engine.object.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;
|
||||
}
|
||||
}
|
@ -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.engine.object.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));
|
||||
}
|
||||
}
|
@ -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.engine.object.matter;
|
||||
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.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));
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.engine.object.matter;
|
||||
|
||||
import com.volmit.iris.engine.cache.Cache;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.util.data.Varint;
|
||||
|
||||
import java.io.DataInput;
|
||||
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();
|
||||
MatterHunk<?> mapped = (MatterHunk<?>) this;
|
||||
dos.writeUTF(getType().getCanonicalName());
|
||||
Varint.writeUnsignedVarInt(mapped.getCount(), dos);
|
||||
iterateSyncIO((x,y,z,b) -> {
|
||||
Varint.writeUnsignedVarInt((z * w * h) + (y * w) + x, dos);
|
||||
writeNode(b, dos);
|
||||
});
|
||||
}
|
||||
|
||||
default void read(DataInputStream din) throws IOException
|
||||
{
|
||||
int nodes = Varint.readUnsignedVarInt(din);
|
||||
int w = getWidth();
|
||||
int h = getHeight();
|
||||
int d = getDepth();
|
||||
int[] pos;
|
||||
|
||||
while(nodes-- > 0)
|
||||
{
|
||||
pos = Cache.to3D(Varint.readUnsignedVarInt(din), w, h);
|
||||
setRaw(pos[0], pos[1], pos[2], readNode(din));
|
||||
}
|
||||
}
|
||||
}
|
224
src/main/java/com/volmit/iris/util/data/Varint.java
Normal file
224
src/main/java/com/volmit/iris/util/data/Varint.java
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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.data;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <p>Encodes signed and unsigned values using a common variable-length
|
||||
* scheme, found for example in
|
||||
* <a href="http://code.google.com/apis/protocolbuffers/docs/encoding.html">
|
||||
* Google's Protocol Buffers</a>. It uses fewer bytes to encode smaller values,
|
||||
* but will use slightly more bytes to encode large values.</p>
|
||||
* <p/>
|
||||
* <p>Signed values are further encoded using so-called zig-zag encoding
|
||||
* in order to make them "compatible" with variable-length encoding.</p>
|
||||
*/
|
||||
public final class Varint {
|
||||
|
||||
private Varint() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a value using the variable-length encoding from
|
||||
* <a href="http://code.google.com/apis/protocolbuffers/docs/encoding.html">
|
||||
* Google Protocol Buffers</a>. It uses zig-zag encoding to efficiently
|
||||
* encode signed values. If values are known to be nonnegative,
|
||||
* {@link #writeUnsignedVarLong(long, DataOutput)} should be used.
|
||||
*
|
||||
* @param value value to encode
|
||||
* @param out to write bytes to
|
||||
* @throws IOException if {@link DataOutput} throws {@link IOException}
|
||||
*/
|
||||
public static void writeSignedVarLong(long value, DataOutput out) throws IOException {
|
||||
// Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types
|
||||
writeUnsignedVarLong((value << 1) ^ (value >> 63), out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a value using the variable-length encoding from
|
||||
* <a href="http://code.google.com/apis/protocolbuffers/docs/encoding.html">
|
||||
* Google Protocol Buffers</a>. Zig-zag is not used, so input must not be negative.
|
||||
* If values can be negative, use {@link #writeSignedVarLong(long, DataOutput)}
|
||||
* instead. This method treats negative input as like a large unsigned value.
|
||||
*
|
||||
* @param value value to encode
|
||||
* @param out to write bytes to
|
||||
* @throws IOException if {@link DataOutput} throws {@link IOException}
|
||||
*/
|
||||
public static void writeUnsignedVarLong(long value, DataOutput out) throws IOException {
|
||||
while ((value & 0xFFFFFFFFFFFFFF80L) != 0L) {
|
||||
out.writeByte(((int) value & 0x7F) | 0x80);
|
||||
value >>>= 7;
|
||||
}
|
||||
out.writeByte((int) value & 0x7F);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #writeSignedVarLong(long, DataOutput)
|
||||
*/
|
||||
public static void writeSignedVarInt(int value, DataOutput out) throws IOException {
|
||||
// Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types
|
||||
writeUnsignedVarInt((value << 1) ^ (value >> 31), out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #writeUnsignedVarLong(long, DataOutput)
|
||||
*/
|
||||
public static void writeUnsignedVarInt(int value, DataOutput out) throws IOException {
|
||||
while ((value & 0xFFFFFF80) != 0L) {
|
||||
out.writeByte((value & 0x7F) | 0x80);
|
||||
value >>>= 7;
|
||||
}
|
||||
out.writeByte(value & 0x7F);
|
||||
}
|
||||
|
||||
public static byte[] writeSignedVarInt(int value) {
|
||||
// Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types
|
||||
return writeUnsignedVarInt((value << 1) ^ (value >> 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #writeUnsignedVarLong(long, DataOutput)
|
||||
* <p/>
|
||||
* This one does not use streams and is much faster.
|
||||
* Makes a single object each time, and that object is a primitive array.
|
||||
*/
|
||||
public static byte[] writeUnsignedVarInt(int value) {
|
||||
byte[] byteArrayList = new byte[10];
|
||||
int i = 0;
|
||||
while ((value & 0xFFFFFF80) != 0L) {
|
||||
byteArrayList[i++] = ((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
}
|
||||
byteArrayList[i] = ((byte) (value & 0x7F));
|
||||
byte[] out = new byte[i + 1];
|
||||
for (; i >= 0; i--) {
|
||||
out[i] = byteArrayList[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in to read bytes from
|
||||
* @return decode value
|
||||
* @throws IOException if {@link DataInput} throws {@link IOException}
|
||||
* @throws IllegalArgumentException if variable-length value does not terminate
|
||||
* after 9 bytes have been read
|
||||
* @see #writeSignedVarLong(long, DataOutput)
|
||||
*/
|
||||
public static long readSignedVarLong(DataInput in) throws IOException {
|
||||
long raw = readUnsignedVarLong(in);
|
||||
// This undoes the trick in writeSignedVarLong()
|
||||
long temp = (((raw << 63) >> 63) ^ raw) >> 1;
|
||||
// This extra step lets us deal with the largest signed values by treating
|
||||
// negative results from read unsigned methods as like unsigned values
|
||||
// Must re-flip the top bit if the original read value had it set.
|
||||
return temp ^ (raw & (1L << 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in to read bytes from
|
||||
* @return decode value
|
||||
* @throws IOException if {@link DataInput} throws {@link IOException}
|
||||
* @throws IllegalArgumentException if variable-length value does not terminate
|
||||
* after 9 bytes have been read
|
||||
* @see #writeUnsignedVarLong(long, DataOutput)
|
||||
*/
|
||||
public static long readUnsignedVarLong(DataInput in) throws IOException {
|
||||
long value = 0L;
|
||||
int i = 0;
|
||||
long b;
|
||||
while (((b = in.readByte()) & 0x80L) != 0) {
|
||||
value |= (b & 0x7F) << i;
|
||||
i += 7;
|
||||
if (i > 63) {
|
||||
throw new IllegalArgumentException("Variable length quantity is too long");
|
||||
}
|
||||
}
|
||||
return value | (b << i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if variable-length value does not terminate
|
||||
* after 5 bytes have been read
|
||||
* @throws IOException if {@link DataInput} throws {@link IOException}
|
||||
* @see #readSignedVarLong(DataInput)
|
||||
*/
|
||||
public static int readSignedVarInt(DataInput in) throws IOException {
|
||||
int raw = readUnsignedVarInt(in);
|
||||
// This undoes the trick in writeSignedVarInt()
|
||||
int temp = (((raw << 31) >> 31) ^ raw) >> 1;
|
||||
// This extra step lets us deal with the largest signed values by treating
|
||||
// negative results from read unsigned methods as like unsigned values.
|
||||
// Must re-flip the top bit if the original read value had it set.
|
||||
return temp ^ (raw & (1 << 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if variable-length value does not terminate
|
||||
* after 5 bytes have been read
|
||||
* @throws IOException if {@link DataInput} throws {@link IOException}
|
||||
* @see #readUnsignedVarLong(DataInput)
|
||||
*/
|
||||
public static int readUnsignedVarInt(DataInput in) throws IOException {
|
||||
int value = 0;
|
||||
int i = 0;
|
||||
int b;
|
||||
while (((b = in.readByte()) & 0x80) != 0) {
|
||||
value |= (b & 0x7F) << i;
|
||||
i += 7;
|
||||
if (i > 35) {
|
||||
throw new IllegalArgumentException("Variable length quantity is too long");
|
||||
}
|
||||
}
|
||||
return value | (b << i);
|
||||
}
|
||||
|
||||
public static int readSignedVarInt(byte[] bytes) {
|
||||
int raw = readUnsignedVarInt(bytes);
|
||||
// This undoes the trick in writeSignedVarInt()
|
||||
int temp = (((raw << 31) >> 31) ^ raw) >> 1;
|
||||
// This extra step lets us deal with the largest signed values by treating
|
||||
// negative results from read unsigned methods as like unsigned values.
|
||||
// Must re-flip the top bit if the original read value had it set.
|
||||
return temp ^ (raw & (1 << 31));
|
||||
}
|
||||
|
||||
public static int readUnsignedVarInt(byte[] bytes) {
|
||||
int value = 0;
|
||||
int i = 0;
|
||||
byte rb = Byte.MIN_VALUE;
|
||||
for (byte b : bytes) {
|
||||
rb = b;
|
||||
if ((b & 0x80) == 0) {
|
||||
break;
|
||||
}
|
||||
value |= (b & 0x7f) << i;
|
||||
i += 7;
|
||||
if (i > 35) {
|
||||
throw new IllegalArgumentException("Variable length quantity is too long");
|
||||
}
|
||||
}
|
||||
return value | (rb << i);
|
||||
}
|
||||
|
||||
}
|
26
src/main/java/com/volmit/iris/util/function/Consumer4IO.java
Normal file
26
src/main/java/com/volmit/iris/util/function/Consumer4IO.java
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Consumer4IO<A, B, C, D> {
|
||||
void accept(A a, B b, C c, D d) throws IOException;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user