codechicken.lib.model.Quad

Here are the examples of the java api codechicken.lib.model.Quad taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

10 Examples 7

18 Source : BakedQuadVertexBuilder.java
with GNU Lesser General Public License v2.1
from TheCBProject

/**
 * Similar to {@link BakedQuadBuilder} except receives its data from a vanilla {@link IVertexConsumer}.
 * <p>
 * Created by covers1624 on 4/23/20.
 */
public clreplaced BakedQuadVertexBuilder implements IVertexBuilder, ISpriteAwareVertexBuilder {

    private final List<Quad> quadList = new ArrayList<>();

    private final int glMode;

    private final int vSize;

    private Quad current;

    private int vertex;

    public BakedQuadVertexBuilder() {
        this(GL11.GL_QUADS);
    }

    public BakedQuadVertexBuilder(int glMode) {
        if (glMode != GL11.GL_QUADS && glMode != GL11.GL_TRIANGLES) {
            throw new IllegalArgumentException("Only GL_QUADS and GL_TRIANGLES supported. Got: " + glMode);
        }
        this.glMode = glMode;
        vSize = glMode == GL11.GL_QUADS ? 4 : 3;
    }

    public void reset() {
        quadList.clear();
        current = null;
        vertex = 0;
    }

    @Override
    public void sprite(TextureAtlreplacedprite sprite) {
        checkNewQuad();
        current.setTexture(sprite);
    }

    @Override
    public IVertexBuilder pos(double x, double y, double z) {
        checkNewQuad();
        current.vertices[vertex].vec[0] = (float) x;
        current.vertices[vertex].vec[1] = (float) y;
        current.vertices[vertex].vec[2] = (float) z;
        return this;
    }

    @Override
    public IVertexBuilder color(int red, int green, int blue, int alpha) {
        checkNewQuad();
        current.vertices[vertex].color[0] = red / 255F;
        current.vertices[vertex].color[1] = green / 255F;
        current.vertices[vertex].color[2] = blue / 255F;
        current.vertices[vertex].color[3] = alpha / 255F;
        return this;
    }

    @Override
    public IVertexBuilder tex(float u, float v) {
        checkNewQuad();
        current.vertices[vertex].uv[0] = u;
        current.vertices[vertex].uv[1] = v;
        return this;
    }

    @Override
    public IVertexBuilder overlay(int u, int v) {
        checkNewQuad();
        current.vertices[vertex].overlay[0] = u / (float) 0xF0;
        current.vertices[vertex].overlay[1] = v / (float) 0xF0;
        return this;
    }

    @Override
    public IVertexBuilder lightmap(int u, int v) {
        checkNewQuad();
        current.vertices[vertex].lightmap[0] = u / (float) 0xF0;
        current.vertices[vertex].lightmap[1] = v / (float) 0xF0;
        return this;
    }

    @Override
    public IVertexBuilder normal(float x, float y, float z) {
        checkNewQuad();
        current.vertices[vertex].normal[0] = x;
        current.vertices[vertex].normal[1] = y;
        current.vertices[vertex].normal[2] = z;
        return this;
    }

    @Override
    public void endVertex() {
        vertex++;
        if (vertex == vSize) {
            if (glMode == GL11.GL_TRIANGLES) {
                // Quadulate.
                for (int e = 0; e < current.format.elementCount; e++) {
                    System.arraycopy(current.vertices[2].raw[e], 0, current.vertices[3].raw[e], 0, 4);
                }
            }
            if (current.sprite == null) {
                throw new IllegalStateException("Sprite not set.");
            }
            quadList.add(current);
            current = null;
            vertex = 0;
        }
    }

    public List<BakedQuad> bake() {
        if (current != null) {
            throw new IllegalStateException("Not finished building.");
        }
        return quadList.stream().map(Quad::bake).collect(Collectors.toList());
    }

    private void checkNewQuad() {
        if (current == null) {
            current = new Quad(CachedFormat.lookup(DefaultVertexFormats.BLOCK));
        }
    }
}

18 Source : BakedVertexSource.java
with GNU Lesser General Public License v2.1
from TheCBProject

/**
 * Created by covers1624 on 12/5/20.
 */
public clreplaced BakedVertexSource implements IVertexSource, ISmartVertexConsumer {

    private static final ThreadLocal<BakedVertexSource> instances = ThreadLocal.withInitial(BakedVertexSource::new);

    private final Quad unpacker = new Quad(CachedFormat.lookup(DefaultVertexFormats.BLOCK));

    private int vertexIndex = -1;

    private Vertex5[] vertices = new Vertex5[0];

    private Object[][] attributes = new Object[0][0];

    private TextureAtlreplacedprite[] sprites = new TextureAtlreplacedprite[0];

    private BakedVertexSource() {
        ensureAttr(AttributeKeyRegistry.numAttributes() - 1);
        // Ensure enough space for a full standard block model.
        ensureSpace(24);
    }

    public static BakedVertexSource instance() {
        return instances.get();
    }

    @Override
    public Vertex5[] getVertices() {
        return vertices;
    }

    @Override
    public <T> T getAttributes(AttributeKey<T> attr) {
        ensureAttr(attr.attributeKeyIndex);
        return unsafeCast(attributes[attr.attributeKeyIndex]);
    }

    @Override
    public boolean hasAttribute(AttributeKey<?> attr) {
        return attr == NormalAttribute.attributeKey || attr == ColourAttribute.attributeKey || attr == LightCoordAttribute.attributeKey;
    }

    @Override
    public void prepareVertex(CCRenderState ccrs) {
    }

    public void reset() {
        vertexIndex = -1;
    }

    public int availableVertices() {
        return vertexIndex + 1;
    }

    private void onFull() {
        if (vertexIndex == -1) {
            vertexIndex = 0;
        }
        ensureSpace(availableVertices() + 4);
        for (int i = 0; i < 4; i++) {
            int v = vertexIndex++;
            Quad.Vertex vertex = unpacker.vertices[i];
            Vertex5 vertex5 = vertices[v];
            vertex5.vec.set(vertex.vec);
            vertex5.uv.set(vertex.uv);
            Vector3 normal = getAttr(NormalAttribute.attributeKey)[v];
            normal.set(vertex.normal);
            getAttr(LightCoordAttribute.attributeKey)[v].compute(vertex5.vec, normal);
            getAttr(ColourAttribute.attributeKey)[v] = Colour.packRGBA(vertex.color);
        }
    }

    private void ensureAttr(int aIdx) {
        if (attributes.length <= aIdx) {
            attributes = Arrays.copyOf(attributes, aIdx + 1);
        }
    }

    // Expands array storage.
    private void ensureSpace(int numVertices) {
        // If we don't have enough, or are full, expand.
        if (vertices.length <= numVertices) {
            int fillStart = vertexIndex == -1 ? 0 : vertexIndex;
            vertices = Arrays.copyOf(vertices, numVertices);
            fill(vertices, fillStart, numVertices, Vertex5::new);
            for (int aIdx = 0; aIdx < attributes.length; aIdx++) {
                Object[] attr = attributes[aIdx];
                AttributeKey<?> key = AttributeKeyRegistry.getAttributeKey(aIdx);
                if (attr == null) {
                    attr = unsafeCast(key.newArray(numVertices));
                } else {
                    attr = Arrays.copyOf(attr, numVertices);
                }
                attributes[aIdx] = attr;
                // Fill non primitive vertex attributes with new things.
                if (key == NormalAttribute.attributeKey) {
                    fill(attr, fillStart, numVertices, Vector3::new);
                } else if (key == LightCoordAttribute.attributeKey) {
                    fill(attr, fillStart, numVertices, LC::new);
                }
            }
            sprites = Arrays.copyOf(sprites, numVertices);
        }
    }

    private <T> T getAttr(AttributeKey<T> key) {
        return unsafeCast(attributes[key.attributeKeyIndex]);
    }

    @Override
    public void put(Quad quad) {
        unpacker.put(quad);
        onFull();
    }

    @Override
    public void put(int element, float... data) {
        unpacker.put(element, data);
        if (unpacker.full) {
            onFull();
        }
    }

    // @formatter:off
    @Override
    public VertexFormat getVertexFormat() {
        return DefaultVertexFormats.BLOCK;
    }

    @Override
    public void setQuadTint(int tint) {
        unpacker.setQuadTint(tint);
    }

    @Override
    public void setQuadOrientation(Direction orientation) {
        unpacker.setQuadOrientation(orientation);
    }

    @Override
    public void setApplyDiffuseLighting(boolean diffuse) {
        unpacker.setApplyDiffuseLighting(diffuse);
    }

    @Override
    public void setTexture(TextureAtlreplacedprite texture) {
        unpacker.setTexture(texture);
    }

    // @formatter:on
    private static void fill(Object[] arr, int start, int end, Supplier<Object> supplier) {
        for (int i = start; i < end; i++) {
            arr[i] = supplier.get();
        }
    }
}

18 Source : QuadTransformer.java
with GNU Lesser General Public License v2.1
from TheCBProject

/**
 * Base clreplaced for a simple QuadTransformer.
 * Operates on BakedQuads.
 * QuadTransformers can be piped into each other at no performance penalty.
 *
 * @author covers1624
 */
public abstract clreplaced QuadTransformer implements IVertexConsumer, ISmartVertexConsumer, IPipelineConsumer {

    protected final Quad quad;

    protected CachedFormat format;

    protected IVertexConsumer consumer;

    /**
     * Used for the BakedPipeline.
     */
    protected QuadTransformer() {
        quad = new Quad();
    }

    public QuadTransformer(IVertexConsumer consumer) {
        this(consumer.getVertexFormat(), consumer);
    }

    public QuadTransformer(VertexFormat format, IVertexConsumer consumer) {
        this(CachedFormat.lookup(format), consumer);
    }

    public QuadTransformer(CachedFormat format, IVertexConsumer consumer) {
        this.format = format;
        this.consumer = consumer;
        quad = new Quad(format);
    }

    @Override
    @OverridingMethodsMustInvokeSuper
    public void reset(CachedFormat format) {
        this.format = format;
        quad.reset(format);
    }

    @Override
    public void setParent(IVertexConsumer parent) {
        consumer = parent;
    }

    @Override
    @OverridingMethodsMustInvokeSuper
    public void setInputQuad(Quad quad) {
        if (consumer instanceof IPipelineConsumer) {
            ((IPipelineConsumer) consumer).setInputQuad(quad);
        }
    }

    // @formatter:off
    @Override
    public VertexFormat getVertexFormat() {
        return format.format;
    }

    @Override
    public void setQuadTint(int tint) {
        quad.setQuadTint(tint);
    }

    @Override
    public void setQuadOrientation(Direction orientation) {
        quad.setQuadOrientation(orientation);
    }

    @Override
    public void setApplyDiffuseLighting(boolean diffuse) {
        quad.setApplyDiffuseLighting(diffuse);
    }

    @Override
    public void setTexture(TextureAtlreplacedprite texture) {
        quad.setTexture(texture);
    }

    // @formatter:on
    @Override
    public void put(int element, float... data) {
        quad.put(element, data);
        if (quad.full) {
            onFull();
        }
    }

    @Override
    public void put(Quad quad) {
        this.quad.put(quad);
        onFull();
    }

    /**
     * Called to transform the vertices.
     *
     * @return If the transformer should pipe the quad.
     */
    public abstract boolean transform();

    public void onFull() {
        if (transform()) {
            quad.pipe(consumer);
        }
    }

    // Should be small enough.
    private final static double EPSILON = 0.00001;

    public static boolean epsComp(float a, float b) {
        if (a == b) {
            return true;
        } else {
            return Math.abs(a - b) < EPSILON;
        }
    }
}

18 Source : QuadTransformer.java
with GNU Lesser General Public License v2.1
from TheCBProject

@Override
public void put(Quad quad) {
    this.quad.put(quad);
    onFull();
}

18 Source : BakedPipeline.java
with GNU Lesser General Public License v2.1
from TheCBProject

/**
 * The BakedPipeline!
 * Basically this allows us to efficiently transform a BakedQuad,
 * the Pipeline has Elements, each element has a name, state and a transformer,
 * you can enable and disable elements easily, you can also grab the underlying
 * transformer for the element if you need to set its state before rendering.
 * <p>
 * The BakedPipeline is final once created, you cannot add or remove elements,
 * you should not need to add or remove them runtime, enable and disable exist.
 * <p>
 * You must use the Builder clreplaced to construct a BakedPipeline, see {@link #builder}
 * <p>
 * Transformers run on a mutable state inside each transformer, allowing for easy reuse.
 * It is recommended to store your pipeline inside a ThreadLocal because 'minecraft'.
 * <p>
 * Each Transformer should be smart enough to expand itself for each newly sized VertexFormat it comes across,
 * meaning that the internal states for the transformers can be safely shared across VertexFormats, this reduces
 * array creations, and generally makes the system as efficient as it is.
 * <p>
 * To use the system:
 * Grab any elements you need to set state data on first, using {@link #getElement(String, Clreplaced)}
 * transformers should NOT clear their state on pipeline Reset's so set any global data on elements now.
 * replaceduming you are looping over a set of quads to transform, next you need to {@link #reset} the pipeline,
 * Now you should disable / enable any optional elements that are needed, NOTE: Element states are reset when resetting
 * the pipeline.
 * Now you will need to call {@link #prepare(IVertexConsumer)} on the pipeline, here you will preplaced your collector,
 * usually this is some form of {@link BakedQuadBuilder}, or {@link Quad} can also pack things.
 * Now final step, simply pipe the quad you want to transform INTO the pipeline 'quad.pipe(pipeline)'
 * And that's it! hell, Pipe a pipeline into each other for all i care, the system is efficient enough that there
 * would be no performance penalty for doing so.
 *
 * @author covers1624
 */
public clreplaced BakedPipeline implements ISmartVertexConsumer {

    private final PipelineElement<?>[] elements;

    private final Map<String, PipelineElement<?>> nameLookup;

    private IPipelineConsumer first;

    private final Quad unpacker = new Quad();

    private BakedPipeline(PipelineElement<?>[] elements) {
        this.elements = elements;
        nameLookup = Arrays.stream(elements).collect(Collectors.toMap(e -> e.name, e -> e));
    }

    /**
     * Used to create a BakedPipeline.
     *
     * @return The builder.
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Used to reset the pipeline for the next quad.
     * MUST be called between quads.
     *
     * @param format The format.
     */
    public void reset(VertexFormat format) {
        reset(CachedFormat.lookup(format));
    }

    /**
     * Used to reset the pipeline for the next quad.
     * MUST be called between quads.
     *
     * @param format The format.
     */
    public void reset(CachedFormat format) {
        unpacker.reset(format);
        for (PipelineElement<?> element : elements) {
            element.reset(format);
        }
        first = null;
    }

    /**
     * Get an element from the pipeline.
     *
     * @param name  The name of the element.
     * @param clazz The Clreplaced of the element, used to safe cast.
     * @return The element.
     */
    public <T extends IPipelineConsumer> T getElement(String name, Clreplaced<T> clazz) {
        PipelineElement<?> element = nameLookup.get(name);
        if (element != null) {
            if (!clazz.isreplacedignableFrom(element.consumer.getClreplaced())) {
                throw new IllegalArgumentException("Element with name " + name + " is not replacedignable from reference clreplaced.");
            }
            return clazz.cast(element.consumer);
        }
        throw new IllegalArgumentException("Element with name " + name + " does not exist.");
    }

    /**
     * Used to enable an element on the pipeline with the specified name.
     *
     * @param name The elements name.
     */
    public void enableElement(String name) {
        setElementState(name, true);
    }

    /**
     * Used to disable an element on the pipeline with the specified name.
     *
     * @param name The elements name.
     */
    public void disableElement(String name) {
        setElementState(name, false);
    }

    /**
     * Used to set the state of an element on the pipeline.
     *
     * @param name    The name of the element.
     * @param enabled The state to set it to.
     */
    public void setElementState(String name, boolean enabled) {
        PipelineElement<?> element = nameLookup.get(name);
        if (element != null) {
            element.isEnabled = enabled;
            return;
        }
        throw new IllegalArgumentException("Element with name " + name + " does not exist.");
    }

    /**
     * Call when you are ready to use the pipeline.
     * This builds the internal state of the Elements getting things ready to transform.
     *
     * @param collector The IVertexConsumer that should collect the transformed quad.
     */
    public void prepare(IVertexConsumer collector) {
        IPipelineConsumer next = null;
        for (PipelineElement<?> element : elements) {
            if (element.isEnabled) {
                if (first == null) {
                    first = element.consumer;
                } else {
                    next.setParent(element.consumer);
                }
                next = element.consumer;
            }
        }
        next.setParent(collector);
    }

    @Override
    public VertexFormat getVertexFormat() {
        check();
        return first.getVertexFormat();
    }

    @Override
    public void setQuadTint(int tint) {
        check();
        unpacker.setQuadTint(tint);
    }

    @Override
    public void setQuadOrientation(Direction orientation) {
        check();
        unpacker.setQuadOrientation(orientation);
    }

    @Override
    public void setApplyDiffuseLighting(boolean diffuse) {
        check();
        unpacker.setApplyDiffuseLighting(diffuse);
    }

    @Override
    public void setTexture(TextureAtlreplacedprite texture) {
        check();
        unpacker.setTexture(texture);
    }

    @Override
    public void put(int element, float... data) {
        check();
        unpacker.put(element, data);
        if (unpacker.full) {
            onFull();
        }
    }

    @Override
    public void put(Quad quad) {
        check();
        unpacker.put(quad);
    }

    private void check() {
        if (first == null) {
            throw new IllegalStateException("Pipeline used before prepare was called.");
        }
    }

    private void onFull() {
        first.setInputQuad(unpacker);
        first.put(unpacker);
    }

    /**
     * Internal clreplaced, used to hold a PipelineElement's state.
     */
    public static clreplaced PipelineElement<T extends IPipelineConsumer> {

        public String name;

        public boolean defaultState;

        public T consumer;

        public boolean isEnabled;

        public void reset(CachedFormat format) {
            isEnabled = defaultState;
            consumer.setParent(null);
            consumer.reset(format);
        }
    }

    /**
     * The builder replacedociated with the BakedPipeline.
     * You must create a BakedPipeline with this,
     * once created a pipeline cannot be modified,
     * modifying should not be needed as you can enable
     * and disable elements with ease.
     */
    public static clreplaced Builder {

        private final LinkedList<PipelineElement<?>> elements = new LinkedList<>();

        /**
         * Inserts an element to the front of the list, Useful if you have a more complex system
         * and each system need to be independent from each other, but this element must be first.
         *
         * @param name    The name to identify this element, used as an identifier when setting state, and retrieving the
         *                element.
         * @param factory The factory used to create the Transformer.
         * @return The same builder.
         */
        public Builder addFirst(String name, IPipelineElementFactory<?> factory) {
            return addFirst(name, factory, true);
        }

        /**
         * Inserts an element to the front of the list, Useful if you have a more complex system
         * and each system need to be independent from each other, but this element must be first.
         *
         * @param name         The name to identify this element, used as an identifier when setting state, and retrieving the
         *                     element.
         * @param factory      The factory used to create the Transformer.
         * @param defaultState The default state for this element.
         * @return The same builder.
         */
        public Builder addFirst(String name, IPipelineElementFactory<?> factory, boolean defaultState) {
            return addFirst(name, factory, defaultState, e -> {
            });
        }

        /**
         * Inserts an element to the front of the list, Useful if you have a more complex system
         * and each system need to be independent from each other, but this element must be first.
         *
         * @param name           The name to identify this element, used as an identifier when setting state, and retrieving the
         *                       element.
         * @param factory        The factory used to create the Transformer.
         * @param defaultState   The default state for this element.
         * @param defaultsSetter A callback used to set any defaults on the transformer.
         * @return The same builder.
         */
        public <T extends IPipelineConsumer> Builder addFirst(String name, IPipelineElementFactory<T> factory, boolean defaultState, Consumer<T> defaultsSetter) {
            PipelineElement<T> element = makeElement(name, factory, defaultState);
            defaultsSetter.accept(element.consumer);
            elements.addFirst(element);
            return this;
        }

        /**
         * Adds an element at the end of the transform list, Suitable for 99% of cases.
         *
         * @param name    The name to identify this element, used as an identifier when setting state, and retrieving the
         *                element.
         * @param factory The factory used to create the Transformer.
         * @return The same builder.
         */
        public Builder addElement(String name, IPipelineElementFactory<?> factory) {
            return addElement(name, factory, true);
        }

        /**
         * Adds an element at the end of the transform list, Suitable for 99% of cases.
         *
         * @param name         The name to identify this element, used as an identifier when setting state, and retrieving the
         *                     element.
         * @param factory      The factory used to create the Transformer.
         * @param defaultState The default state for this element.
         * @return The same builder.
         */
        public Builder addElement(String name, IPipelineElementFactory<?> factory, boolean defaultState) {
            return addElement(name, factory, defaultState, e -> {
            });
        }

        /**
         * Adds an element at the end of the transform list, Suitable for 99% of cases.
         *
         * @param name           The name to identify this element, used as an identifier when setting state, and retrieving the
         *                       element.
         * @param factory        The factory used to create the Transformer.
         * @param defaultState   The default state for this element.
         * @param defaultsSetter A callback used to set any defaults on the transformer.
         * @return The same builder.
         */
        public <T extends IPipelineConsumer> Builder addElement(String name, IPipelineElementFactory<T> factory, boolean defaultState, Consumer<T> defaultsSetter) {
            PipelineElement<T> element = makeElement(name, factory, defaultState);
            defaultsSetter.accept(element.consumer);
            elements.add(element);
            return this;
        }

        // Internal method, used to construct the PipelineElement clreplaced.
        private <T extends IPipelineConsumer> PipelineElement<T> makeElement(String name, IPipelineElementFactory<T> factory, boolean defaultState) {
            if (elements.stream().anyMatch(p -> p.name.equals(name))) {
                throw new IllegalArgumentException("Unable to add element with duplicate name: " + name);
            }
            PipelineElement<T> element = new PipelineElement<>();
            element.name = name;
            element.consumer = factory.create();
            element.defaultState = defaultState;
            return element;
        }

        /**
         * Call this once you are finished to build your BakedPipeline!
         *
         * @return The new Pipeline.
         */
        public BakedPipeline build() {
            return new BakedPipeline(elements.toArray(new PipelineElement[0]));
        }
    }
}

17 Source : BakedVertexSource.java
with GNU Lesser General Public License v2.1
from TheCBProject

@Override
public void put(Quad quad) {
    unpacker.put(quad);
    onFull();
}

17 Source : QuadReInterpolator.java
with GNU Lesser General Public License v2.1
from TheCBProject

/**
 * This transformer Re-Interpolates the Color, UV's and LightMaps.
 * Use this after all transformations that translate vertices in the pipeline.
 * <p>
 * This Transformation can only be used in the BakedPipeline.
 *
 * @author covers1624
 */
public clreplaced QuadReInterpolator extends QuadTransformer {

    public static final IPipelineElementFactory<QuadReInterpolator> FACTORY = QuadReInterpolator::new;

    private final Quad interpCache = new Quad();

    private final InterpHelper interpHelper = new InterpHelper();

    QuadReInterpolator() {
        super();
    }

    @Override
    public void reset(CachedFormat format) {
        super.reset(format);
        interpCache.reset(format);
    }

    @Override
    public void setInputQuad(Quad quad) {
        super.setInputQuad(quad);
        quad.resetInterp(interpHelper, quad.orientation.ordinal() >> 1);
    }

    @Override
    public boolean transform() {
        int s = quad.orientation.ordinal() >> 1;
        if (format.hasColor || format.hasUV || format.hasLightMap) {
            interpCache.copyFrom(quad);
            interpHelper.setup();
            for (Vertex v : quad.vertices) {
                interpHelper.locate(v.dx(s), v.dy(s));
                if (format.hasColor) {
                    v.interpColorFrom(interpHelper, interpCache.vertices);
                }
                if (format.hasUV) {
                    v.interpUVFrom(interpHelper, interpCache.vertices);
                }
                if (format.hasLightMap) {
                    v.interpLightMapFrom(interpHelper, interpCache.vertices);
                }
            }
        }
        return true;
    }
}

17 Source : QuadReInterpolator.java
with GNU Lesser General Public License v2.1
from TheCBProject

@Override
public void setInputQuad(Quad quad) {
    super.setInputQuad(quad);
    quad.resetInterp(interpHelper, quad.orientation.ordinal() >> 1);
}

17 Source : QuadTransformer.java
with GNU Lesser General Public License v2.1
from TheCBProject

@Override
@OverridingMethodsMustInvokeSuper
public void setInputQuad(Quad quad) {
    if (consumer instanceof IPipelineConsumer) {
        ((IPipelineConsumer) consumer).setInputQuad(quad);
    }
}

17 Source : BakedPipeline.java
with GNU Lesser General Public License v2.1
from TheCBProject

@Override
public void put(Quad quad) {
    check();
    unpacker.put(quad);
}