2021-11-18 03:02:38 +00:00
/ *
* Copyright ( c ) 2019 - 2021 GeyserMC . http : //geysermc.org
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*
* @author GeyserMC
* @link https : //github.com/GeyserMC/Geyser
* /
2021-11-20 21:34:30 +00:00
package org.geysermc.geyser.entity ;
2021-11-18 03:02:38 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata ;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType ;
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType ;
import it.unimi.dsi.fastutil.objects.ObjectArrayList ;
import lombok.Setter ;
import lombok.experimental.Accessors ;
2021-11-20 21:34:30 +00:00
import org.geysermc.geyser.GeyserImpl ;
import org.geysermc.geyser.entity.factory.EntityFactory ;
2021-11-20 23:29:46 +00:00
import org.geysermc.geyser.entity.type.Entity ;
2021-11-20 21:34:30 +00:00
import org.geysermc.geyser.registry.Registries ;
2021-11-20 23:29:46 +00:00
import org.geysermc.geyser.translator.entity.EntityMetadataTranslator ;
2021-11-18 03:02:38 +00:00
import java.util.List ;
import java.util.Locale ;
import java.util.function.BiConsumer ;
/ * *
* Represents data for an entity . This includes properties such as height and width , as well as the list of entity
* metadata translators needed to translate the properties sent from the server . The translators are structured in such
* a way that inserting a new one ( for example in version updates ) is convenient .
*
* @param < T > the entity type this definition represents
* /
2021-11-19 01:44:03 +00:00
public record EntityDefinition < T extends Entity > ( EntityFactory < T > factory , EntityType entityType , String identifier ,
2021-11-20 19:25:21 +00:00
float width , float height , float offset , List < EntityMetadataTranslator < ? super T , ? , ? > > translators ) {
2021-11-18 03:02:38 +00:00
public static < T extends Entity > Builder < T > inherited ( EntityFactory < T > factory , EntityDefinition < ? super T > parent ) {
2021-11-19 01:44:03 +00:00
return new Builder < > ( factory , parent . entityType , parent . identifier , parent . width , parent . height , parent . offset , new ObjectArrayList < > ( parent . translators ) ) ;
2021-11-18 03:02:38 +00:00
}
public static < T extends Entity > Builder < T > builder ( EntityFactory < T > factory ) {
return new Builder < > ( factory ) ;
}
2021-11-20 19:25:21 +00:00
public < M > void translateMetadata ( T entity , EntityMetadata < M , ? extends MetadataType < M > > metadata ) {
EntityMetadataTranslator < ? super T , M , EntityMetadata < M , ? extends MetadataType < M > > > translator = ( EntityMetadataTranslator < ? super T , M , EntityMetadata < M , ? extends MetadataType < M > > > ) this . translators . get ( metadata . getId ( ) ) ;
if ( translator = = null ) {
// This can safely happen; it means we don't translate this entity metadata
return ;
}
if ( translator . acceptedType ( ) ! = metadata . getType ( ) ) {
2021-11-20 21:34:30 +00:00
GeyserImpl . getInstance ( ) . getLogger ( ) . warning ( " Metadata ID " + metadata . getId ( ) + " was received with type " + metadata . getType ( ) + " but we expected " + translator . acceptedType ( ) + " for " + entity . getDefinition ( ) . entityType ( ) ) ;
if ( GeyserImpl . getInstance ( ) . getConfig ( ) . isDebugMode ( ) ) {
GeyserImpl . getInstance ( ) . getLogger ( ) . debug ( metadata . toString ( ) ) ;
2021-11-20 19:25:21 +00:00
}
return ;
}
2021-11-20 23:29:46 +00:00
translator . translate ( entity , metadata ) ;
2021-11-20 19:25:21 +00:00
}
2021-11-18 03:02:38 +00:00
@Setter
@Accessors ( fluent = true , chain = true )
public static class Builder < T extends Entity > {
private final EntityFactory < T > factory ;
private EntityType type ;
private String identifier ;
private float width ;
private float height ;
2021-12-03 00:56:12 +00:00
private float offset = 0 . 00001f ;
2021-11-20 19:25:21 +00:00
private final List < EntityMetadataTranslator < ? super T , ? , ? > > translators ;
2021-11-18 03:02:38 +00:00
private Builder ( EntityFactory < T > factory ) {
this . factory = factory ;
translators = new ObjectArrayList < > ( ) ;
}
2021-11-20 19:25:21 +00:00
public Builder ( EntityFactory < T > factory , EntityType type , String identifier , float width , float height , float offset , List < EntityMetadataTranslator < ? super T , ? , ? > > translators ) {
2021-11-18 03:02:38 +00:00
this . factory = factory ;
this . type = type ;
this . identifier = identifier ;
this . width = width ;
this . height = height ;
this . offset = offset ;
this . translators = translators ;
}
/ * *
* Sets the height and width as one value
* /
public Builder < T > heightAndWidth ( float value ) {
height = value ;
width = value ;
return this ;
}
2021-12-03 00:56:12 +00:00
public Builder < T > offset ( float offset ) {
this . offset = offset + 0 . 00001f ;
return this ;
}
2021-11-18 03:02:38 +00:00
/ * *
* Resets the identifier as well
* /
public Builder < T > type ( EntityType type ) {
this . type = type ;
identifier = null ;
return this ;
}
2021-11-20 19:25:21 +00:00
public < U , EM extends EntityMetadata < U , ? extends MetadataType < U > > > Builder < T > addTranslator ( MetadataType < U > type , BiConsumer < T , EM > translateFunction ) {
2021-11-18 03:02:38 +00:00
translators . add ( new EntityMetadataTranslator < > ( type , translateFunction ) ) ;
return this ;
}
2021-11-20 19:25:21 +00:00
public Builder < T > addTranslator ( EntityMetadataTranslator < T , ? , ? > translator ) {
2021-11-18 03:02:38 +00:00
translators . add ( translator ) ;
return this ;
}
public EntityDefinition < T > build ( ) {
return build ( true ) ;
}
/ * *
* @param register whether to register this entity in the Registries for entity types . Generally this should be
* set to false if we ' re not expecting this entity to spawn from the network .
* /
public EntityDefinition < T > build ( boolean register ) {
if ( identifier = = null & & type ! = null ) {
identifier = " minecraft: " + type . name ( ) . toLowerCase ( Locale . ROOT ) ;
}
2021-11-19 01:44:03 +00:00
EntityDefinition < T > definition = new EntityDefinition < > ( factory , type , identifier , width , height , offset , translators ) ;
2021-11-18 03:02:38 +00:00
if ( register & & definition . entityType ( ) ! = null ) {
Registries . ENTITY_DEFINITIONS . get ( ) . putIfAbsent ( definition . entityType ( ) , definition ) ;
2021-11-19 01:44:03 +00:00
Registries . JAVA_ENTITY_IDENTIFIERS . get ( ) . putIfAbsent ( " minecraft: " + type . name ( ) . toLowerCase ( Locale . ROOT ) , definition ) ;
2021-11-18 03:02:38 +00:00
}
return definition ;
}
}
}