001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package net.tridentsdk.server.data.item;
018
019import java.nio.charset.StandardCharsets;
020import java.util.Base64;
021import java.util.List;
022
023import com.google.common.collect.Lists;
024import com.google.gson.Gson;
025import com.google.gson.GsonBuilder;
026import com.google.gson.JsonObject;
027
028import net.tridentsdk.meta.item.SkullMeta;
029import net.tridentsdk.meta.item.SkullTexture;
030import net.tridentsdk.meta.nbt.NBTField;
031import net.tridentsdk.meta.nbt.NBTSerializable;
032import net.tridentsdk.meta.nbt.TagType;
033
034public class SkullMetaImpl extends ItemMetaImpl implements SkullMeta {
035    protected static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
036
037    @NBTField(name = "SkullOwner", type = TagType.COMPOUND)
038    protected SkullOwnerData data;
039
040    @Override
041    public String owner() {
042        return data == null ? null : data.name;
043    }
044
045    @Override
046    public void setOwner(String name) {
047        if (data == null) {
048            data = new SkullOwnerData();
049        }
050        data.name = name;
051    }
052
053    @Override
054    public List<SkullTexture> textures() {
055        List<SkullTexture> textures = Lists.newArrayListWithCapacity(data.properties.textures.size());
056        data.properties.textures.forEach(t -> textures.add(t));
057        return textures;
058    }
059
060    protected static class SkullOwnerData implements NBTSerializable {
061        @NBTField(name = "Name", type = TagType.STRING)
062        String name;
063
064        @NBTField(name = "Id", type = TagType.STRING)
065        String id;
066
067        @NBTField(name = "Properties", type = TagType.COMPOUND)
068        SkullOwnerDataProperties properties;
069    }
070
071    protected static class SkullOwnerDataProperties implements NBTSerializable {
072        @NBTField(name = "textures", type = TagType.LIST)
073        List<SkullOwnerDataTexture> textures;
074    }
075
076    protected static class SkullOwnerDataTexture implements SkullTexture, NBTSerializable {
077        @NBTField(name = "Value", type = TagType.STRING, required = true)
078        String value;
079
080        @NBTField(name = "Signature", type = TagType.STRING)
081        String signature;
082
083        String jsonString;
084        JsonObject json;
085
086        long jsonTimestamp;
087        boolean jsonIsPublic;
088        String jsonProfileId;
089        String jsonProfileName;
090        String jsonSkinUrl;
091        String jsonCapeUrl;
092
093        @Override
094        public void process() {
095            this.jsonString = new String(Base64.getDecoder().decode(value), StandardCharsets.ISO_8859_1);
096
097            this.json = gson.fromJson(jsonString, JsonObject.class);
098
099            this.jsonTimestamp = json.get("timestamp").getAsLong();
100            this.jsonProfileId = json.get("profileId").getAsString();
101            this.jsonProfileName = json.get("profileName").getAsString();
102            this.jsonIsPublic = json.get("isPublic").getAsBoolean();
103
104            JsonObject texObj = json.getAsJsonObject("textures");
105            JsonObject skinObj = texObj.getAsJsonObject("SKIN");
106            JsonObject capeObj = texObj.getAsJsonObject("CAPE");
107
108            this.jsonSkinUrl = skinObj == null ? null : skinObj.get("url").getAsString();
109            this.jsonCapeUrl = capeObj == null ? null : capeObj.get("url").getAsString();
110        }
111
112        public JsonObject jsonObject() {
113            return json;
114        }
115
116        @Override
117        public long timestamp() {
118            return jsonTimestamp;
119        }
120
121        @Override
122        public String profileId() {
123            return jsonProfileId;
124        }
125
126        @Override
127        public String profileName() {
128            return jsonProfileName;
129        }
130
131        @Override
132        public boolean isPublic() {
133            return jsonIsPublic;
134        }
135
136        @Override
137        public String skinUrl() {
138            return jsonSkinUrl;
139        }
140
141        @Override
142        public String capeUrl() {
143            return jsonCapeUrl;
144        }
145    }
146}