001/*
002 * Copyright (c) 2022-2024 See AUTHORS file.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 */
017
018package com.github.tommyettinger.kryo.gand;
019
020import com.esotericsoftware.kryo.Kryo;
021import com.esotericsoftware.kryo.Serializer;
022import com.esotericsoftware.kryo.io.Input;
023import com.esotericsoftware.kryo.io.Output;
024import com.github.tommyettinger.gand.GradientGridI2;
025import com.github.tommyettinger.gand.Path;
026import com.github.tommyettinger.gand.ds.IntList;
027import com.github.tommyettinger.gand.utils.GridMetric;
028import com.github.tommyettinger.gdcrux.PointI2;
029
030/**
031 * Kryo {@link Serializer} for gand {@link GradientGridI2}s.
032 * You must have {@link PointI2} registered to use this as the serializer for GradientGridI2,
033 * such as with {@link com.github.tommyettinger.kryo.gdcrux.PointI2Serializer}.
034 */
035public class GradientGridI2Serializer extends Serializer<GradientGridI2> {
036
037    public GradientGridI2Serializer() {
038        setAcceptsNull(false);
039    }
040
041    @Override
042    public void write(final Kryo kryo, final Output output, final GradientGridI2 data) {
043        output.writeVarInt(data.getMeasurement().ordinal(), true);
044        int width = data.getWidth();
045        int height = data.getHeight();
046        if(data.physicalMap != null && data.gradientMap != null) {
047            output.writeVarInt(width, true);
048            output.writeVarInt(height, true);
049        }
050        else {
051            output.writeVarInt(0, true);
052            output.writeVarInt(0, true);
053        }
054        output.writeVarInt(data.getBlockingRequirement(), true);
055
056        IntList goals = data.getGoals();
057        output.writeVarInt(goals.size(), true);
058        for (int i = 0, n = goals.size(); i < n; i++) {
059            output.writeVarInt(goals.get(i), true);
060        }
061
062        Path<PointI2> path = data.path;
063        output.writeVarInt(path.size(), true);
064        for (int i = 0, n = path.size(); i < n; i++) {
065            output.writeVarInt(path.get(i).xi(), true);
066            output.writeVarInt(path.get(i).yi(), true);
067        }
068
069        if(data.physicalMap != null && data.gradientMap != null) {
070            for (int x = 0; x < width; x++) {
071                for (int y = 0; y < height; y++) {
072                    output.writeFloat(data.physicalMap[x][y]);
073                }
074            }
075            for (int x = 0; x < width; x++) {
076                for (int y = 0; y < height; y++) {
077                    output.writeFloat(data.gradientMap[x][y]);
078                }
079            }
080        }
081    }
082
083    /*
084    @Override
085    public void read(Json json, JsonValue jsonData) {
086        GridMetric m = GridMetric.ALL[Math.min(Math.max(jsonData.getInt("m", 2), 0), 2)];
087        setMeasurement(m);
088        int w = Math.max(0, jsonData.getInt("w"));
089        float[][] pm = new float[w][];
090
091        setBlockingRequirement(jsonData.getInt("b"));
092        goals.clear();
093        goals.addAll(jsonData.get("g").asIntArray());
094        path.clear();
095        int[] p = jsonData.get("p").asIntArray();
096        for (int i = 0; i < p.length; i += 2) {
097            path.add(acquire(p[i], p[i+1]));
098        }
099
100        JsonValue a2 = jsonData.get("pm");
101        if(a2 == null || a2.isNull()){
102            initialized = false;
103            physicalMap = null;
104            gradientMap = null;
105            return;
106        }
107        int x = 0;
108        for(JsonValue sub = a2.child; sub != null; sub = sub.next){
109            pm[x] = sub.asFloatArray();
110            ++x;
111        }
112        initialize(pm);
113        a2 = jsonData.get("gm");
114        if(a2 == null || a2.isNull()){
115            initialized = false;
116            physicalMap = null;
117            gradientMap = null;
118            return;
119        }
120        x = 0;
121        for(JsonValue sub = a2.child; sub != null; sub = sub.next){
122            gradientMap[x] = sub.asFloatArray();
123            ++x;
124        }
125    }
126*/
127
128    @Override
129    public GradientGridI2 read(final Kryo kryo, final Input input, final Class<? extends GradientGridI2> dataClass) {
130        GridMetric m = GridMetric.ALL[Math.min(Math.max(input.readVarInt(true), 0), 2)];
131        int width = input.readVarInt(true);
132        int height = input.readVarInt(true);
133        int blocking = input.readVarInt(true);
134        int goalSize = input.readVarInt(true);
135        IntList goals = new IntList(goalSize);
136        for (int i = 0; i < goalSize; i++) {
137            goals.add(input.readVarInt(true));
138        }
139        int pathSize = input.readVarInt(true);
140        Path<PointI2> path = new Path<>(pathSize);
141        for (int i = 0; i < pathSize; i++) {
142            path.add(new PointI2(input.readVarInt(true), input.readVarInt(true)));
143        }
144        GradientGridI2 gg;
145        if(width > 0 && height > 0) {
146            float[][] level = new float[width][height];
147            for (int x = 0; x < width; x++) {
148                for (int y = 0; y < height; y++) {
149                    level[x][y] = input.readFloat();
150                }
151            }
152            gg = new GradientGridI2(level, m);
153            for (int x = 0; x < width; x++) {
154                for (int y = 0; y < height; y++) {
155                    gg.gradientMap[x][y] = input.readFloat();
156                }
157            }
158        }
159        else {
160            gg = new GradientGridI2();
161            gg.setMeasurement(m);
162        }
163        gg.setBlockingRequirement(blocking);
164        gg.goals.addAll(goals);
165        gg.path.addAll(path);
166
167        return gg;
168    }
169
170    @Override
171    public GradientGridI2 copy(Kryo kryo, GradientGridI2 original) {
172        GradientGridI2 gg;
173        if(original.physicalMap != null && original.gradientMap != null) {
174            gg = new GradientGridI2(original.physicalMap, original.getMeasurement());
175            for (int x = 0, w = gg.getWidth(), h = gg.getHeight(); x < w; x++) {
176                System.arraycopy(original.gradientMap[x], 0, gg.physicalMap[x], 0, h);
177            }
178        } else {
179          gg = new GradientGridI2();
180          gg.setMeasurement(original.getMeasurement());
181        }
182        gg.setBlockingRequirement(original.getBlockingRequirement());
183        gg.goals.addAll(original.goals);
184        gg.path.addAll(original.path);
185        return gg;
186    }
187}