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> <p align="center">Feels like a distant memory</p>
# WhimsyWorld # 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). An unofficial server for semi-famous game Rolypolyland (Shararam). Remake by alterwain. Original by cl0zzzy (also me, but in 2018).
## Caution ## Caution

View File

@ -345,7 +345,7 @@ public class GameServer {
List<Triplet<Long, Object, AvatarInventoryType>> l = Stream.concat( 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)), 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()); ).collect(Collectors.toList());
users.resetUsedClothes(playerId); users.resetUsedClothes(playerId);

View File

@ -1,42 +1,58 @@
package com.alterdekim.game.component.game; 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.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter
public enum AvatarInventoryType { public enum AvatarInventoryType {
Clothes(List.of(1, 4, 14, 32, 36, 40)), Clothes_(1),
Magic(Collections.singletonList(64)), Caps(4),
Backgrounds(Collections.singletonList(41)), Glasses(14),
Phones(Collections.emptyList()), Boots(32),
Smile(Collections.emptyList()), Bangles(36),
House(Collections.singletonList(34)), Suits(40),
HouseFurniture(Collections.singletonList(20)), Magic(64),
Club(Collections.singletonList(58)), Backgrounds(41),
ClubFacade(Collections.singletonList(63)), Phones(-4),
ClubShow(Collections.singletonList(78)), Smile(-5),
ClubFurniture(Collections.singletonList(59)), House(34),
ClubInstruments(Collections.singletonList(105)), HouseFurniture(20),
ClubDigitalStuff(Collections.singletonList(68)), Club(58),
ClubFloor(Collections.singletonList(61)), ClubFacade(63),
ClubWallpaper(Collections.singletonList(62)), ClubShow(78),
ClubGames(Collections.singletonList(107)), ClubFurniture(59),
ClubFood(Collections.singletonList(67)), ClubInstruments(105),
ClubBeverages(Collections.singletonList(66)), ClubDigitalStuff(68),
ClubDeserts(Collections.singletonList(65)), ClubFloor(61),
Achievements(Collections.emptyList()), ClubWallpaper(62),
BodyParts(Collections.emptyList()); 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) { public static AvatarInventoryType fromGoodType(int goodType) {
for( AvatarInventoryType t : values() ) { for( AvatarInventoryType t : values() ) {
for( Integer gt : t.goodTypes ) { if( goodType == t.goodType ) return t;
if( goodType == gt) 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; package com.alterdekim.game.component.game.avatar;
import com.alterdekim.game.component.game.AvatarInventoryType;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum GoodClothType { public enum GoodClothType {
Clothes(1, 212, 36, 120), Clothes(AvatarInventoryType.Clothes_, 212, 36, 120),
Caps(4, 211, 45, 21), Caps(AvatarInventoryType.Caps, 211, 45, 21),
Glasses(14, 210, 31, 62), Glasses(AvatarInventoryType.Glasses, 210, 31, 62),
Boots(32, 213, 11, 123), Boots(AvatarInventoryType.Boots, 213, 11, 123),
Bangles(36, 214, 56, 24), Bangles(AvatarInventoryType.Bangles, 214, 56, 24),
Suits(40, 429, 27, 697); Suits(AvatarInventoryType.Suits, 429, 27, 697);
private final int val; private final AvatarInventoryType val;
private final long tabMediaResourceId; private final long tabMediaResourceId;
private final int layerId; private final int layerId;
private final int textResourceId; 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.repository.UserRepository;
import com.alterdekim.game.security.AuthenticationUtil; import com.alterdekim.game.security.AuthenticationUtil;
import com.alterdekim.game.service.AvatarInventoryService; import com.alterdekim.game.service.AvatarInventoryService;
import com.alterdekim.game.service.GoodsService;
import com.alterdekim.game.service.IncompatibleService; import com.alterdekim.game.service.IncompatibleService;
import com.alterdekim.game.service.UserService; import com.alterdekim.game.service.UserService;
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect;
@ -30,6 +31,8 @@ import java.util.Base64;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import static com.alterdekim.game.utils.GameUtils.EmptyGoodId;
@Slf4j @Slf4j
@Controller @Controller
public class SignUpController { public class SignUpController {
@ -46,6 +49,9 @@ public class SignUpController {
@Autowired @Autowired
private UserService userService; private UserService userService;
@Autowired
private GoodsService goodsService;
@PostMapping("/ConstructorACHandler.ashx") @PostMapping("/ConstructorACHandler.ashx")
public ResponseEntity<String> avatarController() { public ResponseEntity<String> avatarController() {
@ -105,13 +111,13 @@ public class SignUpController {
try { try {
av.getInventory() av.getInventory()
.stream() .stream()
.filter(i -> i.getID() != 98) .filter(i -> i.getID() != EmptyGoodId.intValue())
.map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.Clothes, 0)) .map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.fromGoodId(goodsService, i.getID()), 0))
.forEach(i -> avatarInventoryService.addGoodToInventory(i)); .forEach(i -> avatarInventoryService.addGoodToInventory(i));
av.getBodyParts() av.getBodyParts()
.stream() .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())) .map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.BodyParts, i.getColor() == null ? 0 : i.getColor()))
.forEach(i -> avatarInventoryService.addGoodToInventory(i)); .forEach(i -> avatarInventoryService.addGoodToInventory(i));
} catch (Exception e) { } catch (Exception e) {

View File

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

View File

@ -61,7 +61,7 @@ public interface AvatarInventoryRepository extends JpaRepository<AvatarInventory
FROM avatar_inventory AS a FROM avatar_inventory AS a
JOIN goods AS g JOIN goods AS g
ON a.good_id = g.id 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); List<InventoryItem> findInventoryItems(@Param("uid") Long userId, @Param("goodTypeId") GoodClothType goodClothType);
@Query(value = """ @Query(value = """
@ -130,9 +130,9 @@ public interface AvatarInventoryRepository extends JpaRepository<AvatarInventory
g.layer_id AS layerId, g.layer_id AS layerId,
g.good_type_id AS goodTypeId g.good_type_id AS goodTypeId
FROM goods g 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) 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 = """ @Query(value = """

View File

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

View File

@ -198,7 +198,12 @@ public class UserService {
public void resetUsedClothes(Long userId) { public void resetUsedClothes(Long userId) {
this.inventoryService.resetUsed(userId, AvatarInventoryType.BodyParts); 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) { public UserPhone getUserPhoneByUserId(Long userId) {

View File

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