Skip to content

Commit

Permalink
packet/inventory_transaction.go: Symmetrical encode/decode.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sandertv committed Mar 22, 2023
1 parent 4ffd30e commit 6a5b730
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 133 deletions.
58 changes: 58 additions & 0 deletions minecraft/protocol/events.go
Expand Up @@ -46,6 +46,64 @@ type Event struct {
Data EventData
}

// lookupEvent looks up an EventData matching the event type passed. False is
// returned if no such event data exists.
func lookupEvent(eventType int32, x *EventData) bool {
switch eventType {
case EventTypeAchievementAwarded:
*x = &AchievementAwardedEventData{}
case EventTypeEntityInteract:
*x = &EntityInteractEventData{}
case EventTypePortalBuilt:
*x = &PortalBuiltEventData{}
case EventTypePortalUsed:
*x = &PortalUsedEventData{}
case EventTypeMobKilled:
*x = &MobKilledEventData{}
case EventTypeCauldronUsed:
*x = &CauldronUsedEventData{}
case EventTypePlayerDied:
*x = &PlayerDiedEventData{}
case EventTypeBossKilled:
*x = &BossKilledEventData{}
case EventTypeAgentCommand:
*x = &AgentCommandEventData{}
case EventTypePatternRemoved:
*x = &PatternRemovedEventData{}
case EventTypeSlashCommandExecuted:
*x = &SlashCommandExecutedEventData{}
case EventTypeFishBucketed:
*x = &FishBucketedEventData{}
case EventTypeMobBorn:
*x = &MobBornEventData{}
case EventTypePetDied:
*x = &PetDiedEventData{}
case EventTypeCauldronInteract:
*x = &CauldronInteractEventData{}
case EventTypeComposterInteract:
*x = &ComposterInteractEventData{}
case EventTypeBellUsed:
*x = &BellUsedEventData{}
case EventTypeEntityDefinitionTrigger:
*x = &EntityDefinitionTriggerEventData{}
case EventTypeRaidUpdate:
*x = &RaidUpdateEventData{}
case EventTypeMovementAnomaly:
*x = &MovementAnomalyEventData{}
case EventTypeMovementCorrected:
*x = &MovementCorrectedEventData{}
case EventTypeExtractHoney:
*x = &ExtractHoneyEventData{}
case EventTypePlayerWaxedOrUnwaxedCopper:
*x = &WaxedOrUnwaxedCopperEventData{}
case EventTypeSneakCloseToSculkSensor:
*x = &SneakCloseToSculkSensorEventData{}
default:
return false
}
return true
}

// EventData represents an object that holds data specific to an event.
// The data it holds depends on the type.
type EventData interface {
Expand Down
46 changes: 46 additions & 0 deletions minecraft/protocol/inventory.go
Expand Up @@ -54,13 +54,59 @@ func (x *InventoryAction) Marshal(r IO) {
r.ItemInstance(&x.NewItem)
}

const (
InventoryTransactionTypeNormal = iota
InventoryTransactionTypeMismatch
InventoryTransactionTypeUseItem
InventoryTransactionTypeUseItemOnEntity
InventoryTransactionTypeReleaseItem
)

// InventoryTransactionData represents an object that holds data specific to an inventory transaction type.
// The data it holds depends on the type.
type InventoryTransactionData interface {
// Marshal encodes/decodes a serialised inventory transaction data object.
Marshal(r IO)
}

// lookupTransactionData looks up inventory transaction data for the ID passed.
func lookupTransactionData(id uint32, x *InventoryTransactionData) bool {
switch id {
case InventoryTransactionTypeNormal:
*x = &NormalTransactionData{}
case InventoryTransactionTypeMismatch:
*x = &MismatchTransactionData{}
case InventoryTransactionTypeUseItem:
*x = &UseItemTransactionData{}
case InventoryTransactionTypeUseItemOnEntity:
*x = &UseItemOnEntityTransactionData{}
case InventoryTransactionTypeReleaseItem:
*x = &ReleaseItemTransactionData{}
default:
return false
}
return true
}

// lookupTransactionDataType looks up an ID for a specific transaction data.
func lookupTransactionDataType(x InventoryTransactionData, id *uint32) bool {
switch x.(type) {
case *NormalTransactionData:
*id = InventoryTransactionTypeNormal
case *MismatchTransactionData:
*id = InventoryTransactionTypeMismatch
case *UseItemTransactionData:
*id = InventoryTransactionTypeUseItem
case *UseItemOnEntityTransactionData:
*id = InventoryTransactionTypeUseItemOnEntity
case *ReleaseItemTransactionData:
*id = InventoryTransactionTypeReleaseItem
default:
return false
}
return true
}

// NormalTransactionData represents an inventory transaction data object for normal transactions, such as
// crafting. It has no content.
type NormalTransactionData struct{}
Expand Down
1 change: 1 addition & 0 deletions minecraft/protocol/io.go
Expand Up @@ -50,6 +50,7 @@ type IO interface {
MaterialReducer(x *MaterialReducer)
Recipe(x *Recipe)
Event(x *Event)
TransactionDataType(x *InventoryTransactionData)
GameRule(x *GameRule)
AbilityValue(x *any)

Expand Down
44 changes: 6 additions & 38 deletions minecraft/protocol/packet/inventory_transaction.go
Expand Up @@ -47,52 +47,20 @@ func (*InventoryTransaction) ID() uint32 {

// Marshal ...
func (pk *InventoryTransaction) Marshal(w *protocol.Writer) {
w.Varint32(&pk.LegacyRequestID)
if pk.LegacyRequestID != 0 {
protocol.Slice(w, &pk.LegacySetItemSlots)
}
var id uint32
switch pk.TransactionData.(type) {
case nil, *protocol.NormalTransactionData:
id = InventoryTransactionTypeNormal
case *protocol.MismatchTransactionData:
id = InventoryTransactionTypeMismatch
case *protocol.UseItemTransactionData:
id = InventoryTransactionTypeUseItem
case *protocol.UseItemOnEntityTransactionData:
id = InventoryTransactionTypeUseItemOnEntity
case *protocol.ReleaseItemTransactionData:
id = InventoryTransactionTypeReleaseItem
}
w.Varuint32(&id)
protocol.Slice(w, &pk.Actions)
if pk.TransactionData != nil {
pk.TransactionData.Marshal(w)
}
pk.marshal(w)
}

// Unmarshal ...
func (pk *InventoryTransaction) Unmarshal(r *protocol.Reader) {
pk.marshal(r)
}

func (pk *InventoryTransaction) marshal(r protocol.IO) {
r.Varint32(&pk.LegacyRequestID)
if pk.LegacyRequestID != 0 {
protocol.Slice(r, &pk.LegacySetItemSlots)
}
var transactionType uint32
r.Varuint32(&transactionType)
r.TransactionDataType(&pk.TransactionData)
protocol.Slice(r, &pk.Actions)
switch transactionType {
case InventoryTransactionTypeNormal:
pk.TransactionData = &protocol.NormalTransactionData{}
case InventoryTransactionTypeMismatch:
pk.TransactionData = &protocol.MismatchTransactionData{}
case InventoryTransactionTypeUseItem:
pk.TransactionData = &protocol.UseItemTransactionData{}
case InventoryTransactionTypeUseItemOnEntity:
pk.TransactionData = &protocol.UseItemOnEntityTransactionData{}
case InventoryTransactionTypeReleaseItem:
pk.TransactionData = &protocol.ReleaseItemTransactionData{}
default:
r.UnknownEnumOption(transactionType, "inventory transaction type")
}
pk.TransactionData.Marshal(r)
}
90 changes: 17 additions & 73 deletions minecraft/protocol/reader.go
Expand Up @@ -467,29 +467,12 @@ func (r *Reader) MaterialReducer(m *MaterialReducer) {

// Recipe reads a Recipe from the reader.
func (r *Reader) Recipe(x *Recipe) {
var recipeType int32
var (
recipeType int32
recipe Recipe
)
r.Varint32(&recipeType)

switch recipeType {
case RecipeShapeless:
*x = &ShapelessRecipe{}
case RecipeShaped:
*x = &ShapedRecipe{}
case RecipeFurnace:
*x = &FurnaceRecipe{}
case RecipeFurnaceData:
*x = &FurnaceDataRecipe{}
case RecipeMulti:
*x = &MultiRecipe{}
case RecipeShulkerBox:
*x = &ShulkerBoxRecipe{}
case RecipeShapelessChemistry:
*x = &ShapelessChemistryRecipe{}
case RecipeShapedChemistry:
*x = &ShapedChemistryRecipe{}
case RecipeSmithingTransform:
*x = &SmithingTransformRecipe{}
default:
if !lookupRecipe(recipeType, &recipe) {
r.UnknownEnumOption(recipeType, "crafting data recipe type")
return
}
Expand All @@ -500,61 +483,22 @@ func (r *Reader) Recipe(x *Recipe) {
func (r *Reader) Event(x *Event) {
r.Varint32(&x.Type)
r.Uint8(&x.UsePlayerID)

switch x.Type {
case EventTypeAchievementAwarded:
x.Data = &AchievementAwardedEventData{}
case EventTypeEntityInteract:
x.Data = &EntityInteractEventData{}
case EventTypePortalBuilt:
x.Data = &PortalBuiltEventData{}
case EventTypePortalUsed:
x.Data = &PortalUsedEventData{}
case EventTypeMobKilled:
x.Data = &MobKilledEventData{}
case EventTypeCauldronUsed:
x.Data = &CauldronUsedEventData{}
case EventTypePlayerDied:
x.Data = &PlayerDiedEventData{}
case EventTypeBossKilled:
x.Data = &BossKilledEventData{}
case EventTypeAgentCommand:
x.Data = &AgentCommandEventData{}
case EventTypePatternRemoved:
x.Data = &PatternRemovedEventData{}
case EventTypeSlashCommandExecuted:
x.Data = &SlashCommandExecutedEventData{}
case EventTypeFishBucketed:
x.Data = &FishBucketedEventData{}
case EventTypeMobBorn:
x.Data = &MobBornEventData{}
case EventTypePetDied:
x.Data = &PetDiedEventData{}
case EventTypeCauldronInteract:
x.Data = &CauldronInteractEventData{}
case EventTypeComposterInteract:
x.Data = &ComposterInteractEventData{}
case EventTypeBellUsed:
x.Data = &BellUsedEventData{}
case EventTypeEntityDefinitionTrigger:
x.Data = &EntityDefinitionTriggerEventData{}
case EventTypeRaidUpdate:
x.Data = &RaidUpdateEventData{}
case EventTypeMovementAnomaly:
x.Data = &MovementAnomalyEventData{}
case EventTypeMovementCorrected:
x.Data = &MovementCorrectedEventData{}
case EventTypeExtractHoney:
x.Data = &ExtractHoneyEventData{}
case EventTypePlayerWaxedOrUnwaxedCopper:
x.Data = &WaxedOrUnwaxedCopperEventData{}
case EventTypeSneakCloseToSculkSensor:
x.Data = &SneakCloseToSculkSensorEventData{}
if !lookupEvent(x.Type, &x.Data) {
r.UnknownEnumOption(x.Type, "event packet event type")
return
}

x.Data.Marshal(r)
}

// TransactionDataType reads an InventoryTransactionData type from the reader.
func (r *Reader) TransactionDataType(x *InventoryTransactionData) {
var transactionType uint32
r.Varuint32(&transactionType)
if !lookupTransactionData(transactionType, x) {
r.UnknownEnumOption(transactionType, "inventory transaction data type")
}
}

// AbilityValue reads an ability value from the reader.
func (r *Reader) AbilityValue(x *any) {
valType, boolVal, floatVal := uint8(0), false, float32(0)
Expand Down
56 changes: 56 additions & 0 deletions minecraft/protocol/recipe.go
Expand Up @@ -77,6 +77,62 @@ type Recipe interface {
Unmarshal(r *Reader)
}

// lookupRecipe looks up the Recipe for a recipe type. False is returned if not
// found.
func lookupRecipe(recipeType int32, x *Recipe) bool {
switch recipeType {
case RecipeShapeless:
*x = &ShapelessRecipe{}
case RecipeShaped:
*x = &ShapedRecipe{}
case RecipeFurnace:
*x = &FurnaceRecipe{}
case RecipeFurnaceData:
*x = &FurnaceDataRecipe{}
case RecipeMulti:
*x = &MultiRecipe{}
case RecipeShulkerBox:
*x = &ShulkerBoxRecipe{}
case RecipeShapelessChemistry:
*x = &ShapelessChemistryRecipe{}
case RecipeShapedChemistry:
*x = &ShapedChemistryRecipe{}
case RecipeSmithingTransform:
*x = &SmithingTransformRecipe{}
default:
return false
}
return true
}

// lookupRecipeType looks up the recipe type for a Recipe. False is returned if
// none was found.
func lookupRecipeType(x Recipe, recipeType *int32) bool {
switch x.(type) {
case *ShapelessRecipe:
*recipeType = RecipeShapeless
case *ShapedRecipe:
*recipeType = RecipeShaped
case *FurnaceRecipe:
*recipeType = RecipeFurnace
case *FurnaceDataRecipe:
*recipeType = RecipeFurnaceData
case *MultiRecipe:
*recipeType = RecipeMulti
case *ShulkerBoxRecipe:
*recipeType = RecipeShulkerBox
case *ShapelessChemistryRecipe:
*recipeType = RecipeShapelessChemistry
case *ShapedChemistryRecipe:
*recipeType = RecipeShapedChemistry
case *SmithingTransformRecipe:
*recipeType = RecipeSmithingTransform
default:
return false
}
return true
}

// ShapelessRecipe is a recipe that has no particular shape. Its functionality is shared with the
// RecipeShulkerBox and RecipeShapelessChemistry types.
type ShapelessRecipe struct {
Expand Down

0 comments on commit 6a5b730

Please sign in to comment.