예제 #1
0
  /**
   * Set the behavior of the current editing component to display the specified lines of formatted
   * text when the client hovers over the text.
   *
   * <p>Tooltips do not inherit display characteristics, such as color and styles, from the message
   * component on which they are applied.
   *
   * @param lines The lines of formatted text which will be displayed to the client upon hovering.
   * @return This builder instance.
   */
  public FancyMessage formattedTooltip(FancyMessage... lines) {
    if (lines.length < 1) {
      onHover(null, null); // Clear tooltip
      return this;
    }

    FancyMessage result = new FancyMessage();
    result.messageParts
        .clear(); // Remove the one existing text component that exists by default, which
                  // destabilizes the object

    for (int i = 0; i < lines.length; i++) {
      try {
        for (MessagePart component : lines[i]) {
          if (component.clickActionData != null && component.clickActionName != null) {
            throw new IllegalArgumentException("The tooltip text cannot have click data.");
          } else if (component.hoverActionData != null && component.hoverActionName != null) {
            throw new IllegalArgumentException("The tooltip text cannot have a tooltip.");
          }
          if (component.hasText()) {
            result.messageParts.add(component.clone());
          }
        }
        if (i != lines.length - 1) {
          result.messageParts.add(new MessagePart(rawText("\n")));
        }
      } catch (CloneNotSupportedException e) {
        Bukkit.getLogger().log(Level.WARNING, "Failed to clone object", e);
        return this;
      }
    }
    return formattedTooltip(
        result.messageParts.isEmpty() ? null : result); // Throws NPE if size is 0, intended
  }
예제 #2
0
 @Override
 public void writeJson(JsonWriter writer) throws IOException {
   if (messageParts.size() == 1) {
     latest().writeJson(writer);
   } else {
     writer.beginObject().name("text").value("").name("extra").beginArray();
     for (final MessagePart part : this) {
       part.writeJson(writer);
     }
     writer.endArray().endObject();
   }
 }
예제 #3
0
 @Override
 @SuppressWarnings("unchecked")
 public MessagePart clone() throws CloneNotSupportedException {
   MessagePart obj = (MessagePart) super.clone();
   obj.styles = (ArrayList<ChatColor>) this.styles.clone();
   if (this.hoverActionData instanceof JsonString) {
     obj.hoverActionData = new JsonString(((JsonString) this.hoverActionData).getValue());
   } else if (this.hoverActionData instanceof FancyMessage) {
     obj.hoverActionData = ((FancyMessage) this.hoverActionData).clone();
   }
   obj.translationReplacements =
       (ArrayList<JsonRepresentedObject>) this.translationReplacements.clone();
   return obj;
 }
예제 #4
0
 @SuppressWarnings("unchecked")
 public static MessagePart deserialize(Map<String, Object> serialized) {
   MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
   part.styles = (ArrayList<ChatColor>) serialized.get("styles");
   part.color = ChatColor.getByChar(serialized.get("color").toString());
   part.hoverActionName = (String) serialized.get("hoverActionName");
   part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
   part.clickActionName = (String) serialized.get("clickActionName");
   part.clickActionData = (String) serialized.get("clickActionData");
   part.insertionData = (String) serialized.get("insertion");
   part.translationReplacements =
       (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
   return part;
 }
예제 #5
0
 /**
  * Deserializes a fancy message from its JSON representation. This JSON representation is of the
  * format of that returned by {@link #toJSONString()}, and is compatible with vanilla inputs.
  *
  * @param json The JSON string which represents a fancy message.
  * @return A {@code FancyMessage} representing the parameterized JSON message.
  */
 public static FancyMessage deserialize(String json) {
   JsonObject serialized = _stringParser.parse(json).getAsJsonObject();
   JsonArray extra = serialized.getAsJsonArray("extra"); // Get the extra component
   FancyMessage returnVal = new FancyMessage();
   returnVal.messageParts.clear();
   for (JsonElement mPrt : extra) {
     MessagePart component = new MessagePart();
     JsonObject messagePart = mPrt.getAsJsonObject();
     for (Map.Entry<String, JsonElement> entry : messagePart.entrySet()) {
       // Deserialize text
       if (TextualComponent.isTextKey(entry.getKey())) {
         // The map mimics the YAML serialization, which has a "key" field and one or more "value"
         // fields
         Map<String, Object> serializedMapForm =
             new HashMap<
                 String, Object>(); // Must be object due to Bukkit serializer API compliance
         serializedMapForm.put("key", entry.getKey());
         if (entry.getValue().isJsonPrimitive()) {
           // Assume string
           serializedMapForm.put("value", entry.getValue().getAsString());
         } else {
           // Composite object, but we assume each element is a string
           for (Map.Entry<String, JsonElement> compositeNestedElement :
               entry.getValue().getAsJsonObject().entrySet()) {
             serializedMapForm.put(
                 "value." + compositeNestedElement.getKey(),
                 compositeNestedElement.getValue().getAsString());
           }
         }
         component.text = TextualComponent.deserialize(serializedMapForm);
       } else if (MessagePart.stylesToNames.inverse().containsKey(entry.getKey())) {
         if (entry.getValue().getAsBoolean()) {
           component.styles.add(MessagePart.stylesToNames.inverse().get(entry.getKey()));
         }
       } else if (entry.getKey().equals("color")) {
         component.color = ChatColor.valueOf(entry.getValue().getAsString().toUpperCase());
       } else if (entry.getKey().equals("clickEvent")) {
         JsonObject object = entry.getValue().getAsJsonObject();
         component.clickActionName = object.get("action").getAsString();
         component.clickActionData = object.get("value").getAsString();
       } else if (entry.getKey().equals("hoverEvent")) {
         JsonObject object = entry.getValue().getAsJsonObject();
         component.hoverActionName = object.get("action").getAsString();
         if (object.get("value").isJsonPrimitive()) {
           // Assume string
           component.hoverActionData = new JsonString(object.get("value").getAsString());
         } else {
           // Assume composite type
           // The only composite type we currently store is another FancyMessage
           // Therefore, recursion time!
           component.hoverActionData =
               deserialize(
                   object
                       .get("value")
                       .toString() /* This should properly serialize the JSON object as a JSON string */);
         }
       } else if (entry.getKey().equals("insertion")) {
         component.insertionData = entry.getValue().getAsString();
       } else if (entry.getKey().equals("with")) {
         for (JsonElement object : entry.getValue().getAsJsonArray()) {
           if (object.isJsonPrimitive()) {
             component.translationReplacements.add(new JsonString(object.getAsString()));
           } else {
             // Only composite type stored in this array is - again - FancyMessages
             // Recurse within this function to parse this as a translation replacement
             component.translationReplacements.add(deserialize(object.toString()));
           }
         }
       }
     }
     returnVal.messageParts.add(component);
   }
   return returnVal;
 }
예제 #6
0
 private void onHover(final String name, final JsonRepresentedObject data) {
   final MessagePart latest = latest();
   latest.hoverActionName = name;
   latest.hoverActionData = data;
   dirty = true;
 }
예제 #7
0
 private void onClick(final String name, final String data) {
   final MessagePart latest = latest();
   latest.clickActionName = name;
   latest.clickActionData = data;
   dirty = true;
 }
예제 #8
0
 /**
  * Sets the text of the current editing component to a value.
  *
  * @param text The new text of the current editing component.
  * @return This builder instance.
  */
 public FancyMessage text(TextualComponent text) {
   MessagePart latest = latest();
   latest.text = text;
   dirty = true;
   return this;
 }
예제 #9
0
 /**
  * Sets the text of the current editing component to a value.
  *
  * @param text The new text of the current editing component.
  * @return This builder instance.
  */
 public FancyMessage text(String text) {
   MessagePart latest = latest();
   latest.text = rawText(text);
   dirty = true;
   return this;
 }