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 */ 017 018package net.tridentsdk.server.entity; 019 020import net.tridentsdk.base.Position; 021import net.tridentsdk.concurrent.SelectableThreadPool; 022import net.tridentsdk.entity.Entity; 023import net.tridentsdk.registry.Registered; 024import net.tridentsdk.server.concurrent.ThreadsHandler; 025import net.tridentsdk.util.TridentLogger; 026 027import java.lang.reflect.Constructor; 028import java.lang.reflect.InvocationTargetException; 029import java.util.UUID; 030 031/** 032 * Builds an entity from initializer components and auto-spawns safely 033 * 034 * <p>This is not thread safe. Do not share across methods, and you should be good.</p> 035 * 036 * @author The TridentSDK Team 037 */ 038public final class EntityBuilder { 039 private UUID uuid = UUID.randomUUID(); 040 private Position spawn = Position.create(Registered.worlds().get("world"), 0, 0, 0); 041 private SelectableThreadPool executor; 042 private boolean god; 043 private Entity passenger; 044 private String displayName; 045 private boolean silent; 046 047 private EntityBuilder() { 048 } 049 050 public static EntityBuilder create() { 051 return new EntityBuilder(); 052 } 053 054 public EntityBuilder uuid(UUID uuid) { 055 this.uuid = uuid; 056 return this; 057 } 058 059 public EntityBuilder spawn(Position spawn) { 060 this.spawn = spawn; 061 return this; 062 } 063 064 public EntityBuilder executor(SelectableThreadPool executor) { 065 this.executor = executor; 066 return this; 067 } 068 069 public EntityBuilder god(boolean god) { 070 this.god = god; 071 return this; 072 } 073 074 public EntityBuilder passenger(Entity passenger) { 075 this.passenger = passenger; 076 return this; 077 } 078 079 public EntityBuilder name(String displayName) { 080 this.displayName = displayName; 081 return this; 082 } 083 084 public EntityBuilder silent(boolean silent) { 085 this.silent = silent; 086 return this; 087 } 088 089 // TODO in reality these should be impl classes?? 090 public <T extends Entity> T build(Class<T> entityType) { 091 TridentEntity entity = null; 092 try { 093 Constructor<? extends TridentEntity> constructor = (Constructor<? extends TridentEntity>) 094 entityType.getConstructor(UUID.class, Position.class); 095 entity = constructor.newInstance(uuid, spawn); 096 entity.executor = executor != null ? executor : ThreadsHandler.entityExecutor(); 097 entity.godMode = god; 098 entity.passenger = passenger; 099 entity.displayName = displayName; 100 entity.nameVisible = displayName != null; 101 entity.silent = silent; 102 entity.spawn(); 103 } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | 104 InstantiationException e) { 105 TridentLogger.get().error(e); 106 } 107 108 return (T) entity; 109 } 110 111 public <T extends Entity> T build(Class<T> entityType, ParameterValue<?>... parameterValues) { 112 int paramLen = parameterValues.length; 113 Class[] params = new Class[paramLen]; 114 Object[] args = new Object[paramLen]; 115 for (int i = 0; i < paramLen; i++) { 116 ParameterValue<?> value = parameterValues[i]; 117 params[i] = value.clazz(); 118 args[i] = value.value(); 119 } 120 121 TridentEntity entity = null; 122 try { 123 Constructor<? extends TridentEntity> constructor = (Constructor<? extends TridentEntity>) 124 entityType.getDeclaredConstructor(params); 125 constructor.setAccessible(true); 126 entity = constructor.newInstance(args); 127 entity.executor = executor != null ? executor : ThreadsHandler.entityExecutor(); 128 entity.godMode = god; 129 entity.passenger = passenger; 130 entity.displayName = displayName; 131 entity.nameVisible = displayName != null; 132 entity.silent = silent; 133 entity.spawn(); 134 } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | 135 InstantiationException e) { 136 TridentLogger.get().error(e); 137 } 138 139 return (T) entity; 140 } 141 142 /** 143 * Immutable parameter type and object value for dynamic constructor resolvation 144 * 145 * @param <T> the type for the parameter 146 * @author The TridentSDK Team 147 */ 148 public static class ParameterValue<T> { 149 private final Class<T> c; 150 private final T value; 151 152 private ParameterValue(Class<T> c, T value) { 153 this.c = c; 154 this.value = value; 155 } 156 157 /** 158 * Creates a new parameter value 159 * 160 * @param c the class type 161 * @param value the value of the parameter 162 * @param <T> the type 163 * @return the new parameter value 164 */ 165 public static <T> ParameterValue from(Class<T> c, T value) { 166 return new ParameterValue<>(c, value); 167 } 168 169 /** 170 * The class type for this parameter 171 * 172 * @return the parameter class type 173 */ 174 public Class<T> clazz() { 175 return this.c; 176 } 177 178 /** 179 * The argument to be passed in for the parameter 180 * 181 * @return the value passed for the parameter 182 */ 183 public T value() { 184 return this.value; 185 } 186 } 187}