Useful patch for goodtype sorting

This commit is contained in:
Michael Wain 2025-03-05 18:32:47 +03:00
parent 27a7cbd2d3
commit 97233286aa
10 changed files with 96 additions and 52 deletions

View File

@ -1,6 +1,10 @@
<p align="center">Feels like a distant memory</p>
# WhimsyWorld
![Gitea Last Commit](https://img.shields.io/gitea/last-commit/alterwain/WhimsyWorld?gitea_url=https%3A%2F%2Fgitea.awain.net)
![Jenkins Build](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.awain.net%2Fjob%2FWhimsyWorld&link=https%3A%2F%2Fjenkins.awain.net%2Fjob%2FWhimsyWorld)
![Contact](https://img.shields.io/badge/xmpp-alterwain-red?link=xmpp%3Aalterwain%40awain.net%3Fomemo-sid-687809972%3Dfc938d0c120affd1f011a1f1e53449b8b773ac7c322667f1dca2b2539987b86c)
An unofficial server for semi-famous game Rolypolyland (Shararam). Remake by alterwain. Original by cl0zzzy (also me, but in 2018).
## Caution

View File

@ -345,7 +345,7 @@ public class GameServer {
List<Triplet<Long, Object, AvatarInventoryType>> l = Stream.concat(
bodyParts.stream().map(f -> (Map<String, AMFObject>) f.getValue()).map(f -> Triplet.with(((Number) f.get("Id").getValue()).longValue(), f.get("Color").getValue(), AvatarInventoryType.BodyParts)),
inventory.stream().map(f -> (Map<String, AMFObject>) f.getValue()).map(f -> Triplet.with(((Number) f.get("Id").getValue()).longValue(), f.get("Color").getValue(), AvatarInventoryType.Clothes))
inventory.stream().map(f -> (Map<String, AMFObject>) f.getValue()).map(f -> Triplet.with(((Number) f.get("Id").getValue()).longValue(), f.get("Color").getValue(), AvatarInventoryType.fromGoodId(goodsService, ((Number) f.get("Id").getValue()).longValue())))
).collect(Collectors.toList());
users.resetUsedClothes(playerId);

View File

@ -1,42 +1,58 @@
package com.alterdekim.game.component.game;
import com.alterdekim.game.entity.Good;
import com.alterdekim.game.service.GoodsService;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Getter
public enum AvatarInventoryType {
Clothes(List.of(1, 4, 14, 32, 36, 40)),
Magic(Collections.singletonList(64)),
Backgrounds(Collections.singletonList(41)),
Phones(Collections.emptyList()),
Smile(Collections.emptyList()),
House(Collections.singletonList(34)),
HouseFurniture(Collections.singletonList(20)),
Club(Collections.singletonList(58)),
ClubFacade(Collections.singletonList(63)),
ClubShow(Collections.singletonList(78)),
ClubFurniture(Collections.singletonList(59)),
ClubInstruments(Collections.singletonList(105)),
ClubDigitalStuff(Collections.singletonList(68)),
ClubFloor(Collections.singletonList(61)),
ClubWallpaper(Collections.singletonList(62)),
ClubGames(Collections.singletonList(107)),
ClubFood(Collections.singletonList(67)),
ClubBeverages(Collections.singletonList(66)),
ClubDeserts(Collections.singletonList(65)),
Achievements(Collections.emptyList()),
BodyParts(Collections.emptyList());
Clothes_(1),
Caps(4),
Glasses(14),
Boots(32),
Bangles(36),
Suits(40),
Magic(64),
Backgrounds(41),
Phones(-4),
Smile(-5),
House(34),
HouseFurniture(20),
Club(58),
ClubFacade(63),
ClubShow(78),
ClubFurniture(59),
ClubInstruments(105),
ClubDigitalStuff(68),
ClubFloor(61),
ClubWallpaper(62),
ClubGames(107),
ClubFood(67),
ClubBeverages(66),
ClubDeserts(65),
Achievements(-1),
BodyParts(-2),
Unknown(-3);
private final List<Integer> goodTypes;
private final Integer goodType;
public static AvatarInventoryType fromGoodType(int goodType) {
for( AvatarInventoryType t : values() ) {
for( Integer gt : t.goodTypes ) {
if( goodType == gt) return t;
if( goodType == t.goodType ) return t;
}
return Unknown;
}
return Clothes;
public static AvatarInventoryType fromGoodId(GoodsService goodsService, long goodId) {
Integer goodType = goodsService.findById(goodId).map(Good::getGoodTypeId).orElse(-3);
return fromGoodType(goodType);
}
}

View File

@ -1,19 +1,20 @@
package com.alterdekim.game.component.game.avatar;
import com.alterdekim.game.component.game.AvatarInventoryType;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum GoodClothType {
Clothes(1, 212, 36, 120),
Caps(4, 211, 45, 21),
Glasses(14, 210, 31, 62),
Boots(32, 213, 11, 123),
Bangles(36, 214, 56, 24),
Suits(40, 429, 27, 697);
Clothes(AvatarInventoryType.Clothes_, 212, 36, 120),
Caps(AvatarInventoryType.Caps, 211, 45, 21),
Glasses(AvatarInventoryType.Glasses, 210, 31, 62),
Boots(AvatarInventoryType.Boots, 213, 11, 123),
Bangles(AvatarInventoryType.Bangles, 214, 56, 24),
Suits(AvatarInventoryType.Suits, 429, 27, 697);
private final int val;
private final AvatarInventoryType val;
private final long tabMediaResourceId;
private final int layerId;
private final int textResourceId;

View File

@ -9,6 +9,7 @@ import com.alterdekim.game.entity.User;
import com.alterdekim.game.repository.UserRepository;
import com.alterdekim.game.security.AuthenticationUtil;
import com.alterdekim.game.service.AvatarInventoryService;
import com.alterdekim.game.service.GoodsService;
import com.alterdekim.game.service.IncompatibleService;
import com.alterdekim.game.service.UserService;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
@ -30,6 +31,8 @@ import java.util.Base64;
import java.util.List;
import java.util.Optional;
import static com.alterdekim.game.utils.GameUtils.EmptyGoodId;
@Slf4j
@Controller
public class SignUpController {
@ -46,6 +49,9 @@ public class SignUpController {
@Autowired
private UserService userService;
@Autowired
private GoodsService goodsService;
@PostMapping("/ConstructorACHandler.ashx")
public ResponseEntity<String> avatarController() {
@ -105,13 +111,13 @@ public class SignUpController {
try {
av.getInventory()
.stream()
.filter(i -> i.getID() != 98)
.map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.Clothes, 0))
.filter(i -> i.getID() != EmptyGoodId.intValue())
.map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.fromGoodId(goodsService, i.getID()), 0))
.forEach(i -> avatarInventoryService.addGoodToInventory(i));
av.getBodyParts()
.stream()
.filter(i -> i.getID() != 98)
.filter(i -> i.getID() != EmptyGoodId.intValue())
.map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.BodyParts, i.getColor() == null ? 0 : i.getColor()))
.forEach(i -> avatarInventoryService.addGoodToInventory(i));
} catch (Exception e) {

View File

@ -27,8 +27,8 @@ public class AMFSerializer {
if( obj == null ) return new ArrayList<>(Collections.singletonList((byte) 0x05));
return switch (obj.getClass().getSimpleName()) {
case "String" -> serializeString((String) obj);
case "Integer", "Double", "Float", "Long", "Short", "Byte" -> serializeNumber(((java.lang.Number) obj).doubleValue());
case "Boolean" -> serializeBoolean((Boolean) obj);
case "Integer", "int", "Double", "double", "Float", "float", "Long", "long", "Short", "short", "Byte", "byte" -> serializeNumber(((java.lang.Number) obj).doubleValue());
case "Boolean", "boolean" -> serializeBoolean((Boolean) obj);
case "Map", "HashMap" -> serializeMap((Map<?, ?>) obj);
case "List", "ArrayList" -> serializeArray((List<?>) obj);
default -> isStream ? serializeJavaObjectAsStream(obj) : serializeJavaObjectAsKeyVal(obj);

View File

@ -61,7 +61,7 @@ public interface AvatarInventoryRepository extends JpaRepository<AvatarInventory
FROM avatar_inventory AS a
JOIN goods AS g
ON a.good_id = g.id
WHERE a.user_id = :uid AND a.type = 'Clothes' AND g.good_type_id = :#{#goodTypeId.getVal()}""", nativeQuery = true)
WHERE a.user_id = :uid AND a.type = :#{#goodTypeId.getVal().name()}""", nativeQuery = true)
List<InventoryItem> findInventoryItems(@Param("uid") Long userId, @Param("goodTypeId") GoodClothType goodClothType);
@Query(value = """
@ -130,9 +130,9 @@ public interface AvatarInventoryRepository extends JpaRepository<AvatarInventory
g.layer_id AS layerId,
g.good_type_id AS goodTypeId
FROM goods g
JOIN (SELECT a.good_id FROM avatar_inventory a WHERE a.user_id = :uid AND a.`type` = 'Clothes' AND a.is_used = true) AS a
JOIN (SELECT a.good_id FROM avatar_inventory a WHERE a.user_id = :uid AND a.`type` = :#{#goodTypeId.getVal().name()} AND a.is_used = true) AS a
ON a.good_id = g.id""", nativeQuery = true)
List<IBodyAvatarItem> findUsedClothesByUserId(@Param("uid") Long userId);
List<IBodyAvatarItem> findUsedClothesByUserId(@Param("uid") Long userId, @Param("goodTypeId") GoodClothType goodClothType);
@Query(value = """

View File

@ -20,6 +20,9 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.alterdekim.game.utils.GameUtils.EmptyGoodId;
import static com.alterdekim.game.utils.GameUtils.EmptyMRId;
@Slf4j
@Service
public class AvatarInventoryService {
@ -85,7 +88,7 @@ public class AvatarInventoryService {
addEmpty ? Stream.of(bodyPartRepository.findInventoryItems(userId, type), Collections.singletonList(new InventoryItem() {
@Override
public Long getId() {
return 98L;
return EmptyGoodId;
}
@Override
@ -95,12 +98,12 @@ public class AvatarInventoryService {
@Override
public Long getBodyPartId() {
return 98L;
return EmptyGoodId;
}
@Override
public Integer getMediaResourceId() {
return 98;
return EmptyMRId;
}
@Override
@ -148,7 +151,7 @@ public class AvatarInventoryService {
public InventoryGroup getClothInventoryGroup(Long userId, GoodClothType type) {
return new InventoryGroup(
type.getVal(),
type.getVal().getGoodType(),
type.getTextResourceId(),
false,
0,
@ -158,7 +161,13 @@ public class AvatarInventoryService {
}
public List<IBodyAvatarItem> getWholeAvatarByUserId(Long userId) {
return Stream.of(this.inventoryRepository.findUsedBodyPartsByUserId(userId), this.inventoryRepository.findUsedClothesByUserId(userId))
return Stream.of(this.inventoryRepository.findUsedBodyPartsByUserId(userId),
this.inventoryRepository.findUsedClothesByUserId(userId, GoodClothType.Clothes),
this.inventoryRepository.findUsedClothesByUserId(userId, GoodClothType.Caps),
this.inventoryRepository.findUsedClothesByUserId(userId, GoodClothType.Glasses),
this.inventoryRepository.findUsedClothesByUserId(userId, GoodClothType.Bangles),
this.inventoryRepository.findUsedClothesByUserId(userId, GoodClothType.Boots),
this.inventoryRepository.findUsedClothesByUserId(userId, GoodClothType.Suits))
.flatMap(List::stream).collect(Collectors.toList());
}
@ -245,7 +254,7 @@ public class AvatarInventoryService {
isShape ? this.getAvatarBodyPartsByType(type) : Stream.of(
this.getAvatarBodyPartsByType(type),
Collections.singletonList(
new AvatarBodyPart(98, 0, true, this.resourceService.getUrlByMediaResourceId(98L).get())
new AvatarBodyPart(EmptyGoodId.intValue(), 0, true, this.resourceService.getUrlByMediaResourceId(EmptyMRId.longValue()).get())
)
)
.flatMap(Collection::stream)
@ -265,7 +274,7 @@ public class AvatarInventoryService {
}
private List<AvatarBodyPart> getRandomStuffByGoodType(GoodClothType type) {
List<Good> g = this.goodRepository.findByGoodTypeId(type.getVal());
List<Good> g = this.goodRepository.findByGoodTypeId(type.getVal().getGoodType());
int l = (int) Math.round(Math.random() * (g.size() - 4));
return g.subList(l, l+3)
.stream()
@ -284,14 +293,14 @@ public class AvatarInventoryService {
for( GoodClothType type : GoodClothType.values() ) {
groups.add(
new AvatarBodyPartGroup(
type.getVal(),
type.getVal().getGoodType(),
type.name(),
resourceService.getUrlByMediaResourceId(type.getTabMediaResourceId()).get(),
type.getLayerId(),
Stream.of(
this.getRandomStuffByGoodType(type),
Collections.singletonList(
new AvatarBodyPart(98, 0, true, this.resourceService.getUrlByMediaResourceId(98L).get())
new AvatarBodyPart(EmptyGoodId.intValue(), 0, true, this.resourceService.getUrlByMediaResourceId(EmptyMRId.longValue()).get())
)
)
.flatMap(Collection::stream)

View File

@ -198,7 +198,12 @@ public class UserService {
public void resetUsedClothes(Long userId) {
this.inventoryService.resetUsed(userId, AvatarInventoryType.BodyParts);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Clothes);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Clothes_);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Caps);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Glasses);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Suits);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Bangles);
this.inventoryService.resetUsed(userId, AvatarInventoryType.Boots);
}
public UserPhone getUserPhoneByUserId(Long userId) {

View File

@ -1,6 +1,9 @@
package com.alterdekim.game.utils;
public class GameUtils {
public static final Long EmptyGoodId = 360L;
public static final Integer EmptyMRId = 98;
public static int extractLocationId(String s) {
String[] r = s.split("\\$");
if( r.length < 3) return 0;